QUIC library with NAT traversal
Project description
QUIC Portal (experimental)
⚠️ Warning: This library is experimental and not intended for production use.
High-performance QUIC communication library with automatic NAT traversal within Modal applications.
Features
- Automatic NAT traversal: Built-in STUN discovery and UDP hole punching, using Modal Dict for rendezvous.
- High-performance QUIC: Rust-based implementation for maximum throughput and minimal latency
- Simple API: Easy-to-use Portal class with static methods for server/client creation. WebSocket-style messaging.
Installation
# Install from PyPi (only certain wheels built)
pip install ...
# Install from source (requires Rust toolchain)
git clone <repository>
cd quic-portal
pip install .
Quick Start
Usage with Modal
import asyncio
import modal
from quic_portal import Portal
app = modal.App("my-quic-app")
@app.function()
async def server_function(coord_dict: modal.Dict):
# Create server with automatic NAT traversal
portal = await Portal.create_server(dict=coord_dict, local_port=5555)
# Receive and echo messages
while True:
data = await portal.recv(timeout_ms=10000)
if data:
message = data.decode("utf-8")
print(f"Received: {message}")
await portal.send(f"Echo: {message}".encode("utf-8"))
@app.function()
async def client_function(coord_dict: modal.Dict):
# Send messages
await portal.send(b"Hello, QUIC!")
response = await portal.recv(timeout_ms=5000)
if response:
print(f"Got response: {response.decode('utf-8')}")
@app.local_entrypoint()
async def main(local: bool = False):
# Create ephemeral coordination dict
async with modal.Dict.ephemeral() as coord_dict:
# Start server
server_task = await server_function.spawn.aio(coord_dict)
# Run client
if local:
# Run test between local environment and remote container.
await client_function.local(coord_dict)
else:
# Run test between two containers.
await client_function.remote.aio(coord_dict)
server_task.cancel()
Manual NAT Traversal
For advanced use cases where you handle NAT traversal yourself, or the server has a public IP:
from quic_portal import Portal
# After NAT hole punching is complete...
# Server side
server = Portal(local_port=5555)
await server.listen(5555)
# Client side
client = Portal(local_port=5556)
await client.connect("server_ip", 5555, 5556)
# WebSocket-style messaging
await client.send(b"Hello!")
response = await server.recv(timeout_ms=1000)
API Reference
Portal Class
Static Methods
Portal.create_server(dict, local_port=5555, stun_server=("stun.ekiga.net", 3478), punch_timeout=15)
Create a server portal with automatic NAT traversal.
Parameters:
dict(modal.Dict): Modal Dict for peer coordinationlocal_port(int): Local port for QUIC server (default: 5555)stun_server(tuple): STUN server for NAT discovery (default: ("stun.ekiga.net", 3478))punch_timeout(int): Timeout in seconds for NAT punching (default: 15)
Returns: Connected Portal instance ready for communication
Portal.create_client(dict, local_port=5556, stun_server=("stun.ekiga.net", 3478), punch_timeout=15)
Create a client portal with automatic NAT traversal.
Parameters:
dict(modal.Dict): Modal Dict for peer coordination (must be same as server)local_port(int): Local port for QUIC client (default: 5556)stun_server(tuple): STUN server for NAT discovery (default: ("stun.ekiga.net", 3478))punch_timeout(int): Timeout in seconds for NAT punching (default: 15)
Returns: Connected Portal instance ready for communication
Instance Methods
send(data: Union[bytes, str]) -> None
Send data over QUIC connection (WebSocket-style).
recv(timeout_ms: Optional[int] = None) -> Optional[bytes]
Receive data from QUIC connection. Blocks until message arrives or timeout.
Parameters:
timeout_ms(int, optional): Timeout in milliseconds (None for blocking)
Returns: Received data as bytes, or None if timeout
is_connected() -> bool
Check if connected to peer.
close() -> None
Close the connection and clean up resources.
Examples
See the examples/ directory for complete working examples:
modal_simple.py- Basic server/client communicationmodal_benchmark.py- Performance benchmarking
Requirements
- Python 3.8+
- Modal (for automatic NAT traversal)
- Rust toolchain (for building from source)
License
MIT License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file quic_portal-0.1.0.tar.gz.
File metadata
- Download URL: quic_portal-0.1.0.tar.gz
- Upload date:
- Size: 26.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43c2c2055cb0324a96c9c97d4fb8cfb13f9cc8b766e010be7b0f04cfe34f5746
|
|
| MD5 |
15b6cc352348a3f0b30e9564a97c41fb
|
|
| BLAKE2b-256 |
e493bee3efca7cf75a78d51fe45712eafcd30183007c17faf5145612772145b4
|
File details
Details for the file quic_portal-0.1.0-cp38-abi3-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: quic_portal-0.1.0-cp38-abi3-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.8+, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.7.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b4803a9d408557f94107a94fe5e6e19e409584ee764c8768df319012d8fe7eaa
|
|
| MD5 |
799c36d462a913a347023ebf10c1f28b
|
|
| BLAKE2b-256 |
a2318d8de8b485c14d9923b4a3716532e9bbe879576fad8674bbea92278841ae
|
File details
Details for the file quic_portal-0.1.0-cp38-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: quic_portal-0.1.0-cp38-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.2 MB
- Tags: CPython 3.8+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.8.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e02de97512a73d47b891ffe5946e58b929758f21d19e547e78a823283b7a5ff5
|
|
| MD5 |
08c6c6024829d985b2ee3a063bbc405d
|
|
| BLAKE2b-256 |
a84bdcbf35b0931f66265341607629cdbbd9d9b04c4e9aa0bd754ffd75286503
|