forked from libp2p/go-libp2p-kad-dht
-
Notifications
You must be signed in to change notification settings - Fork 0
/
subscriber_notifee.go
141 lines (121 loc) · 4.47 KB
/
subscriber_notifee.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package dht
import (
"fmt"
"github.com/libp2p/go-libp2p/core/event"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
)
func (dht *IpfsDHT) startNetworkSubscriber() error {
bufSize := eventbus.BufSize(256)
evts := []interface{}{
// register for event bus notifications of when peers successfully complete identification in order to update
// the routing table
new(event.EvtPeerIdentificationCompleted),
// register for event bus protocol ID changes in order to update the routing table
new(event.EvtPeerProtocolsUpdated),
// register for event bus notifications for when our local address/addresses change so we can
// advertise those to the network
new(event.EvtLocalAddressesUpdated),
// we want to know when we are disconnecting from other peers.
new(event.EvtPeerConnectednessChanged),
}
// register for event bus local routability changes in order to trigger switching between client and server modes
// only register for events if the DHT is operating in ModeAuto
if dht.auto == ModeAuto || dht.auto == ModeAutoServer {
evts = append(evts, new(event.EvtLocalReachabilityChanged))
}
subs, err := dht.host.EventBus().Subscribe(evts, bufSize)
if err != nil {
return fmt.Errorf("dht could not subscribe to eventbus events: %w", err)
}
dht.wg.Add(1)
go func() {
defer dht.wg.Done()
defer subs.Close()
for {
select {
case e, more := <-subs.Out():
if !more {
return
}
switch evt := e.(type) {
case event.EvtLocalAddressesUpdated:
// when our address changes, we should proactively tell our closest peers about it so
// we become discoverable quickly. The Identify protocol will push a signed peer record
// with our new address to all peers we are connected to. However, we might not necessarily be connected
// to our closet peers & so in the true spirit of Zen, searching for ourself in the network really is the best way
// to to forge connections with those matter.
if dht.autoRefresh || dht.testAddressUpdateProcessing {
dht.rtRefreshManager.RefreshNoWait()
}
case event.EvtPeerProtocolsUpdated:
handlePeerChangeEvent(dht, evt.Peer)
case event.EvtPeerIdentificationCompleted:
handlePeerChangeEvent(dht, evt.Peer)
case event.EvtPeerConnectednessChanged:
if evt.Connectedness != network.Connected {
dht.msgSender.OnDisconnect(dht.ctx, evt.Peer)
}
case event.EvtLocalReachabilityChanged:
if dht.auto == ModeAuto || dht.auto == ModeAutoServer {
handleLocalReachabilityChangedEvent(dht, evt)
} else {
// something has gone really wrong if we get an event we did not subscribe to
logger.Errorf("received LocalReachabilityChanged event that was not subscribed to")
}
default:
// something has gone really wrong if we get an event for another type
logger.Errorf("got wrong type from subscription: %T", e)
}
case <-dht.ctx.Done():
return
}
}
}()
return nil
}
func handlePeerChangeEvent(dht *IpfsDHT, p peer.ID) {
valid, err := dht.validRTPeer(p)
if err != nil {
logger.Errorf("could not check peerstore for protocol support: err: %s", err)
return
} else if valid {
dht.peerFound(p)
} else {
dht.peerStoppedDHT(p)
}
}
func handleLocalReachabilityChangedEvent(dht *IpfsDHT, e event.EvtLocalReachabilityChanged) {
var target mode
switch e.Reachability {
case network.ReachabilityPrivate:
target = modeClient
case network.ReachabilityUnknown:
if dht.auto == ModeAutoServer {
target = modeServer
} else {
target = modeClient
}
case network.ReachabilityPublic:
target = modeServer
}
logger.Infof("processed event %T; performing dht mode switch", e)
err := dht.setMode(target)
// NOTE: the mode will be printed out as a decimal.
if err == nil {
logger.Infow("switched DHT mode successfully", "mode", target)
} else {
logger.Errorw("switching DHT mode failed", "mode", target, "error", err)
}
}
// validRTPeer returns true if the peer supports the DHT protocol and false otherwise. Supporting the DHT protocol means
// supporting the primary protocols, we do not want to add peers that are speaking obsolete secondary protocols to our
// routing table
func (dht *IpfsDHT) validRTPeer(p peer.ID) (bool, error) {
b, err := dht.peerstore.FirstSupportedProtocol(p, dht.protocols...)
if len(b) == 0 || err != nil {
return false, err
}
return dht.routingTablePeerFilter == nil || dht.routingTablePeerFilter(dht, p), nil
}