package relay import ( "fmt" "net" "time" "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/network" "github.com/libp2p/go-libp2p-core/peer" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr-net" ) type Conn struct { stream network.Stream remote peer.AddrInfo host host.Host } type NetAddr struct { Relay string Remote string } func (n *NetAddr) Network() string { return "libp2p-circuit-relay" } func (n *NetAddr) String() string { return fmt.Sprintf("relay[%s-%s]", n.Remote, n.Relay) } func (c *Conn) Close() error { c.untagHop() return c.stream.Reset() } func (c *Conn) Read(buf []byte) (int, error) { return c.stream.Read(buf) } func (c *Conn) Write(buf []byte) (int, error) { return c.stream.Write(buf) } func (c *Conn) SetDeadline(t time.Time) error { return c.stream.SetDeadline(t) } func (c *Conn) SetReadDeadline(t time.Time) error { return c.stream.SetReadDeadline(t) } func (c *Conn) SetWriteDeadline(t time.Time) error { return c.stream.SetWriteDeadline(t) } func (c *Conn) RemoteAddr() net.Addr { return &NetAddr{ Relay: c.stream.Conn().RemotePeer().Pretty(), Remote: c.remote.ID.Pretty(), } } // Increment the underlying relay connection tag by 1, thus increasing its protection from // connection pruning. This ensures that connections to relays are not accidentally closed, // by the connection manager, taking with them all the relayed connections (that may themselves // be protected). func (c *Conn) tagHop() { c.host.ConnManager().UpsertTag(c.stream.Conn().RemotePeer(), "relay-hop-stream", incrementTag) } // Decrement the underlying relay connection tag by 1; this is performed when we close the // relayed connection. func (c *Conn) untagHop() { c.host.ConnManager().UpsertTag(c.stream.Conn().RemotePeer(), "relay-hop-stream", decrementTag) } // TODO: is it okay to cast c.Conn().RemotePeer() into a multiaddr? might be "user input" func (c *Conn) RemoteMultiaddr() ma.Multiaddr { // TODO: We should be able to do this directly without converting to/from a string. relayAddr, err := ma.NewComponent( ma.ProtocolWithCode(ma.P_P2P).Name, c.stream.Conn().RemotePeer().Pretty(), ) if err != nil { panic(err) } return ma.Join(c.stream.Conn().RemoteMultiaddr(), relayAddr, circuitAddr) } func (c *Conn) LocalMultiaddr() ma.Multiaddr { return c.stream.Conn().LocalMultiaddr() } func (c *Conn) LocalAddr() net.Addr { na, err := manet.ToNetAddr(c.stream.Conn().LocalMultiaddr()) if err != nil { log.Error("failed to convert local multiaddr to net addr:", err) return nil } return na }