mirror of
https://github.com/libp2p/go-libp2p.git
synced 2025-10-05 16:17:12 +08:00

* add circuitv1 protobuf * add implementation of v1 circuit relay Intended to be used by standalone daemons and tests * remove references to go-libp2p-circuit from production code * update tests to use the in-tree v1 Relay * use go-log/v2 in relay v1 impl * use in-tree v1 relay in relay example * remove go-libp2p-circuit dep from examples go.mod, go mod tidy
113 lines
3.0 KiB
Go
113 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
|
|
"github.com/libp2p/go-libp2p"
|
|
"github.com/libp2p/go-libp2p-core/network"
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
|
|
|
relayv1 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv1/relay"
|
|
|
|
swarm "github.com/libp2p/go-libp2p-swarm"
|
|
ma "github.com/multiformats/go-multiaddr"
|
|
)
|
|
|
|
func main() {
|
|
run()
|
|
}
|
|
|
|
func run() {
|
|
// Create three libp2p hosts, enable relay client capabilities on all
|
|
// of them.
|
|
|
|
// Tell the host use relays
|
|
h1, err := libp2p.New(libp2p.EnableRelay())
|
|
if err != nil {
|
|
log.Printf("Failed to create h1: %v", err)
|
|
return
|
|
}
|
|
|
|
// Tell the host to relay connections for other peers (The ability to *use*
|
|
// a relay vs the ability to *be* a relay)
|
|
h2, err := libp2p.New(libp2p.DisableRelay())
|
|
if err != nil {
|
|
log.Printf("Failed to create h2: %v", err)
|
|
return
|
|
}
|
|
_, err = relayv1.NewRelay(h2)
|
|
if err != nil {
|
|
log.Printf("Failed to instantiate h2 relay: %v", err)
|
|
return
|
|
}
|
|
|
|
// Zero out the listen addresses for the host, so it can only communicate
|
|
// via p2p-circuit for our example
|
|
h3, err := libp2p.New(libp2p.ListenAddrs(), libp2p.EnableRelay())
|
|
if err != nil {
|
|
log.Printf("Failed to create h3: %v", err)
|
|
return
|
|
}
|
|
|
|
h2info := peer.AddrInfo{
|
|
ID: h2.ID(),
|
|
Addrs: h2.Addrs(),
|
|
}
|
|
|
|
// Connect both h1 and h3 to h2, but not to each other
|
|
if err := h1.Connect(context.Background(), h2info); err != nil {
|
|
log.Printf("Failed to connect h1 and h2: %v", err)
|
|
return
|
|
}
|
|
if err := h3.Connect(context.Background(), h2info); err != nil {
|
|
log.Printf("Failed to connect h3 and h2: %v", err)
|
|
return
|
|
}
|
|
|
|
// Now, to test things, let's set up a protocol handler on h3
|
|
h3.SetStreamHandler("/cats", func(s network.Stream) {
|
|
log.Println("Meow! It worked!")
|
|
s.Close()
|
|
})
|
|
|
|
_, err = h1.NewStream(context.Background(), h3.ID(), "/cats")
|
|
if err == nil {
|
|
log.Println("Didnt actually expect to get a stream here. What happened?")
|
|
return
|
|
}
|
|
log.Printf("Okay, no connection from h1 to h3: %v", err)
|
|
log.Println("Just as we suspected")
|
|
|
|
// Creates a relay address to h3 using h2 as the relay
|
|
relayaddr, err := ma.NewMultiaddr("/p2p/" + h2.ID().Pretty() + "/p2p-circuit/ipfs/" + h3.ID().Pretty())
|
|
if err != nil {
|
|
log.Println(err)
|
|
return
|
|
}
|
|
|
|
// Since we just tried and failed to dial, the dialer system will, by default
|
|
// prevent us from redialing again so quickly. Since we know what we're doing, we
|
|
// can use this ugly hack (it's on our TODO list to make it a little cleaner)
|
|
// to tell the dialer "no, its okay, let's try this again"
|
|
h1.Network().(*swarm.Swarm).Backoff().Clear(h3.ID())
|
|
|
|
h3relayInfo := peer.AddrInfo{
|
|
ID: h3.ID(),
|
|
Addrs: []ma.Multiaddr{relayaddr},
|
|
}
|
|
if err := h1.Connect(context.Background(), h3relayInfo); err != nil {
|
|
log.Printf("Failed to connect h1 and h3: %v", err)
|
|
return
|
|
}
|
|
|
|
// Woohoo! we're connected!
|
|
s, err := h1.NewStream(context.Background(), h3.ID(), "/cats")
|
|
if err != nil {
|
|
log.Println("huh, this should have worked: ", err)
|
|
return
|
|
}
|
|
|
|
s.Read(make([]byte, 1)) // block until the handler closes the stream
|
|
}
|