libp2p.transport package

Subpackages

Submodules

libp2p.transport.exceptions module

exception libp2p.transport.exceptions.MuxerUpgradeFailure

Bases: UpgradeFailure

exception libp2p.transport.exceptions.OpenConnectionError

Bases: BaseLibp2pError

exception libp2p.transport.exceptions.SecurityUpgradeFailure

Bases: UpgradeFailure

exception libp2p.transport.exceptions.UpgradeFailure

Bases: BaseLibp2pError

libp2p.transport.upgrader module

class libp2p.transport.upgrader.TransportUpgrader(secure_transports_by_protocol: Mapping[TProtocol, object], muxer_transports_by_protocol: Mapping[TProtocol, type[object]], negotiate_timeout: int = 30)

Bases: object

muxer_multistream: MuxerMultistream
security_multistream: SecurityMultistream
async upgrade_connection(conn: ISecureConn, peer_id: ID) IMuxedConn

Upgrade secured connection to a muxed connection.

async upgrade_security(raw_conn: IRawConnection, is_initiator: bool, peer_id: ID | None = None) ISecureConn

Upgrade conn to a secured connection.

Module contents

class libp2p.transport.DemultiplexedConnType(value)

Bases: IntEnum

Mirrors tcpreuse.DemultiplexedConnType from go-libp2p.

Used to route an incoming TCP connection to the correct transport listener after peeking at the first 3 bytes of the stream.

HTTP = 2

WebSocket (plain) connections start with an HTTP upgrade request. Matches GET / HEAD / POST / PUT / DELETE / CONNECT / OPTIONS / TRACE / PATCH and also PRI (HTTP/2 cleartext preface).

MULTISTREAM_SELECT = 1

Raw libp2p TCP connections start with the multistream-select header \\x13/multistream/1.0.0\\n. The first 3 bytes are \\x13/m.

TLS = 3

WebSocket-Secure (WSS) connections are wrapped in TLS. Matches TLS 1.0–1.3 ClientHello record headers.

UNKNOWN = 0
class libp2p.transport.DemultiplexedListener(conn_type: DemultiplexedConnType, recv_channel: MemoryReceiveChannel[PeekableStream], listen_maddr: Multiaddr, close_callback: Callable[[DemultiplexedConnType], None], conn_handler: Callable[[Stream], Awaitable[None]] | None = None)

Bases: IListener

A listener that receives pre-classified connections from PortDemultiplexer.

Each instance holds one end of a trio.open_memory_channel() and exposes an accept() async iterator consumed by the transport that registered for this connection type.

When a conn_handler is provided, listen() spawns a background Trio task that drains the channel and calls the handler for every incoming connection. This is the Trio equivalent of the goroutine that reads from a buffered chan *connWithScope in go-libp2p’s demultiplexedListener.

Mirrors tcpreuse.demultiplexedListener from go-libp2p.

async close() None

Close this demultiplexed listener and remove it from PortDemultiplexer.

async connections() AsyncIterator[PeekableStream]

Async-iterate over pre-classified connections.

get_addrs() tuple[Multiaddr, ...]

Retrieve the list of addresses on which the listener is active.

Returns

tuple[Multiaddr, …]

A tuple of multiaddresses.

async listen(maddr: Multiaddr) None

Start the connection-drain loop (no-op when no handler is registered).

When a conn_handler was supplied, this spawns a Trio system task that continuously reads PeekableStream objects from the channel and calls the handler for each one. The actual TCP socket is created by PortDemultiplexer — this method only starts the consumer side.

class libp2p.transport.PortDemultiplexer(host: str, port: int)

Bases: IListener

Enables sharing a single TCP port between multiple transports.

Each transport calls demultiplexed_listen() with its expected DemultiplexedConnType. Internally, one OS-level TCP socket is opened and a background task classifies every new connection by peeking at its first 3 bytes, then routes it into the matching DemultiplexedListener’s channel.

Mirrors tcpreuse.PortDemultiplexer from go-libp2p (p2p/transport/tcpreuse).

Usage:

port_demux = PortDemultiplexer("0.0.0.0", 4001)

# TCP transport registers for raw libp2p connections
tcp_listener = port_demux.demultiplexed_listen(
    maddr, DemultiplexedConnType.MULTISTREAM_SELECT
)

# WebSocket transport registers for HTTP-upgrade connections
ws_listener = port_demux.demultiplexed_listen(
    maddr, DemultiplexedConnType.HTTP
)

await port_demux.listen(maddr)   # binds the socket and starts routing
async close() None

Close all registered listeners and the underlying TCP socket.

demultiplexed_listen(maddr: Multiaddr, conn_type: DemultiplexedConnType, conn_handler: Callable[[Stream], Awaitable[None]] | None = None) DemultiplexedListener

Register a listener for conn_type connections on this shared port.

