routed host stash
Juan Batiz-Benet committed
Feb 13, 2015 at 22:26 UTC
ee1450bf9e310a1e6f0eb168b6a05c2dfcc6f730
1 file changed
+108
p2p/host/routed/routed.go
new
+108
@@ -0,0 +1,108 @@
1
+package routedhost
2
+
3
+import (
4
+ "fmt"
5
+ "time"
6
+
7
+ context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
8
+ ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
9
+
10
+ eventlog "github.com/jbenet/go-ipfs/thirdparty/eventlog"
11
+ lgbl "github.com/jbenet/go-ipfs/util/eventlog/loggables"
12
+
13
+ host "github.com/jbenet/go-ipfs/p2p/host"
14
+ inet "github.com/jbenet/go-ipfs/p2p/net"
15
+ peer "github.com/jbenet/go-ipfs/p2p/peer"
16
+ protocol "github.com/jbenet/go-ipfs/p2p/protocol"
17
+ routing "github.com/jbenet/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
+func (rh *RoutedHost) Peerstore() peer.Peerstore {
88
+ return rh.host.Peerstore()
89
+}
90
+func (rh *RoutedHost) Addrs() []ma.Multiaddr {
91
+ return rh.host.Addrs()
92
+}
93
+func (rh *RoutedHost) Network() inet.Network {
94
+ return rh.host.Network()
95
+}
96
+func (rh *RoutedHost) Mux() *protocol.Mux {
97
+ return rh.host.Mux()
98
+}
99
+func (rh *RoutedHost) SetStreamHandler(pid protocol.ID, handler inet.StreamHandler) {
100
+ rh.host.SetStreamHandler(pid, handler)
101
+}
102
+func (rh *RoutedHost) NewStream(pid protocol.ID, p peer.ID) (inet.Stream, error) {
103
+ return rh.host.NewStream(pid, p)
104
+}
105
+func (rh *RoutedHost) Close() error {
106
+ // no need to close IpfsRouting. we dont own it.
107
+ return rh.host.Close()
108
+}