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