fix: refine selection of quic transport while init

This commit is contained in:
Akash Mondal
2025-08-31 16:07:41 +00:00
parent 186113968e
commit 9749be6574
6 changed files with 38 additions and 72 deletions

View File

@ -1,3 +1,5 @@
import logging
from libp2p.transport.quic.utils import is_quic_multiaddr
from typing import Any
from libp2p.transport.quic.transport import QUICTransport
@ -87,7 +89,7 @@ MUXER_YAMUX = "YAMUX"
MUXER_MPLEX = "MPLEX"
DEFAULT_NEGOTIATE_TIMEOUT = 5
logger = logging.getLogger(__name__)
def set_default_muxer(muxer_name: Literal["YAMUX", "MPLEX"]) -> None:
"""
@ -163,7 +165,8 @@ def new_swarm(
peerstore_opt: IPeerStore | None = None,
muxer_preference: Literal["YAMUX", "MPLEX"] | None = None,
listen_addrs: Sequence[multiaddr.Multiaddr] | None = None,
transport_opt: dict[Any, Any] | None = None,
enable_quic: bool = False,
quic_transport_opt: QUICTransportConfig | None = None,
) -> INetworkService:
"""
Create a swarm instance based on the parameters.
@ -174,7 +177,8 @@ def new_swarm(
:param peerstore_opt: optional peerstore
:param muxer_preference: optional explicit muxer preference
:param listen_addrs: optional list of multiaddrs to listen on
:param transport_opt: options for transport
:param enable_quic: enable quic for transport
:param quic_transport_opt: options for transport
:return: return a default swarm instance
Note: Yamux (/yamux/1.0.0) is the preferred stream multiplexer
@ -182,6 +186,10 @@ def new_swarm(
Mplex (/mplex/6.7.0) is retained for backward compatibility
but may be deprecated in the future.
"""
if not enable_quic and quic_transport_opt is not None:
logger.warning(f"QUIC config provided but QUIC not enabled, ignoring QUIC config")
quic_transport_opt = None
if key_pair is None:
key_pair = generate_new_rsa_identity()
@ -190,22 +198,17 @@ def new_swarm(
transport: TCP | QUICTransport
if listen_addrs is None:
transport_opt = transport_opt or {}
quic_config: QUICTransportConfig | None = transport_opt.get('quic_config')
if quic_config:
transport = QUICTransport(key_pair.private_key, quic_config)
if enable_quic:
transport = QUICTransport(key_pair.private_key, config=quic_transport_opt)
else:
transport = TCP()
else:
addr = listen_addrs[0]
is_quic = addr.__contains__("quic") or addr.__contains__("quic-v1")
is_quic = is_quic_multiaddr(addr)
if addr.__contains__("tcp"):
transport = TCP()
elif is_quic:
transport_opt = transport_opt or {}
quic_config = transport_opt.get('quic_config', QUICTransportConfig())
transport = QUICTransport(key_pair.private_key, quic_config)
transport = QUICTransport(key_pair.private_key, config=quic_transport_opt)
else:
raise ValueError(f"Unknown transport in listen_addrs: {listen_addrs}")
@ -266,7 +269,8 @@ def new_host(
enable_mDNS: bool = False,
bootstrap: list[str] | None = None,
negotiate_timeout: int = DEFAULT_NEGOTIATE_TIMEOUT,
transport_opt: dict[Any, Any] | None = None,
enable_quic: bool = False,
quic_transport_opt: QUICTransportConfig | None = None,
) -> IHost:
"""
Create a new libp2p host based on the given parameters.
@ -280,17 +284,23 @@ def new_host(
:param listen_addrs: optional list of multiaddrs to listen on
:param enable_mDNS: whether to enable mDNS discovery
:param bootstrap: optional list of bootstrap peer addresses as strings
:param transport_opt: optional dictionary of properties of transport
:param enable_quic: optinal choice to use QUIC for transport
:param transport_opt: optional configuration for quic transport
:return: return a host instance
"""
if not enable_quic and quic_transport_opt is not None:
logger.warning(f"QUIC config provided but QUIC not enabled, ignoring QUIC config")
swarm = new_swarm(
enable_quic=enable_quic,
key_pair=key_pair,
muxer_opt=muxer_opt,
sec_opt=sec_opt,
peerstore_opt=peerstore_opt,
muxer_preference=muxer_preference,
listen_addrs=listen_addrs,
transport_opt=transport_opt
quic_transport_opt=quic_transport_opt if enable_quic else None
)
if disc_opt is not None:

View File

@ -51,9 +51,13 @@ class QUICTransportConfig:
"""Configuration for QUIC transport."""
# Connection settings
idle_timeout: float = 30.0 # Connection idle timeout in seconds
max_datagram_size: int = 1200 # Maximum UDP datagram size
local_port: int | None = None # Local port for binding (None = random)
idle_timeout: float = 30.0 # Seconds before an idle connection is closed.
max_datagram_size: int = (
1200 # Maximum size of UDP datagrams to avoid IP fragmentation.
)
local_port: int | None = (
None # Local port to bind to. If None, a random port is chosen.
)
# Protocol version support
enable_draft29: bool = True # Enable QUIC draft-29 for compatibility
@ -102,14 +106,14 @@ class QUICTransportConfig:
"""Timeout for graceful stream close (seconds)."""
# Flow control configuration
STREAM_FLOW_CONTROL_WINDOW: int = 512 * 1024 # 512KB
STREAM_FLOW_CONTROL_WINDOW: int = 1024 * 1024 # 1MB
"""Per-stream flow control window size."""
CONNECTION_FLOW_CONTROL_WINDOW: int = 768 * 1024 # 768KB
CONNECTION_FLOW_CONTROL_WINDOW: int = 1536 * 1024 # 1.5MB
"""Connection-wide flow control window size."""
# Buffer management
MAX_STREAM_RECEIVE_BUFFER: int = 1024 * 1024 # 1MB
MAX_STREAM_RECEIVE_BUFFER: int = 2 * 1024 * 1024 # 2MB
"""Maximum receive buffer size per stream."""
STREAM_RECEIVE_BUFFER_LOW_WATERMARK: int = 64 * 1024 # 64KB

View File

@ -655,13 +655,6 @@ class QUICConnection(IRawConnection, IMuxedConn):
return info
# Legacy compatibility for existing code
async def verify_peer_identity(self) -> None:
"""
Legacy method for compatibility - delegates to security manager.
"""
await self._verify_peer_identity_with_security()
# Stream management methods (IMuxedConn interface)
async def open_stream(self, timeout: float = 5.0) -> QUICStream:

View File

@ -1163,20 +1163,3 @@ def create_quic_security_transport(
"""
return QUICTLSConfigManager(libp2p_private_key, peer_id)
# Legacy compatibility functions for existing code
def generate_libp2p_tls_config(private_key: PrivateKey, peer_id: ID) -> TLSConfig:
"""
Legacy function for compatibility with existing transport code.
Args:
private_key: libp2p private key
peer_id: libp2p peer ID
Returns:
TLS configuration
"""
generator = CertificateGenerator()
return generator.generate_certificate(private_key, peer_id)