Must be called before listen(). Raises ValueError if a listener for the same conn_type is already registered (mirrors tcpreuse.ErrListenerExists).

Parameters:
  • maddr – The multiaddress that will be bound (used for DemultiplexedListener.get_addrs()).

  • conn_type – The connection type this listener should receive.

  • conn_handler – Optional async callable called per connection. When provided, DemultiplexedListener.listen() starts a background drain task that calls this handler for each classified connection.

Returns:

A DemultiplexedListener whose connections() yields classified connections.

Raises:

ValueError – If conn_type already has a registered listener.

get_addrs() tuple[Multiaddr, ...]

Return the multiaddresses this listener is bound to.

get_listener(conn_type: DemultiplexedConnType) DemultiplexedListener | None

Return the listener registered for this conn_type, or None.

has_listener(conn_type: DemultiplexedConnType) bool

Return True if a listener is registered for this conn_type.

host: str
async listen(maddr: Multiaddr) None

Bind to the port and start the demultiplexing loop.

Subsequent calls are no-ops if the socket is already bound (mirrors go-libp2p where each transport calls DemultiplexedListen and the underlying socket is only created once per address).

listen_maddr: Multiaddr | None
port: int
class libp2p.transport.TCP(*, dns_resolution_timeout: float = 5.0, dns_max_retries: int = 3)

Bases: ITransport

can_dial(maddr: Multiaddr) bool

Return True if this TCP transport can dial the given multiaddr.

Accepts pure TCP addresses (/ip4/…/tcp/… or /ip6/…/tcp/…) but rejects WebSocket addresses (/ws, /wss) even though they use TCP underneath, so the TransportManager routes those to WebsocketTransport instead.

Parameters:

maddr – The multiaddress to check.

Returns:

True if this transport handles the multiaddr.

can_listen(maddr: Multiaddr) bool

Return True if this TCP transport can listen on the given multiaddr.

Parameters:

maddr – The multiaddress to check.

Returns:

True if this transport can listen on the multiaddr.

create_listener(handler_function: Callable[[ReadWriteCloser], Awaitable[None]]) TCPListener

Create listener on transport.

Parameters:

handler_function – a function called when a new connection is received that takes a connection as argument which implements interface-connection

Returns:

a listener object that implements listener_interface.py

async dial(maddr: Multiaddr) IRawConnection

Dial a transport to peer listening on multiaddr.

Resolves DNS (dns, dns4, dns6, dnsaddr) before dialing (Phase 3.1).

Parameters:

maddr – multiaddr of peer

Returns:

RawConnection if successful

Raises:

OpenConnectionError – raised when failed to open connection

protocols() list[str]

Return the list of multiaddr protocol names handled by TCP transport.

Returns:

[“tcp”]

class libp2p.transport.TransportManager(port_demux: PortDemultiplexer | None = None, port_demuxers: dict[tuple[str, int], PortDemultiplexer] | None = None)

Bases: object

Maintains an ordered list of ITransport instances and provides routing helpers used by the Swarm.

Transports are checked in the order they were added. For dialing, the first transport whose can_dial() returns True is selected. For listening, the same logic applies via can_listen().

This is the Python equivalent of go-libp2p’s Swarm.TransportForDialing / Swarm.TransportForListening pair.

Parameters:

port_demux – Optional PortDemultiplexer for sharing a single TCP port between multiple transports (TCP + WS). Mirrors the sharedTCP *tcpreuse.PortDemultiplexer parameter passed to NewTCPTransport / websocket.New in go-libp2p.

add_listen_addr(maddr: Multiaddr, conn_handler: Callable[[ReadWriteCloser], Awaitable[None]]) IListener | None

Create and return a listener for maddr.

Mirrors Swarm.AddListenAddr() from go-libp2p.

When a PortDemultiplexer was supplied at construction and the address is TCP-based, the manager calls demultiplexed_listen() on the appropriate DemultiplexedConnType so that TCP and WebSocket transports can share the same OS socket.

For non-TCP transports (e.g. QUIC) the transport’s own create_listener() is used directly.

Parameters:
  • maddr – The multiaddress to listen on.

  • conn_handler – Handler called for every accepted connection.

Returns:

An IListener, or None if no transport supports maddr.

add_transport(transport: ITransport) None

Append a transport to the routing list.

Parameters:

transport – A transport instance implementing ITransport.

add_transports(transports: list[ITransport]) None

Convenience helper to register multiple transports at once.

Parameters:

transports – List of transport instances.

async close_all() None

Close all registered transports concurrently.

Called by close() during teardown.

get_transports() list[ITransport]

Return a shallow copy of the registered transports list.

Returns:

List of registered ITransport instances.

has_transport_for(maddr: Multiaddr) bool

Return True if any registered transport can dial maddr.

Parameters:

maddr – The multiaddress to check.

Returns:

