mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-11-14 12:15:18 +00:00
142 lines
4.5 KiB
Go
142 lines
4.5 KiB
Go
|
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
|
||
|
}
|