packages/hyprspace: add rebootstrap support

This commit is contained in:
Max Headroom 2022-09-26 22:10:29 +02:00
parent cbe51dd88c
commit 76f3badc7c
3 changed files with 61 additions and 17 deletions

View file

@ -153,8 +153,7 @@ func UpRun(r *cmd.Root, c *cmd.Sub) {
fmt.Println("[+] Setting Up Node Discovery via DHT")
// Setup P2P Discovery
discoverNow := make(chan bool)
go p2p.Discover(ctx, host, dht, peerTable, discoverNow)
go p2p.Discover(ctx, host, dht, peerTable)
// Configure path for lock
lockPath := filepath.Join(filepath.Dir(cfg.Path), cfg.Interface.Name+".lock")
@ -219,7 +218,7 @@ func UpRun(r *cmd.Root, c *cmd.Sub) {
stream, err = host.NewStream(ctx, peer, p2p.Protocol)
if err != nil {
fmt.Println("[!] Failed to open stream to " + dst)
go p2p.Rediscover(discoverNow)
go p2p.Rediscover()
continue
}
stream.SetWriteDeadline(time.Now().Add(25 * time.Second))

View file

@ -11,8 +11,10 @@ import (
dht "github.com/libp2p/go-libp2p-kad-dht"
)
var discoverNow = make(chan bool)
// Discover starts up a DHT based discovery system finding and adding nodes with the same rendezvous string.
func Discover(ctx context.Context, h host.Host, dht *dht.IpfsDHT, peerTable map[string]peer.ID, discoverNow chan bool) {
func Discover(ctx context.Context, h host.Host, dht *dht.IpfsDHT, peerTable map[string]peer.ID) {
dur := time.Second * 1
ticker := time.NewTicker(dur)
defer ticker.Stop()
@ -26,6 +28,7 @@ func Discover(ctx context.Context, h host.Host, dht *dht.IpfsDHT, peerTable map[
// Immediately trigger discovery
ticker.Reset(time.Millisecond * 1)
case <-ticker.C:
connectedToAny := false
for nd, id := range peerTable {
if h.Network().Connectedness(id) != network.Connected {
addrs, err := dht.FindPeer(ctx, id)
@ -37,8 +40,17 @@ func Discover(ctx context.Context, h host.Host, dht *dht.IpfsDHT, peerTable map[
continue
}
fmt.Printf("[+] Connected to %s at %s\n", nd, conn.RemoteMultiaddr())
connectedToAny = true
} else {
connectedToAny = true
}
}
if !connectedToAny {
fmt.Println("[!] Not connected to any peers, attempting to bootstrap again")
Rebootstrap()
dur = time.Second * 1
ticker.Reset(dur)
} else {
dur = dur * 2
if dur >= time.Second*60 {
dur = time.Second * 60
@ -46,8 +58,9 @@ func Discover(ctx context.Context, h host.Host, dht *dht.IpfsDHT, peerTable map[
ticker.Reset(dur)
}
}
}
}
func Rediscover(discoverNow chan bool) {
func Rediscover() {
discoverNow <- true
}

View file

@ -9,7 +9,9 @@ import (
"net/http"
"net/url"
"os"
"os/signal"
"sync"
"syscall"
"github.com/ipfs/go-datastore"
"github.com/libp2p/go-libp2p"
@ -26,6 +28,8 @@ import (
// Protocol is a descriptor for the Hyprspace P2P Protocol.
const Protocol = "/hyprspace/0.0.1"
var bootstrapTriggerChan = make(chan bool)
func getExtraBootstrapNodes(addr ma.Multiaddr) (nodesList []string) {
nodesList = []string{}
ip4, err := addr.ValueForProtocol(ma.P_IP4)
@ -145,11 +149,22 @@ func CreateNode(ctx context.Context, inputKey []byte, port int, handler network.
// Let's connect to the bootstrap nodes first. They will tell us about the
// other nodes in the network.
count := bootstrap(ctx, node, BootstrapPeers)
if count < 1 {
return node, dhtOut, errors.New("unable to bootstrap libp2p node")
}
go rebootstrap(ctx, node, BootstrapPeers)
return node, dhtOut, nil
}
func bootstrap(ctx context.Context, node host.Host, bootstrapPeers map[peer.ID]*peer.AddrInfo) int {
var wg sync.WaitGroup
lock := sync.Mutex{}
count := 0
wg.Add(len(BootstrapPeers))
for _, peerInfo := range BootstrapPeers {
wg.Add(len(bootstrapPeers))
for _, peerInfo := range bootstrapPeers {
go func(peerInfo *peer.AddrInfo) {
defer wg.Done()
err := node.Connect(ctx, *peerInfo)
@ -162,11 +177,28 @@ func CreateNode(ctx context.Context, inputKey []byte, port int, handler network.
}(peerInfo)
}
wg.Wait()
if count < 1 {
return node, dhtOut, errors.New("unable to bootstrap libp2p node")
}
fmt.Printf("[+] Connected to %d bootstrap peers\n", count)
return node, dhtOut, nil
return count
}
func rebootstrap(ctx context.Context, node host.Host, bootstrapPeers map[peer.ID]*peer.AddrInfo) {
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, syscall.SIGUSR1)
for {
select {
case <-ctx.Done():
return
case <-bootstrapTriggerChan:
bootstrap(ctx, node, bootstrapPeers)
case <-signalCh:
fmt.Println("[-] Rebootstrapping on SIGUSR1")
bootstrap(ctx, node, bootstrapPeers)
Rediscover()
}
}
}
func Rebootstrap() {
bootstrapTriggerChan <- true
}