True if a matching transport exists, False otherwise.

listen_on(maddr: Multiaddr, conn_handler: Callable[[ReadWriteCloser], Awaitable[None]]) IListener | None

Deprecated alias for add_listen_addr().

set_background_nursery(nursery: Nursery) None

Pass the Swarm’s background nursery to all transports that need one.

Called once by run() as soon as the background nursery is ready. Delegates to every transport that exposes a set_background_nursery method (currently QUIC and WebSocket).

Parameters:

nursery – The trio nursery to share with transports.

set_swarm(swarm: object) None

Pass a reference to the Swarm to all transports that need it.

Called once by run(). Needed by QUICTransport so it can call add_conn() for inbound QUIC connections.

Parameters:

swarm – The Swarm instance.

transport_for_dialing(maddr: Multiaddr) ITransport | None

Return the first registered transport that can dial maddr, or None.

The manager first performs a cheap pre-filter using each transport’s protocols() list (set intersection), and only calls can_dial() when there is at least one protocol name overlap. This avoids unnecessary work when many transports are registered.

This is the Python equivalent of go-libp2p’s Swarm.TransportForDialing().

Parameters:

maddr – The multiaddress to route.

Returns:

The matching transport, or None if no transport can handle the address.

transport_for_listening(maddr: Multiaddr) ITransport | None

Return the first registered transport that can listen on maddr, or None.

Uses the same two-step pre-filter logic as transport_for_dialing().

This is the Python equivalent of go-libp2p’s Swarm.TransportForListening().

Parameters:

maddr – The multiaddress to route.

Returns:

The matching transport, or None if no transport can handle the address.

class libp2p.transport.WebsocketTransport(upgrader: TransportUpgrader, config: WebsocketConfig | None = None, tls_client_config: SSLContext | None = None, tls_server_config: SSLContext | None = None, handshake_timeout: float | None = None)

Bases: ITransport

Libp2p WebSocket transport implementation with production features:

Features: - WS and WSS protocol support with configurable TLS - Connection management with limits and tracking - Flow control and buffer management - SOCKS5 proxy support - Proper error handling and connection cleanup - Configurable timeouts and limits - Connection state monitoring - Concurrent connection handling

can_dial(maddr: Multiaddr) bool

Return True if this WebSocket transport can dial the given multiaddr.

Checks whether the multiaddr matches the WebSocket multiaddr pattern (e.g. /ip4/.../tcp/.../ws or /ip4/.../tcp/.../wss).

The check is purely protocol-level (no I/O); it changed from async to sync to satisfy the ITransport interface.

Parameters:

maddr – The multiaddress to check.

Returns:

True if this transport handles the multiaddr.

can_listen(maddr: Multiaddr) bool

Return True if this WebSocket transport can listen on the given multiaddr.

Parameters:

maddr – The multiaddress to check.

Returns:

True if this transport can listen on the multiaddr.

create_listener(handler: Callable[[ReadWriteCloser], Awaitable[None]]) IListener

Create a WebSocket listener with the given handler.

Args:

handler: Connection handler function

Returns:

A WebSocket listener

Raises:

ValueError – If configuration validation fails

async dial(maddr: Multiaddr) RawConnection

Dial a WebSocket connection to the given multiaddr.

Resolves DNS (dns, dns4, dns6, dnsaddr) before dialing (Phase 3.1).

Args:

maddr: The multiaddr to dial (e.g., /ip4/127.0.0.1/tcp/8000/ws)

Returns:

An upgraded RawConnection

Raises:
  • OpenConnectionError – If connection fails, cannot dial the multiaddr, connection upgrade fails, or maximum connections reached

  • ValueError – If multiaddr is invalid or cannot be parsed

async get_connections() dict[str, P2PWebSocketConnection]

Get all active connections.

get_listeners() set[WebsocketListener]

Get all active listeners.

get_stats() dict[str, int]

Get transport statistics.

protocols() list[str]

Return the list of multiaddr protocol names handled by WebSocket transport.

Returns:

[“ws”, “wss”]

resolve(maddr: Multiaddr) list[Multiaddr]

Resolve a WebSocket multiaddr to its concrete addresses. Currently, just validates and returns the input multiaddr.

Args:

maddr: The multiaddr to resolve

Returns:

List containing the original multiaddr

set_background_nursery(nursery: Nursery) None

Set the nursery to use for background tasks (called by Swarm).

set_peer_id(peer_id: ID) None

Set the peer ID of the host.

libp2p.transport.identify_conn_type(prefix: bytes) DemultiplexedConnType

Classify a connection from its first 3 bytes.

Directly mirrors tcpreuse.identifyConnType / IsMultistreamSelect / IsHTTP / IsTLS from go-libp2p.

Parameters:

prefix – Exactly 3 bytes read from the start of the stream.

Returns:

The detected DemultiplexedConnType.