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

     1  package network
     2  
     3  import (
     4  	ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
     5  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
     6  	key "github.com/ipfs/go-ipfs/blocks/key"
     7  	bsmsg "github.com/ipfs/go-ipfs/exchange/bitswap/message"
     8  	host "github.com/ipfs/go-ipfs/p2p/host"
     9  	inet "github.com/ipfs/go-ipfs/p2p/net"
    10  	peer "github.com/ipfs/go-ipfs/p2p/peer"
    11  	routing "github.com/ipfs/go-ipfs/routing"
    12  	eventlog "github.com/ipfs/go-ipfs/thirdparty/eventlog"
    13  )
    14  
    15  var log = eventlog.Logger("bitswap_network")
    16  
    17  // NewFromIpfsHost returns a BitSwapNetwork supported by underlying IPFS host
    18  func NewFromIpfsHost(host host.Host, r routing.IpfsRouting) BitSwapNetwork {
    19  	bitswapNetwork := impl{
    20  		host:    host,
    21  		routing: r,
    22  	}
    23  	host.SetStreamHandler(ProtocolBitswap, bitswapNetwork.handleNewStream)
    24  	host.Network().Notify((*netNotifiee)(&bitswapNetwork))
    25  	// TODO: StopNotify.
    26  
    27  	return &bitswapNetwork
    28  }
    29  
    30  // impl transforms the ipfs network interface, which sends and receives
    31  // NetMessage objects, into the bitswap network interface.
    32  type impl struct {
    33  	host    host.Host
    34  	routing routing.IpfsRouting
    35  
    36  	// inbound messages from the network are forwarded to the receiver
    37  	receiver Receiver
    38  }
    39  
    40  func (bsnet *impl) newStreamToPeer(ctx context.Context, p peer.ID) (inet.Stream, error) {
    41  
    42  	// first, make sure we're connected.
    43  	// if this fails, we cannot connect to given peer.
    44  	//TODO(jbenet) move this into host.NewStream?
    45  	if err := bsnet.host.Connect(ctx, peer.PeerInfo{ID: p}); err != nil {
    46  		return nil, err
    47  	}
    48  
    49  	return bsnet.host.NewStream(ProtocolBitswap, p)
    50  }
    51  
    52  func (bsnet *impl) SendMessage(
    53  	ctx context.Context,
    54  	p peer.ID,
    55  	outgoing bsmsg.BitSwapMessage) error {
    56  
    57  	s, err := bsnet.newStreamToPeer(ctx, p)
    58  	if err != nil {
    59  		return err
    60  	}
    61  	defer s.Close()
    62  
    63  	if err := outgoing.ToNet(s); err != nil {
    64  		log.Debugf("error: %s", err)
    65  		return err
    66  	}
    67  
    68  	return err
    69  }
    70  
    71  func (bsnet *impl) SendRequest(
    72  	ctx context.Context,
    73  	p peer.ID,
    74  	outgoing bsmsg.BitSwapMessage) (bsmsg.BitSwapMessage, error) {
    75  
    76  	s, err := bsnet.newStreamToPeer(ctx, p)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	defer s.Close()
    81  
    82  	if err := outgoing.ToNet(s); err != nil {
    83  		log.Debugf("error: %s", err)
    84  		return nil, err
    85  	}
    86  
    87  	incoming, err := bsmsg.FromNet(s)
    88  	if err != nil {
    89  		log.Debugf("error: %s", err)
    90  		return incoming, err
    91  	}
    92  
    93  	return incoming, nil
    94  }
    95  
    96  func (bsnet *impl) SetDelegate(r Receiver) {
    97  	bsnet.receiver = r
    98  }
    99  
   100  func (bsnet *impl) ConnectTo(ctx context.Context, p peer.ID) error {
   101  	return bsnet.host.Connect(ctx, peer.PeerInfo{ID: p})
   102  }
   103  
   104  // FindProvidersAsync returns a channel of providers for the given key
   105  func (bsnet *impl) FindProvidersAsync(ctx context.Context, k key.Key, max int) <-chan peer.ID {
   106  
   107  	// Since routing queries are expensive, give bitswap the peers to which we
   108  	// have open connections. Note that this may cause issues if bitswap starts
   109  	// precisely tracking which peers provide certain keys. This optimization
   110  	// would be misleading. In the long run, this may not be the most
   111  	// appropriate place for this optimization, but it won't cause any harm in
   112  	// the short term.
   113  	connectedPeers := bsnet.host.Network().Peers()
   114  	out := make(chan peer.ID, len(connectedPeers)) // just enough buffer for these connectedPeers
   115  	for _, id := range connectedPeers {
   116  		if id == bsnet.host.ID() {
   117  			continue // ignore self as provider
   118  		}
   119  		out <- id
   120  	}
   121  
   122  	go func() {
   123  		defer close(out)
   124  		providers := bsnet.routing.FindProvidersAsync(ctx, k, max)
   125  		for info := range providers {
   126  			if info.ID == bsnet.host.ID() {
   127  				continue // ignore self as provider
   128  			}
   129  			bsnet.host.Peerstore().AddAddrs(info.ID, info.Addrs, peer.TempAddrTTL)
   130  			select {
   131  			case <-ctx.Done():
   132  				return
   133  			case out <- info.ID:
   134  			}
   135  		}
   136  	}()
   137  	return out
   138  }
   139  
   140  // Provide provides the key to the network
   141  func (bsnet *impl) Provide(ctx context.Context, k key.Key) error {
   142  	return bsnet.routing.Provide(ctx, k)
   143  }
   144  
   145  // handleNewStream receives a new stream from the network.
   146  func (bsnet *impl) handleNewStream(s inet.Stream) {
   147  	defer s.Close()
   148  
   149  	if bsnet.receiver == nil {
   150  		return
   151  	}
   152  
   153  	received, err := bsmsg.FromNet(s)
   154  	if err != nil {
   155  		go bsnet.receiver.ReceiveError(err)
   156  		log.Debugf("bitswap net handleNewStream from %s error: %s", s.Conn().RemotePeer(), err)
   157  		return
   158  	}
   159  
   160  	p := s.Conn().RemotePeer()
   161  	ctx := context.Background()
   162  	log.Debugf("bitswap net handleNewStream from %s", s.Conn().RemotePeer())
   163  	bsnet.receiver.ReceiveMessage(ctx, p, received)
   164  }
   165  
   166  type netNotifiee impl
   167  
   168  func (nn *netNotifiee) impl() *impl {
   169  	return (*impl)(nn)
   170  }
   171  
   172  func (nn *netNotifiee) Connected(n inet.Network, v inet.Conn) {
   173  	nn.impl().receiver.PeerConnected(v.RemotePeer())
   174  }
   175  
   176  func (nn *netNotifiee) Disconnected(n inet.Network, v inet.Conn) {
   177  	nn.impl().receiver.PeerDisconnected(v.RemotePeer())
   178  }
   179  
   180  func (nn *netNotifiee) OpenedStream(n inet.Network, v inet.Stream) {}
   181  func (nn *netNotifiee) ClosedStream(n inet.Network, v inet.Stream) {}
   182  func (nn *netNotifiee) Listen(n inet.Network, a ma.Multiaddr)      {}
   183  func (nn *netNotifiee) ListenClose(n inet.Network, a ma.Multiaddr) {}