Skip to content

Commit ffcf9f5

Browse files
authored
Merge branch 'main' into feature/tls-example
2 parents 9a514ef + 35889ad commit ffcf9f5

File tree

150 files changed

+26354
-2330
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

150 files changed

+26354
-2330
lines changed

.github/workflows/tox.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ jobs:
6969
cd tests/interop/nim_libp2p
7070
./scripts/setup_nim_echo.sh
7171
72+
- name: Setup Node.js for interop testing
73+
if: matrix.toxenv == 'interop'
74+
uses: actions/setup-node@v4
75+
with:
76+
node-version: '22'
77+
7278
- run: |
7379
uv venv venv
7480
source venv/bin/activate

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ coverage.xml
4545
*.cover
4646
.pytest_cache/
4747

48+
# Test result files
49+
tests/**/results/*.json
50+
tests/**/results/*.xml
51+
tests/**/results/*.html
52+
4853
# Translations
4954
*.mo
5055
*.pot

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@
310310
"tests.factories",
311311
# Mocked ONLY for Sphinx/autodoc: this module does not exist in the codebase
312312
# but some doc tools may try to import it. No real code references this import.
313-
"libp2p.relay.circuit_v2.lib"
313+
"libp2p.relay.circuit_v2.lib",
314314
]
315315

316316
# Documents to append as an appendix to all manuals.

docs/examples.interop.rst

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
Interoperability Testing
2+
========================
3+
4+
This example provides a standalone console script for testing libp2p ping functionality
5+
without Docker or Redis dependencies. It supports both listener and dialer roles and
6+
measures ping RTT and handshake times.
7+
8+
Usage
9+
-----
10+
11+
Run as listener (waits for connection):
12+
13+
.. code-block:: console
14+
15+
$ python -m examples.interop.local_ping_test --listener --port 8000
16+
Listener ready, listening on:
17+
/ip4/127.0.0.1/tcp/8000/p2p/Qm...
18+
Waiting for dialer to connect...
19+
20+
Run as dialer (connects to listener):
21+
22+
.. code-block:: console
23+
24+
$ python -m examples.interop.local_ping_test --dialer --destination /ip4/127.0.0.1/tcp/8000/p2p/Qm...
25+
Connecting to listener at: /ip4/127.0.0.1/tcp/8000/p2p/Qm...
26+
Connected successfully
27+
Performing ping test
28+
{"handshakePlusOneRTTMillis": 15.2, "pingRTTMilllis": 2.1}
29+
30+
Options
31+
-------
32+
33+
- ``--listener``: Run as listener (wait for connection)
34+
- ``--dialer``: Run as dialer (connect to listener)
35+
- ``--destination ADDR``: Destination multiaddr (required for dialer)
36+
- ``--port PORT``: Port number (0 = auto-select)
37+
- ``--transport {tcp,ws,quic-v1}``: Transport protocol (default: tcp)
38+
- ``--muxer {mplex,yamux}``: Stream muxer (default: mplex)
39+
- ``--security {noise,plaintext}``: Security protocol (default: noise)
40+
- ``--test-timeout SECONDS``: Test timeout in seconds (default: 180)
41+
- ``--debug``: Enable debug logging
42+
43+
The full source code for this example is below:
44+
45+
.. literalinclude:: ../examples/interop/local_ping_test.py
46+
:language: python
47+
:linenos:

docs/examples.nat.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
examples.nat package
2+
====================
3+
4+
Submodules
5+
----------
6+
7+
examples.nat.dialer module
8+
--------------------------
9+
10+
.. automodule:: examples.nat.dialer
11+
:members:
12+
:show-inheritance:
13+
:undoc-members:
14+
15+
examples.nat.listener module
16+
----------------------------
17+
18+
.. automodule:: examples.nat.listener
19+
:members:
20+
:show-inheritance:
21+
:undoc-members:
22+
23+
examples.nat.relay module
24+
-------------------------
25+
26+
.. automodule:: examples.nat.relay
27+
:members:
28+
:show-inheritance:
29+
:undoc-members:
30+
31+
Module contents
32+
---------------
33+
34+
.. automodule:: examples.nat
35+
:members:
36+
:show-inheritance:
37+
:undoc-members:

docs/examples.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ Examples
1111
examples.echo
1212
examples.echo_quic
1313
examples.ping
14+
examples.interop
1415
examples.pubsub
1516
examples.bitswap
1617
examples.circuit_relay
1718
examples.kademlia
1819
examples.mDNS
20+
examples.nat
1921
examples.rendezvous
2022
examples.random_walk
2123
examples.multiple_connections
24+
examples.websocket

docs/examples.websocket.rst

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
WebSocket Transport Examples
2+
============================
3+
4+
This guide demonstrates how to use the WebSocket transport in py-libp2p, including WS (WebSocket) and WSS (WebSocket Secure) protocols, SOCKS proxy support, AutoTLS, and advanced configuration options.
5+
6+
Quick Start
7+
-----------
8+
9+
Basic WebSocket transport setup:
10+
11+
.. code-block:: python
12+
13+
from libp2p import new_host
14+
from libp2p.transport.websocket import WebsocketTransport, WebsocketConfig
15+
from libp2p.transport.upgrader import TransportUpgrader
16+
from libp2p.security.insecure.transport import PLAINTEXT_PROTOCOL_ID, InsecureTransport
17+
from libp2p.stream_muxer.yamux.yamux import Yamux
18+
from libp2p.custom_types import TProtocol
19+
from libp2p.crypto.rsa import create_new_key_pair
20+
from multiaddr import Multiaddr
21+
22+
# Generate a key pair
23+
key_pair = create_new_key_pair()
24+
25+
# Create upgrader with security and muxer
26+
upgrader = TransportUpgrader(
27+
secure_transports_by_protocol={
28+
TProtocol(PLAINTEXT_PROTOCOL_ID): InsecureTransport(key_pair)
29+
},
30+
muxer_transports_by_protocol={TProtocol("/yamux/1.0.0"): Yamux}
31+
)
32+
33+
# Create WebSocket transport
34+
config = WebsocketConfig()
35+
transport = WebsocketTransport(upgrader, config=config)
36+
37+
# Create host with WebSocket transport
38+
# Note: new_host handles transport creation internally if not overridden,
39+
# but this shows how to set it up manually if needed.
40+
host = new_host(
41+
listen_addrs=[Multiaddr("/ip4/127.0.0.1/tcp/8080/ws")]
42+
)
43+
44+
WS vs WSS
45+
---------
46+
47+
**WS (Insecure WebSocket):**
48+
49+
Use for development and testing. No TLS encryption:
50+
51+
.. code-block:: python
52+
53+
ws_addr = Multiaddr("/ip4/127.0.0.1/tcp/8080/ws")
54+
host = new_host(listen_addrs=[ws_addr])
55+
56+
**WSS (Secure WebSocket):**
57+
58+
Use for production. Requires TLS configuration:
59+
60+
.. code-block:: python
61+
62+
import ssl
63+
64+
# Create TLS context
65+
tls_context = ssl.create_default_context()
66+
tls_context.check_hostname = False
67+
tls_context.verify_mode = ssl.CERT_NONE # For testing only
68+
69+
# Configure transport with TLS
70+
config = WebsocketConfig(tls_server_config=tls_context)
71+
transport = WebsocketTransport(upgrader, config=config)
72+
73+
wss_addr = Multiaddr("/ip4/127.0.0.1/tcp/8080/wss")
74+
host = new_host(listen_addrs=[wss_addr])
75+
76+
SOCKS Proxy Configuration
77+
-------------------------
78+
79+
**Using Proxy Factory Function:**
80+
81+
.. code-block:: python
82+
83+
from libp2p.transport.websocket import WithProxy
84+
85+
# Configure with SOCKS5 proxy
86+
config = WithProxy(
87+
proxy_url="socks5://proxy.example.com:1080",
88+
auth=("username", "password") # Optional
89+
)
90+
transport = WebsocketTransport(upgrader, config=config)
91+
92+
**Using Environment Variables:**
93+
94+
.. code-block:: python
95+
96+
from libp2p.transport.websocket import WithProxyFromEnvironment
97+
98+
# Reads HTTP_PROXY or HTTPS_PROXY environment variables
99+
config = WithProxyFromEnvironment()
100+
transport = WebsocketTransport(upgrader, config=config)
101+
102+
**Environment Variable Format:**
103+
104+
.. code-block:: bash
105+
106+
export HTTP_PROXY=socks5://proxy.example.com:1080
107+
export HTTPS_PROXY=socks5://proxy.example.com:1080
108+
109+
AutoTLS Configuration
110+
---------------------
111+
112+
AutoTLS automatically generates and manages TLS certificates for browser integration:
113+
114+
.. code-block:: python
115+
116+
from libp2p.transport.websocket import WithAutoTLS, AutoTLSConfig
117+
118+
autotls_config = AutoTLSConfig(
119+
enabled=True,
120+
default_domain="localhost",
121+
cert_validity_days=365
122+
)
123+
124+
config = WithAutoTLS(autotls_config)
125+
transport = WebsocketTransport(upgrader, config=config)
126+
127+
**Browser Integration:**
128+
129+
AutoTLS is particularly useful for browser-based applications where you need trusted certificates for WebSocket connections.
130+
131+
Advanced TLS Configuration
132+
---------------------------
133+
134+
For production deployments with custom certificates:
135+
136+
.. code-block:: python
137+
138+
from libp2p.transport.websocket import WithAdvancedTLS
139+
from libp2p.transport.websocket.tls_config import (
140+
TLSConfig,
141+
CertificateValidationMode
142+
)
143+
144+
tls_config = TLSConfig(
145+
cert_file="path/to/cert.pem",
146+
key_file="path/to/key.pem",
147+
ca_file="path/to/ca.pem",
148+
validation_mode=CertificateValidationMode.STRICT
149+
)
150+
151+
config = WithAdvancedTLS(tls_config)
152+
transport = WebsocketTransport(upgrader, config=config)
153+
154+
Connection Management
155+
---------------------
156+
157+
Configure connection limits and timeouts:
158+
159+
.. code-block:: python
160+
161+
from libp2p.transport.websocket import (
162+
WithMaxConnections,
163+
WithHandshakeTimeout
164+
)
165+
166+
config = WebsocketConfig(
167+
max_connections=1000,
168+
handshake_timeout=15.0,
169+
max_buffered_amount=4 * 1024 * 1024, # 4MB
170+
max_message_size=32 * 1024 * 1024 # 32MB
171+
)
172+
173+
transport = WebsocketTransport(upgrader, config=config)
174+
175+
**Monitoring Connection Statistics:**
176+
177+
.. code-block:: python
178+
179+
# Get transport statistics
180+
stats = transport.get_stats()
181+
print(f"Total connections: {stats['total_connections']}")
182+
print(f"Current connections: {stats['current_connections']}")
183+
print(f"Failed connections: {stats['failed_connections']}")
184+
185+
# Get connection details
186+
connections = await transport.get_connections()
187+
for conn_id, conn in connections.items():
188+
conn_stats = conn.get_stats()
189+
print(f"Connection {conn_id}: {conn_stats}")
190+
191+
Complete Example
192+
----------------
193+
194+
A complete example demonstrating WebSocket transport with all features:
195+
196+
.. literalinclude:: ../examples/websocket/websocket_demo.py
197+
:language: python
198+
:linenos:
199+
200+
Multiaddr Formats
201+
-----------------
202+
203+
WebSocket transport supports various multiaddr formats:
204+
205+
- **WS (Insecure):** ``/ip4/127.0.0.1/tcp/8080/ws``
206+
- **WSS (Secure):** ``/ip4/127.0.0.1/tcp/8080/wss``
207+
- **TLS/WS Format:** ``/ip4/127.0.0.1/tcp/8080/tls/ws``
208+
- **IPv6:** ``/ip6/::1/tcp/8080/ws``
209+
- **DNS:** ``/dns/example.com/tcp/443/wss``
210+
211+
Production Considerations
212+
--------------------------
213+
214+
1. **Security:**
215+
- Always use WSS in production
216+
- Use proper CA-signed certificates
217+
- Enable certificate validation
218+
- AutoTLS is for development/testing only
219+
220+
2. **Performance:**
221+
- Configure appropriate connection limits
222+
- Set reasonable timeouts
223+
- Monitor connection statistics
224+
- Use connection pooling for high-traffic scenarios
225+
226+
3. **Error Handling:**
227+
- Handle ``OpenConnectionError`` for connection failures
228+
- Implement retry logic for transient failures
229+
- Monitor failed connection counts
230+
231+
4. **Proxy Configuration:**
232+
- Use environment variables for flexible deployment
233+
- Test proxy connectivity before production deployment
234+
- Monitor proxy connection statistics
235+
236+
See Also
237+
--------
238+
239+
- :doc:`libp2p.transport.websocket` - Full API documentation
240+
- :doc:`examples.echo` - Basic echo protocol example
241+
- :doc:`examples.echo_quic` - QUIC transport example for comparison

0 commit comments

Comments
 (0)