185 lines
4.8 KiB
Go
185 lines
4.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
"github.com/libp2p/go-libp2p"
|
|
"github.com/libp2p/go-libp2p/core/peer"
|
|
peerstore "github.com/libp2p/go-libp2p/core/peer"
|
|
"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client"
|
|
"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay"
|
|
"github.com/libp2p/go-libp2p/p2p/protocol/ping"
|
|
"github.com/libp2p/go-libp2p/p2p/security/noise"
|
|
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
|
|
multiaddr "github.com/multiformats/go-multiaddr"
|
|
)
|
|
|
|
const help = `pear [options] [<multiaddr>]
|
|
|
|
Options:
|
|
-help Output this help
|
|
-relay Run in relay mode
|
|
-reserve Reserve a slot with relay
|
|
-holepunch Enable holepunching
|
|
-via Relay to use
|
|
-with Peer to connect with
|
|
-port Port to listen on
|
|
`
|
|
|
|
func main() {
|
|
var (
|
|
helpFlag bool
|
|
relayFlag bool
|
|
reserveFlag bool
|
|
holepunchFlag bool
|
|
viaFlag string
|
|
withFlag string
|
|
portFlag string
|
|
)
|
|
|
|
flag.BoolVar(&helpFlag, "help", false, "Output help")
|
|
flag.BoolVar(&relayFlag, "relay", false, "Run in relay mode")
|
|
flag.BoolVar(&reserveFlag, "reserve", false, "Reserve a slot with relay")
|
|
flag.BoolVar(&holepunchFlag, "holepunch", false, "Enable holepunching")
|
|
flag.StringVar(&viaFlag, "via", "", "Relay to use")
|
|
flag.StringVar(&withFlag, "with", "", "Peer to connect to")
|
|
flag.StringVar(&portFlag, "port", "9000", "Port to listen on")
|
|
flag.Parse()
|
|
|
|
if helpFlag {
|
|
fmt.Printf(help)
|
|
os.Exit(0)
|
|
}
|
|
|
|
opts := []libp2p.Option{
|
|
libp2p.RandomIdentity,
|
|
libp2p.DisableMetrics(),
|
|
libp2p.Security(noise.ID, noise.New),
|
|
libp2p.Transport(tcp.NewTCPTransport),
|
|
libp2p.DefaultPeerstore,
|
|
libp2p.DefaultConnectionManager,
|
|
libp2p.DefaultMuxers,
|
|
libp2p.ListenAddrStrings(fmt.Sprintf("/ip4/0.0.0.0/tcp/%s", portFlag)),
|
|
libp2p.NATPortMap(),
|
|
libp2p.EnableRelay(),
|
|
}
|
|
|
|
if holepunchFlag {
|
|
opts = append(opts, libp2p.EnableHolePunching())
|
|
}
|
|
|
|
pear, err := libp2p.NewWithoutDefaults(opts...)
|
|
if err != nil {
|
|
log.Fatalf("failed to initialise libp2p: %s", err)
|
|
}
|
|
|
|
peerId, err := multiaddr.NewMultiaddr(
|
|
fmt.Sprintf("/p2p/%s", pear.ID().Pretty()),
|
|
)
|
|
if err != nil {
|
|
log.Fatalf("failed to create new multiaddr: %s", err)
|
|
}
|
|
|
|
for _, addr := range pear.Addrs() {
|
|
fmt.Println(addr.Encapsulate(peerId))
|
|
}
|
|
|
|
if relayFlag {
|
|
_, err = relay.New(pear)
|
|
if err != nil {
|
|
log.Fatalf("failed to instantiate the relay: %v", err)
|
|
}
|
|
}
|
|
|
|
pingService := &ping.PingService{Host: pear}
|
|
pear.SetStreamHandler(ping.ID, pingService.PingHandler)
|
|
if withFlag != "" {
|
|
if viaFlag != "" {
|
|
viaAddr, err := multiaddr.NewMultiaddr(viaFlag)
|
|
if err != nil {
|
|
log.Fatalf("via: failed to parse %s: %s", viaFlag, err)
|
|
}
|
|
|
|
viaAddrInfo, err := peerstore.AddrInfoFromP2pAddr(viaAddr)
|
|
if err != nil {
|
|
log.Fatalf("viaAddr: failed to add %s to peer store: %s", viaAddr, err)
|
|
}
|
|
|
|
if err := pear.Connect(context.Background(), *viaAddrInfo); err != nil {
|
|
log.Fatalf("pear -> viaPeer: failed to connect to %s: %s", viaAddrInfo, err)
|
|
}
|
|
|
|
withAddr, err := multiaddr.NewMultiaddr(withFlag)
|
|
if err != nil {
|
|
log.Fatalf("withAddr: failed to parse %s: %s", withFlag, err)
|
|
}
|
|
|
|
withAddrInfo, err := peerstore.AddrInfoFromP2pAddr(withAddr)
|
|
if err != nil {
|
|
log.Fatalf("withAddr: failed to add %s to peer store: %s", withAddr, err)
|
|
}
|
|
|
|
relayAddr, err := multiaddr.NewMultiaddr("/p2p/" + viaAddrInfo.ID.String() + "/p2p-circuit/p2p/" + withAddrInfo.ID.String())
|
|
if err != nil {
|
|
log.Fatalf("failed to create relayAddr: %s", err)
|
|
}
|
|
|
|
withViaInfo := peer.AddrInfo{
|
|
ID: withAddrInfo.ID,
|
|
Addrs: []multiaddr.Multiaddr{relayAddr},
|
|
}
|
|
|
|
if err := pear.Connect(context.Background(), withViaInfo); err != nil {
|
|
log.Fatalf("peer -> relayPeer: failed to connect to %s: %s", withViaInfo, err)
|
|
}
|
|
|
|
ch := pingService.Ping(context.Background(), withViaInfo.ID)
|
|
for i := 0; i < 5; i++ {
|
|
res := <-ch
|
|
fmt.Println("pinged", withAddrInfo, "in", res.RTT)
|
|
}
|
|
} else {
|
|
addr, err := multiaddr.NewMultiaddr(withFlag)
|
|
if err != nil {
|
|
log.Fatalf("failed to parse %s: %s", withFlag, err)
|
|
}
|
|
|
|
peer, err := peerstore.AddrInfoFromP2pAddr(addr)
|
|
if err != nil {
|
|
log.Fatalf("failed to add %s to peer store: %s", addr, err)
|
|
}
|
|
|
|
if reserveFlag {
|
|
_, err = client.Reserve(context.Background(), pear, *peer)
|
|
if err != nil {
|
|
log.Fatalf("reserve: failed to receive a relay reservation: %v", err)
|
|
}
|
|
}
|
|
|
|
if err := pear.Connect(context.Background(), *peer); err != nil {
|
|
log.Fatalf("failed to connect to %s: %s", peer, err)
|
|
}
|
|
|
|
ch := pingService.Ping(context.Background(), peer.ID)
|
|
for i := 0; i < 5; i++ {
|
|
res := <-ch
|
|
fmt.Println("pinged", addr, "in", res.RTT)
|
|
}
|
|
}
|
|
}
|
|
|
|
ch := make(chan os.Signal, 1)
|
|
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
|
<-ch
|
|
|
|
if err := pear.Close(); err != nil {
|
|
log.Fatalf("failed to shutdown: %s", err)
|
|
}
|
|
}
|