I have Node A (has a public IP) it acts as a bootstrap peer. I also have Node B and C (Node B in my house with no public IP and Node C in my friends house also no public IP). Both of them can connect to Node A during the bootstrap phase. Node B now wants to Advertise
a rendezvous point using discovery.RoutingDiscovery
. Now Node C wants to discover this rendezvous point using discovery.FindPeers
. However, I keep getting 0 peers found. My question is: Is what I am trying to do even possible?
I find that my scenario works if either Node B or C runs on the same machine as Node A (but with a non public address).
Here is the code for Node A (the bootstrap peer)
package main
import (
context2 "context"
"crypto/rand"
"flag"
"fmt"
"github.com/libp2p/go-libp2p"
relay "github.com/libp2p/go-libp2p-circuit"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/routing"
//dht "github.com/libp2p/go-libp2p-kad-dht"
"github.com/libp2p/go-libp2p-kad-dht/dual"
secio "github.com/libp2p/go-libp2p-secio"
)
func main() {
listen := flag.String("listen", "/ip4/0.0.0.0/tcp/5000", "The listen address")
flag.Parse()
ctx, cancel := context2.WithCancel(context2.Background())
defer cancel()
routing := libp2p.Routing(func(host host.Host) (routing.PeerRouting, error) {
return dual.New(ctx, host)
})
listenAddress := libp2p.ListenAddrStrings(*listen)
enableRelay := libp2p.EnableRelay(relay.OptActive, relay.OptHop)
priv, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, rand.Reader)
if err != nil {
panic(err)
}
identity := libp2p.Identity(priv)
security := libp2p.Security(secio.ID, secio.New)
host, err := libp2p.New(
ctx,
routing,
listenAddress,
enableRelay,
identity,
security,
)
if err != nil {
panic(err)
}
for _, addr := range host.Addrs() {
fmt.Printf("Addr: %s/p2p/%s\n", addr, host.ID().Pretty())
}
select {}
}
Here is the code for Node B and C
func main() {
room := flag.String("room", "", "the room you want to create")
joinRoom := flag.String("join", "", "the room you want to join")
bootstrap := flag.String("bootstrap", "/ip4/134.209.171.195/tcp/5000/p2p/QmWpBxWhq8G9G9m2yxc314Hfmd39PiHuWC5EJv3xZz9KxZ", "the relay")
flag.Parse()
ctx := context.Background()
//defer cancel()
if *joinRoom == "" && *room == "" {
panic("At least one flag must be provided")
}
var ddht *dual.DHT
var routingDiscovery *discovery.RoutingDiscovery
routing := libp2p.Routing(func(host host.Host) (routing.PeerRouting, error) {
var err error
ddht, err = dual.New(ctx, host)
routingDiscovery = discovery.NewRoutingDiscovery(ddht)
return ddht, err
})
listenAddress := libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0")
//enableRelay := libp2p.EnableRelay()
security := libp2p.Security(secio.ID, secio.New)
host, err := libp2p.New(ctx, listenAddress, security, routing, libp2p.NATPortMap())
if err != nil {
panic(err)
}
fmt.Println("Host Created")
for _, addr := range host.Addrs() {
fmt.Printf("Address: %s\n", addr)
}
fmt.Printf("My ID %s\n", host.ID().Pretty())
// connect to the bootstrap peers
ma, err := multiaddr.NewMultiaddr(*bootstrap)
if err != nil {
panic(err)
}
peerInfo, err := peer.AddrInfoFromP2pAddr(ma)
if err != nil {
panic(err)
}
if err := ddht.Bootstrap(ctx); err != nil {
panic(err)
}
if err := host.Connect(ctx, *peerInfo); err != nil {
panic(err)
}
fmt.Println("we are connected to the bootstrap peer")
fmt.Println("DHT in a bootstrapped state")
time.Sleep(time.Second * 5)
ddht.LAN.RoutingTable().Print()
ddht.WAN.RoutingTable().Print()
// now do chat specific stuff
if *room != "" {
host.SetStreamHandler(protocolKey(*room), handleStream)
// create a room and wait for connections in it
fmt.Printf("Advertising %s\n", protocolKey(*room))
discovery.Advertise(ctx, routingDiscovery, string(protocolKey(*room)))
fmt.Printf("Successfully advertised room: %s\n", *room)
// wait forever
select {}
}
if *joinRoom != "" {
fmt.Printf("Joining room %s\n", protocolKey(*joinRoom))
pctx, _ := context.WithTimeout(ctx, time.Second*10)
peers, err := discovery.FindPeers(pctx, routingDiscovery, string(protocolKey(*joinRoom)))
//peerChan, err := routingDiscovery.FindPeers(pctx, protocolKey(*joinRoom))
if err != nil {
panic(err)
}
if len(peers) == 0 {
fmt.Println("No Peers Found")
return
}
fmt.Printf("Found %d peers\n", len(peers))
for _, p := range peers {
fmt.Printf("Trying peer %s\n", p.ID.Pretty())
fmt.Println("Addresses")
for _, addr := range p.Addrs {
ma, err := circuitRelay(addr.String(), p.ID.String())
if err != nil {
fmt.Printf("Error circuit Relay address %s\n", err)
continue
}
info, err := peer.AddrInfoFromP2pAddr(ma)
if err != nil {
fmt.Printf("Error converting to addr info %s\n", err)
continue
}
fmt.Printf("Going to try and connect via relay (%s)\n", ma)
if err := host.Connect(ctx, *info); err == nil {
fmt.Printf("We Have a connection try to create a stream now\n")
stream, err := host.NewStream(ctx, p.ID, protocolKey(*joinRoom))
if err != nil {
fmt.Printf("Error dialing %s <%s>\n", p.ID.Pretty(), err)
} else {
go handleStream(stream)
break
}
}
}
}
select {}
}
}
func protocolKey(key string) protocol.ID {
return protocol.ID("/chat/" + key)
}
func handleStream(stream network.Stream) {
fmt.Println("Handling Stream")
defer stream.Close()
}
func circuitRelay(target string, id string) (multiaddr.Multiaddr, error) {
return multiaddr.NewMultiaddr("/p2p-circuit" + target + "/p2p/" + id)
}