github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/exchange/bitswap/testnet/virtual.go (about)

     1  package bitswap
     2  
     3  import (
     4  	"errors"
     5  
     6  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
     7  	key "github.com/ipfs/go-ipfs/blocks/key"
     8  	bsmsg "github.com/ipfs/go-ipfs/exchange/bitswap/message"
     9  	bsnet "github.com/ipfs/go-ipfs/exchange/bitswap/network"
    10  	peer "github.com/ipfs/go-ipfs/p2p/peer"
    11  	routing "github.com/ipfs/go-ipfs/routing"
    12  	mockrouting "github.com/ipfs/go-ipfs/routing/mock"
    13  	delay "github.com/ipfs/go-ipfs/thirdparty/delay"
    14  	testutil "github.com/ipfs/go-ipfs/util/testutil"
    15  )
    16  
    17  func VirtualNetwork(rs mockrouting.Server, d delay.D) Network {
    18  	return &network{
    19  		clients:       make(map[peer.ID]bsnet.Receiver),
    20  		delay:         d,
    21  		routingserver: rs,
    22  	}
    23  }
    24  
    25  type network struct {
    26  	clients       map[peer.ID]bsnet.Receiver
    27  	routingserver mockrouting.Server
    28  	delay         delay.D
    29  }
    30  
    31  func (n *network) Adapter(p testutil.Identity) bsnet.BitSwapNetwork {
    32  	client := &networkClient{
    33  		local:   p.ID(),
    34  		network: n,
    35  		routing: n.routingserver.Client(p),
    36  	}
    37  	n.clients[p.ID()] = client
    38  	return client
    39  }
    40  
    41  func (n *network) HasPeer(p peer.ID) bool {
    42  	_, found := n.clients[p]
    43  	return found
    44  }
    45  
    46  // TODO should this be completely asynchronous?
    47  // TODO what does the network layer do with errors received from services?
    48  func (n *network) SendMessage(
    49  	ctx context.Context,
    50  	from peer.ID,
    51  	to peer.ID,
    52  	message bsmsg.BitSwapMessage) error {
    53  
    54  	receiver, ok := n.clients[to]
    55  	if !ok {
    56  		return errors.New("Cannot locate peer on network")
    57  	}
    58  
    59  	// nb: terminate the context since the context wouldn't actually be passed
    60  	// over the network in a real scenario
    61  
    62  	go n.deliver(receiver, from, message)
    63  
    64  	return nil
    65  }
    66  
    67  func (n *network) deliver(
    68  	r bsnet.Receiver, from peer.ID, message bsmsg.BitSwapMessage) error {
    69  	if message == nil || from == "" {
    70  		return errors.New("Invalid input")
    71  	}
    72  
    73  	n.delay.Wait()
    74  
    75  	r.ReceiveMessage(context.TODO(), from, message)
    76  	return nil
    77  }
    78  
    79  type networkClient struct {
    80  	local peer.ID
    81  	bsnet.Receiver
    82  	network *network
    83  	routing routing.IpfsRouting
    84  }
    85  
    86  func (nc *networkClient) SendMessage(
    87  	ctx context.Context,
    88  	to peer.ID,
    89  	message bsmsg.BitSwapMessage) error {
    90  	return nc.network.SendMessage(ctx, nc.local, to, message)
    91  }
    92  
    93  // FindProvidersAsync returns a channel of providers for the given key
    94  func (nc *networkClient) FindProvidersAsync(ctx context.Context, k key.Key, max int) <-chan peer.ID {
    95  
    96  	// NB: this function duplicates the PeerInfo -> ID transformation in the
    97  	// bitswap network adapter. Not to worry. This network client will be
    98  	// deprecated once the ipfsnet.Mock is added. The code below is only
    99  	// temporary.
   100  
   101  	out := make(chan peer.ID)
   102  	go func() {
   103  		defer close(out)
   104  		providers := nc.routing.FindProvidersAsync(ctx, k, max)
   105  		for info := range providers {
   106  			select {
   107  			case <-ctx.Done():
   108  			case out <- info.ID:
   109  			}
   110  		}
   111  	}()
   112  	return out
   113  }
   114  
   115  // Provide provides the key to the network
   116  func (nc *networkClient) Provide(ctx context.Context, k key.Key) error {
   117  	return nc.routing.Provide(ctx, k)
   118  }
   119  
   120  func (nc *networkClient) SetDelegate(r bsnet.Receiver) {
   121  	nc.Receiver = r
   122  }
   123  
   124  func (nc *networkClient) ConnectTo(_ context.Context, p peer.ID) error {
   125  	if !nc.network.HasPeer(p) {
   126  		return errors.New("no such peer in network")
   127  	}
   128  	nc.network.clients[p].PeerConnected(nc.local)
   129  	nc.Receiver.PeerConnected(p)
   130  	return nil
   131  }