@@ -17,8 +17,10 @@ import (
1717 dht "github.com/libp2p/go-libp2p-kad-dht"
1818 pubsub "github.com/libp2p/go-libp2p-pubsub"
1919 "github.com/libp2p/go-libp2p/core/host"
20+ "github.com/libp2p/go-libp2p/core/network"
2021 "github.com/libp2p/go-libp2p/core/peer"
2122 "github.com/libp2p/go-libp2p/p2p/discovery/mdns"
23+ "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/proto"
2224 drouting "github.com/libp2p/go-libp2p/p2p/discovery/routing"
2325 "github.com/multiformats/go-multiaddr"
2426)
@@ -31,13 +33,16 @@ type Message struct {
3133}
3234
3335type PeerTracker struct {
34- mu sync.RWMutex
35- names map [peer.ID ]string
36+ mu sync.RWMutex
37+ names map [peer.ID ]string
38+ relayCount int
39+ isRelaying map [string ]bool
3640}
3741
3842func NewPeerTracker () * PeerTracker {
3943 return & PeerTracker {
40- names : make (map [peer.ID ]string ),
44+ names : make (map [peer.ID ]string ),
45+ isRelaying : make (map [string ]bool ),
4146 }
4247}
4348
@@ -56,6 +61,24 @@ func (pt *PeerTracker) GetName(peerID peer.ID) string {
5661 return "unknown"
5762}
5863
64+ func (pt * PeerTracker ) RecordRelay (srcPeer , dstPeer peer.ID ) {
65+ pt .mu .Lock ()
66+ defer pt .mu .Unlock ()
67+
68+ key := srcPeer .String () + "->" + dstPeer .String ()
69+ if ! pt .isRelaying [key ] {
70+ pt .isRelaying [key ] = true
71+ pt .relayCount ++
72+ fmt .Printf ("\n [RELAY] Acting as relay: %s -> %s (total relays: %d)\n \n " , srcPeer .String ()[:16 ], dstPeer .String ()[:16 ], pt .relayCount )
73+ }
74+ }
75+
76+ func (pt * PeerTracker ) GetRelayCount () int {
77+ pt .mu .RLock ()
78+ defer pt .mu .RUnlock ()
79+ return pt .relayCount
80+ }
81+
5982var bootstrapNodes = []string {
6083 "/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN" ,
6184 "/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb" ,
@@ -78,12 +101,23 @@ func (n *discoveryNotifee) HandlePeerFound(pi peer.AddrInfo) {
78101
79102func main () {
80103 name := flag .String ("name" , "" , "Your node name" )
104+ bootstrap := flag .String ("bootstrap" , "" , "Comma-separated list of bootstrap node multiaddrs (overrides defaults)" )
81105 flag .Parse ()
82106
83107 if * name == "" {
84108 log .Fatal ("--name flag is required" )
85109 }
86110
111+ var bootstrapPeers []string
112+ if * bootstrap != "" {
113+ bootstrapPeers = strings .Split (* bootstrap , "," )
114+ for i , addr := range bootstrapPeers {
115+ bootstrapPeers [i ] = strings .TrimSpace (addr )
116+ }
117+ } else {
118+ bootstrapPeers = bootstrapNodes
119+ }
120+
87121 ctx , cancel := context .WithCancel (context .Background ())
88122
89123 h , err := createHost (ctx )
@@ -103,7 +137,7 @@ func main() {
103137 log .Fatalf ("Failed to bootstrap DHT: %v" , err )
104138 }
105139
106- connectToBootstrapNodes (ctx , h , bootstrapNodes )
140+ connectToBootstrapNodes (ctx , h , bootstrapPeers )
107141
108142 ps , err := pubsub .NewGossipSub (ctx , h )
109143 if err != nil {
@@ -139,6 +173,12 @@ func main() {
139173
140174 peerTracker := NewPeerTracker ()
141175
176+ h .Network ().Notify (& network.NotifyBundle {
177+ ConnectedF : func (n network.Network , conn network.Conn ) {
178+ monitorRelayActivity (conn , peerTracker )
179+ },
180+ })
181+
142182 go discoverPeers (ctx , h , routingDiscovery )
143183
144184 go receiveMessages (ctx , sub , h .ID (), peerTracker )
@@ -320,7 +360,8 @@ func printPeersPeriodically(ctx context.Context, h host.Host, topic *pubsub.Topi
320360 allPeers := h .Network ().Peers ()
321361 topicPeers := topic .ListPeers ()
322362
323- fmt .Printf ("\n [Total connections: %d | Topic peers: %d]\n " , len (allPeers ), len (topicPeers ))
363+ relayCount := tracker .GetRelayCount ()
364+ fmt .Printf ("\n [Total connections: %d | Topic peers: %d | Acting as relay: %d]\n " , len (allPeers ), len (topicPeers ), relayCount )
324365 if len (topicPeers ) > 0 {
325366 fmt .Println ("Topic peers:" )
326367 for _ , p := range topicPeers {
@@ -352,3 +393,21 @@ func printPeersPeriodically(ctx context.Context, h host.Host, topic *pubsub.Topi
352393func isRelayedConnection (addr string ) bool {
353394 return strings .Contains (addr , "/p2p-circuit/" )
354395}
396+
397+ func monitorRelayActivity (conn network.Conn , tracker * PeerTracker ) {
398+ go func () {
399+ streams := conn .GetStreams ()
400+ for _ , stream := range streams {
401+ protocol := stream .Protocol ()
402+ if protocol == proto .ProtoIDv2Hop || protocol == proto .ProtoIDv2Stop {
403+ localAddr := conn .LocalMultiaddr ().String ()
404+ remoteAddr := conn .RemoteMultiaddr ().String ()
405+
406+ if strings .Contains (localAddr , "/p2p-circuit/" ) || strings .Contains (remoteAddr , "/p2p-circuit/" ) {
407+ remotePeer := conn .RemotePeer ()
408+ tracker .RecordRelay (remotePeer , remotePeer )
409+ }
410+ }
411+ }
412+ }()
413+ }
0 commit comments