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 }