github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/p2p/host/routed/routed.go (about)

     1  package routedhost
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
     8  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
     9  	eventlog "github.com/ipfs/go-ipfs/thirdparty/eventlog"
    10  	lgbl "github.com/ipfs/go-ipfs/util/eventlog/loggables"
    11  
    12  	metrics "github.com/ipfs/go-ipfs/metrics"
    13  	host "github.com/ipfs/go-ipfs/p2p/host"
    14  	inet "github.com/ipfs/go-ipfs/p2p/net"
    15  	peer "github.com/ipfs/go-ipfs/p2p/peer"
    16  	protocol "github.com/ipfs/go-ipfs/p2p/protocol"
    17  	routing "github.com/ipfs/go-ipfs/routing"
    18  )
    19  
    20  var log = eventlog.Logger("p2p/host/routed")
    21  
    22  // AddressTTL is the expiry time for our addresses.
    23  // We expire them quickly.
    24  const AddressTTL = time.Second * 10
    25  
    26  // RoutedHost is a p2p Host that includes a routing system.
    27  // This allows the Host to find the addresses for peers when
    28  // it does not have them.
    29  type RoutedHost struct {
    30  	host  host.Host // embedded other host.
    31  	route routing.IpfsRouting
    32  }
    33  
    34  func Wrap(h host.Host, r routing.IpfsRouting) *RoutedHost {
    35  	return &RoutedHost{h, r}
    36  }
    37  
    38  // Connect ensures there is a connection between this host and the peer with
    39  // given peer.ID. See (host.Host).Connect for more information.
    40  //
    41  // RoutedHost's Connect differs in that if the host has no addresses for a
    42  // given peer, it will use its routing system to try to find some.
    43  func (rh *RoutedHost) Connect(ctx context.Context, pi peer.PeerInfo) error {
    44  	// first, check if we're already connected.
    45  	if len(rh.Network().ConnsToPeer(pi.ID)) > 0 {
    46  		return nil
    47  	}
    48  
    49  	// if we were given some addresses, keep + use them.
    50  	if len(pi.Addrs) > 0 {
    51  		rh.Peerstore().AddAddrs(pi.ID, pi.Addrs, peer.TempAddrTTL)
    52  	}
    53  
    54  	// Check if we have some addresses in our recent memory.
    55  	addrs := rh.Peerstore().Addrs(pi.ID)
    56  	if len(addrs) < 1 {
    57  
    58  		// no addrs? find some with the routing system.
    59  		pi2, err := rh.route.FindPeer(ctx, pi.ID)
    60  		if err != nil {
    61  			return err // couldnt find any :(
    62  		}
    63  		if pi2.ID != pi.ID {
    64  			err = fmt.Errorf("routing failure: provided addrs for different peer")
    65  			logRoutingErrDifferentPeers(ctx, pi.ID, pi2.ID, err)
    66  			return err
    67  		}
    68  		addrs = pi2.Addrs
    69  	}
    70  
    71  	// if we're here, we got some addrs. let's use our wrapped host to connect.
    72  	pi.Addrs = addrs
    73  	return rh.host.Connect(ctx, pi)
    74  }
    75  
    76  func logRoutingErrDifferentPeers(ctx context.Context, wanted, got peer.ID, err error) {
    77  	lm := make(lgbl.DeferredMap)
    78  	lm["error"] = err
    79  	lm["wantedPeer"] = func() interface{} { return wanted.Pretty() }
    80  	lm["gotPeer"] = func() interface{} { return got.Pretty() }
    81  	log.Event(ctx, "routingError", lm)
    82  }
    83  
    84  func (rh *RoutedHost) ID() peer.ID {
    85  	return rh.host.ID()
    86  }
    87  
    88  func (rh *RoutedHost) Peerstore() peer.Peerstore {
    89  	return rh.host.Peerstore()
    90  }
    91  
    92  func (rh *RoutedHost) Addrs() []ma.Multiaddr {
    93  	return rh.host.Addrs()
    94  }
    95  
    96  func (rh *RoutedHost) Network() inet.Network {
    97  	return rh.host.Network()
    98  }
    99  
   100  func (rh *RoutedHost) Mux() *protocol.Mux {
   101  	return rh.host.Mux()
   102  }
   103  
   104  func (rh *RoutedHost) SetStreamHandler(pid protocol.ID, handler inet.StreamHandler) {
   105  	rh.host.SetStreamHandler(pid, handler)
   106  }
   107  
   108  func (rh *RoutedHost) RemoveStreamHandler(pid protocol.ID) {
   109  	rh.host.RemoveStreamHandler(pid)
   110  }
   111  
   112  func (rh *RoutedHost) NewStream(pid protocol.ID, p peer.ID) (inet.Stream, error) {
   113  	return rh.host.NewStream(pid, p)
   114  }
   115  func (rh *RoutedHost) Close() error {
   116  	// no need to close IpfsRouting. we dont own it.
   117  	return rh.host.Close()
   118  }
   119  
   120  func (rh *RoutedHost) GetBandwidthReporter() metrics.Reporter {
   121  	return rh.host.GetBandwidthReporter()
   122  }