ceremonyclient/go-libp2p/p2p/protocol/circuitv2/client/transport.go
2024-10-12 11:55:17 -07:00

102 lines
2.5 KiB
Go

package client
import (
"context"
"fmt"
"io"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/transport"
ma "github.com/multiformats/go-multiaddr"
)
var circuitProtocol = ma.ProtocolWithCode(ma.P_CIRCUIT)
var circuitAddr, _ = ma.Cast(circuitProtocol.VCode)
// AddTransport constructs a new p2p-circuit/v2 client and adds it as a transport to the
// host network
func AddTransport(h host.Host, upgrader transport.Upgrader) error {
n, ok := h.Network().(transport.TransportNetwork)
if !ok {
return fmt.Errorf("%v is not a transport network", h.Network())
}
c, err := New(h, upgrader)
if err != nil {
return fmt.Errorf("error constructing circuit client: %w", err)
}
err = n.AddTransport(c)
if err != nil {
return fmt.Errorf("error adding circuit transport: %w", err)
}
err = n.Listen(circuitAddr)
if err != nil {
return fmt.Errorf("error listening to circuit addr: %w", err)
}
c.Start()
return nil
}
// Transport interface
var _ transport.Transport = (*Client)(nil)
var _ io.Closer = (*Client)(nil)
func (c *Client) Dial(ctx context.Context, a ma.Multiaddr, p peer.ID) (transport.CapableConn, error) {
connScope, err := c.host.Network().ResourceManager().OpenConnection(network.DirOutbound, false, a)
if err != nil {
return nil, err
}
conn, err := c.dialAndUpgrade(ctx, a, p, connScope)
if err != nil {
connScope.Done()
return nil, err
}
return conn, nil
}
func (c *Client) dialAndUpgrade(ctx context.Context, a ma.Multiaddr, p peer.ID, connScope network.ConnManagementScope) (transport.CapableConn, error) {
if err := connScope.SetPeer(p); err != nil {
return nil, err
}
conn, err := c.dial(ctx, a, p)
if err != nil {
return nil, err
}
conn.tagHop()
cc, err := c.upgrader.Upgrade(ctx, c, conn, network.DirOutbound, p, connScope)
if err != nil {
return nil, err
}
return capableConn{cc.(capableConnWithStat)}, nil
}
func (c *Client) CanDial(addr ma.Multiaddr) bool {
_, err := addr.ValueForProtocol(ma.P_CIRCUIT)
return err == nil
}
func (c *Client) Listen(addr ma.Multiaddr) (transport.Listener, error) {
// TODO connect to the relay and reserve slot if specified
if _, err := addr.ValueForProtocol(ma.P_CIRCUIT); err != nil {
return nil, err
}
return c.upgrader.UpgradeListener(c, c.Listener()), nil
}
func (c *Client) Protocols() []int {
return []int{ma.P_CIRCUIT}
}
func (c *Client) Proxy() bool {
return true
}