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 }