package tcp import ( "context" logging "github.com/ipfs/go-log" peer "github.com/libp2p/go-libp2p-peer" tpt "github.com/libp2p/go-libp2p-transport" tptu "github.com/libp2p/go-libp2p-transport-upgrader" rtpt "github.com/libp2p/go-reuseport-transport" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr-net" mafmt "github.com/whyrusleeping/mafmt" ) var log = logging.Logger("tcp-tpt") // TcpTransport is the TCP transport. type TcpTransport struct { // Connection upgrader for upgrading insecure stream connections to // secure multiplex connections. Upgrader *tptu.Upgrader // Explicitly disable reuseport. DisableReuseport bool reuse rtpt.Transport } var _ tpt.Transport = &TcpTransport{} // NewTCPTransport creates a tcp transport object that tracks dialers and listeners // created. It represents an entire tcp stack (though it might not necessarily be) func NewTCPTransport(upgrader *tptu.Upgrader) *TcpTransport { return &TcpTransport{Upgrader: upgrader} } // CanDial returns true if this transport believes it can dial the given // multiaddr. func (t *TcpTransport) CanDial(addr ma.Multiaddr) bool { return mafmt.TCP.Matches(addr) } func (t *TcpTransport) maDial(ctx context.Context, raddr ma.Multiaddr) (manet.Conn, error) { if t.UseReuseport() { return t.reuse.DialContext(ctx, raddr) } var d manet.Dialer return d.DialContext(ctx, raddr) } // Dial dials the peer at the remote address. func (t *TcpTransport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (tpt.Conn, error) { conn, err := t.maDial(ctx, raddr) if err != nil { return nil, err } return t.Upgrader.UpgradeOutbound(ctx, t, conn, p) } // UseReuseport returns true if reuseport is enabled and available. func (t *TcpTransport) UseReuseport() bool { return !t.DisableReuseport && ReuseportIsAvailable() } func (t *TcpTransport) maListen(laddr ma.Multiaddr) (manet.Listener, error) { if t.UseReuseport() { return t.reuse.Listen(laddr) } return manet.Listen(laddr) } // Listen listens on the given multiaddr. func (t *TcpTransport) Listen(laddr ma.Multiaddr) (tpt.Listener, error) { list, err := t.maListen(laddr) if err != nil { return nil, err } return t.Upgrader.UpgradeListener(t, list), nil } // Protocols returns the list of terminal protocols this transport can dial. func (t *TcpTransport) Protocols() []int { return []int{ma.P_TCP} } // Proxy always returns false for the TCP transport. func (t *TcpTransport) Proxy() bool { return false } func (t *TcpTransport) String() string { return "TCP" }