routing/dht: adjust routing table on peer conn/disc
Juan Batiz-Benet committed
Jan 24, 2015 at 08:52 UTC
00d7b498efc2e3f4929354f3379c158b289b305f
4 files changed
+69
-1
routing/dht/dht.go
+9
-1
@@ -65,9 +65,17 @@ func NewDHT(ctx context.Context, h host.Host, dstore ds.ThreadSafeDatastore) *Ip
65
dht.datastore = dstore
66
dht.self = h.ID()
67
dht.peerstore = h.Peerstore()
68
- dht.ContextGroup = ctxgroup.WithContext(ctx)
68
dht.host = h
69
70
+ // register for network notifs.
71
+ dht.host.Network().Notify((*netNotifiee)(dht))
72
+
73
+ dht.ContextGroup = ctxgroup.WithContextAndTeardown(ctx, func() error {
74
+ // remove ourselves from network notifs.
75
+ dht.host.Network().StopNotify((*netNotifiee)(dht))
76
+ return nil
77
+ })
78
+
79
// sanity check. this should **never** happen
80
if len(dht.peerstore.Addresses(dht.self)) < 1 {
81
panic("attempt to initialize dht without addresses for self")
routing/dht/notif.go
new
+33
@@ -0,0 +1,33 @@
1
+package dht
2
+
3
+import (
4
+ inet "github.com/jbenet/go-ipfs/p2p/net"
5
+)
6
+
7
+// netNotifiee defines methods to be used with the IpfsDHT
8
+type netNotifiee IpfsDHT
9
+
10
+func (nn *netNotifiee) DHT() *IpfsDHT {
11
+ return (*IpfsDHT)(nn)
12
+}
13
+
14
+func (nn *netNotifiee) Connected(n inet.Network, v inet.Conn) {
15
+ dht := nn.DHT()
16
+ select {
17
+ case <-dht.Closing():
18
+ return
19
+ }
20
+ dht.Update(dht.Context(), v.RemotePeer())
21
+}
22
+
23
+func (nn *netNotifiee) Disconnected(n inet.Network, v inet.Conn) {
24
+ dht := nn.DHT()
25
+ select {
26
+ case <-dht.Closing():
27
+ return
28
+ }
29
+ dht.routingTable.Remove(v.RemotePeer())
30
+}
31
+
32
+func (nn *netNotifiee) OpenedStream(n inet.Network, v inet.Stream) {}
33
+func (nn *netNotifiee) ClosedStream(n inet.Network, v inet.Stream) {}
routing/kbucket/bucket.go
+10
@@ -30,6 +30,16 @@ func (b *Bucket) find(id peer.ID) *list.Element {
30
return nil
31
}
32
33
+func (b *Bucket) remove(id peer.ID) {
34
+ b.lk.RLock()
35
+ defer b.lk.RUnlock()
36
+ for e := b.list.Front(); e != nil; e = e.Next() {
37
+ if e.Value.(peer.ID) == id {
38
+ b.list.Remove(e)
39
+ }
40
+ }
41
+}
42
+
43
func (b *Bucket) moveToFront(e *list.Element) {
44
b.lk.Lock()
45
b.list.MoveToFront(e)
routing/kbucket/table.go
+17
@@ -87,6 +87,23 @@ func (rt *RoutingTable) Update(p peer.ID) peer.ID {
87
return ""
88
}
89
90
+// Remove deletes a peer from the routing table. This is to be used
91
+// when we are sure a node has disconnected completely.
92
+func (rt *RoutingTable) Remove(p peer.ID) {
93
+ rt.tabLock.Lock()
94
+ defer rt.tabLock.Unlock()
95
+ peerID := ConvertPeerID(p)
96
+ cpl := commonPrefixLen(peerID, rt.local)
97
+
98
+ bucketID := cpl
99
+ if bucketID >= len(rt.Buckets) {
100
+ bucketID = len(rt.Buckets) - 1
101
+ }
102
+
103
+ bucket := rt.Buckets[bucketID]
104
+ bucket.remove(p)
105
+}
106
+
107
func (rt *RoutingTable) nextBucket() peer.ID {
108
bucket := rt.Buckets[len(rt.Buckets)-1]
109
newBucket := bucket.Split(len(rt.Buckets)-1, rt.local)