High-performance QUIC/HTTP3 library — picoquic-backed, qh3-compatible asyncio API
Project description
aiopquic - Async QUIC + WebTransport (picoquic)
aiopquic is a Python/Cython binding to picoquic, providing high-performance QUIC transport and WebTransport for asyncio applications.
Overview
aiopquic exposes picoquic's QUIC implementation through a lock-free SPSC ring buffer architecture that bridges the picoquic network thread with Python's asyncio event loop. It provides an asyncio QUIC/HTTP3 transport API in the spirit of aioquic (and its fork qh3) — similar shapes for QuicConfiguration, QuicConnection, connect() / serve(), and event types — plus a native WebTransport client/server layered on picoquic's H3 + h3zero. Note: not a drop-in replacement — semantics differ around backpressure (send_stream_data raises BufferError on full per-stream ring) and flow-control sizing.
Architecture
- SPSC Ring Buffers -- Lock-free single producer/single consumer rings for zero-copy event passing between threads. RX uses per-event
mallocwith ownership transfer at pop (1-copy delivery to Python viaStreamChunk). - Cross-platform wake fd -- Linux
eventfdfor efficient asyncioadd_reader()notification;pipe()self-pipe fallback on macOS / BSD. - Dedicated Network Thread -- picoquic runs in its own thread via
picoquic_start_network_thread(). - Cython Bridge -- Thin Cython layer over C callbacks, minimal overhead.
- WebTransport --
asyncio.webtransport.WebTransportSession(client + server) over picoquic'spicowt_*API and h3zero.
Features
- QUIC client and server support (qh3-compatible asyncio API:
connect(),serve(),QuicConnectionProtocol) - Stream data send/receive with FIN signaling, stream reset, stop_sending
- Datagram support
- WebTransport client + server (
serve_webtransport,WebTransportSession) - Connection migration / 0-RTT (inherited from picoquic)
- Connection management (create, close, idle timeout, application close codes)
- Per-cnx multiplexing on the server side via
QuicEngine - Native picoquic_ct / picohttp_ct subprocess smoke (catches upstream regressions on every submodule bump)
Test Results
Tests pass on Linux and macOS (excluding the network-dependent interop suite):
| Suite | Tests | Coverage |
|---|---|---|
test_spsc_ring |
per-event malloc ring lifecycle | |
test_buffer |
Cython Buffer (qh3-compatible) |
|
test_transport |
Transport lifecycle, wake fd, wake-up, connection management | |
test_loopback |
17 tests — handshake, streams, FIN, reset, datagrams, ALPN mismatch, idle timeout, app-close codes, stop_sending, many-streams stress, TX-ring overflow | |
test_asyncio |
qh3-compat client/server stream and datagram exchange | |
test_baton_pattern |
Pure-QUIC baton-style stream multiplexing (UNI ↔ BIDI) | |
test_native_picoquic |
picoquic_ct / picohttp_ct subprocess driver | |
test_interop |
Real public endpoints (network required, opt-in) | |
tests/bench/ |
17 microbenches: ring push/pop, single-shot/sustained/parallel/bidirectional throughput, datagrams, RTT latency, handshake rate (opt-in via pytest tests/bench) |
Installation
Requires Python 3.14+ and a C build toolchain. picoquic + picotls are built from source as git submodules.
git clone https://github.com/gmarzot/aiopquic.git
cd aiopquic
git submodule update --init --recursive
./bootstrap_python.sh
source .venv/bin/activate
./build_picoquic.sh # builds picotls, picoquic, native test drivers
pip install -e '.[dev]'
On macOS, set OPENSSL_ROOT_DIR if Homebrew OpenSSL is not auto-detected (the build script tries openssl@3 then openssl@1.1).
Usage
Low-level Transport API
from aiopquic._binding._transport import TransportContext
server = TransportContext()
server.start(port=4433, cert_file="cert.pem", key_file="key.pem",
alpn="moq-00", is_client=False)
client = TransportContext()
client.start(port=0, alpn="moq-00", is_client=True)
client.create_client_connection("127.0.0.1", 4433,
sni="localhost", alpn="moq-00")
qh3-compatible asyncio API
from aiopquic.asyncio.client import connect
from aiopquic.quic.configuration import QuicConfiguration
configuration = QuicConfiguration(
alpn_protocols=["h3"],
is_client=True,
)
async with connect("quic.nginx.org", 443,
configuration=configuration) as protocol:
quic = protocol._quic
stream_id = quic.get_next_available_stream_id()
quic.send_stream_data(stream_id, b"GET / HTTP/1.0\r\n\r\n", end_stream=True)
protocol.transmit()
WebTransport
from aiopquic.asyncio.webtransport import (
serve_webtransport, WebTransportSession,
)
# See src/aiopquic/asyncio/webtransport.py and tests/ for full examples.
Development
pip install -e '.[dev]'
python -m pytest tests/ -v -m "not interop and not native"
# Microbenches (opt-in)
python -m pytest tests/bench
Known Limitations
- Python 3.14+ required -- relax planned (test on 3.12/3.13).
- Free-threaded Python (3.14t) not yet supported -- the TX-ring producer side,
TransportContextlifecycle, and the WebTransport engine state currently rely on the GIL for serialization. FT support deferred until a per-context locking audit lands. - STOP_SENDING error codes surface as 0 today: picoquic's public stream-error getter only returns the RESET_STREAM code. STOP_SENDING's code lives in
stream->remote_stop_errorinpicoquic_internal.h(no public getter). A small helper that pulls the field is straightforward future work — see TODO insrc/aiopquic/_binding/c/callback.h. - Source build only -- requires building picoquic + picotls from submodules; binary wheel distribution planned.
TODO
- Windows support (eventfd alternative — IOCP / WSAEventSelect on the wake-fd path)
- Free-threaded Python (3.14t) support after producer-side locking audit
- STOP_SENDING error-code surfacing helper (read
remote_stop_errorfrom picoquic_internal.h) - Relax Python version requirement (test on 3.12/3.13)
- Per-stream wrapper cleanup on RESET/FIN before connection close (currently bounded leak per cnx)
Resources
- picoquic -- QUIC implementation by Christian Huitema
- picotls -- TLS 1.3 implementation
- Media Over QUIC Working Group
A Marz Research project.
License
MIT License -- see 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 aiopquic-0.2.0.tar.gz.
File metadata
- Download URL: aiopquic-0.2.0.tar.gz
- Upload date:
- Size: 399.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7afa63ce3b85fe34b355e003602381739cc48ff41c1d4e7de79e30a779b08533
|
|
| MD5 |
04b9f41501c8e76ad53c1c1e96d92b38
|
|
| BLAKE2b-256 |
82ce3c5d9d3b3a58862d394f745bdf9ccb1e315812b6d944501e5f8bcbeae46b
|
File details
Details for the file aiopquic-0.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: aiopquic-0.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 3.9 MB
- Tags: CPython 3.14, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2dfdb6b36df71f20b3f3928bd0dbaaf5100316d19c5d81a2a0c4e11bebf9ffb2
|
|
| MD5 |
39030e2bad48a329def00162f6e1c2fe
|
|
| BLAKE2b-256 |
bbaf1e9f2a7625b4cf6b0d735c18eb5cf5f3a81e590b005236be7760158b2ee0
|
File details
Details for the file aiopquic-0.2.0-cp314-cp314-macosx_14_0_arm64.whl.
File metadata
- Download URL: aiopquic-0.2.0-cp314-cp314-macosx_14_0_arm64.whl
- Upload date:
- Size: 3.6 MB
- Tags: CPython 3.14, macOS 14.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
11bc699521e7852aabc919d1ab7cbaf94ebec9a3b5f8aa478e95bcfd6c9c525b
|
|
| MD5 |
42ca6fd480f42af80148176739410434
|
|
| BLAKE2b-256 |
878ded80233d42283c83c678d336fc3bab4202e70c8941e957b2186a3b166d45
|
File details
Details for the file aiopquic-0.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: aiopquic-0.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 3.9 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb2b064d0d7f9c8b116d582762c775a875d070c456c83662a395f541a2ffb793
|
|
| MD5 |
9d6bb0bcee1d439d8177a88586e71c11
|
|
| BLAKE2b-256 |
446768a6ae86af8e609d241f1cbf5c18191fd36358410bb1a5e69e089c12467b
|
File details
Details for the file aiopquic-0.2.0-cp313-cp313-macosx_14_0_arm64.whl.
File metadata
- Download URL: aiopquic-0.2.0-cp313-cp313-macosx_14_0_arm64.whl
- Upload date:
- Size: 3.5 MB
- Tags: CPython 3.13, macOS 14.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6500a0715c9fe008e6ab941c7cb8fc26139fd5209ddb25970d4f2bee68a7d7a8
|
|
| MD5 |
5ed5c0faa91157b4f439445b6322afc2
|
|
| BLAKE2b-256 |
e2df3186e38f0751a9f11530c48400b8f7be34e72bbf5c5a8721403b2e497ed6
|
File details
Details for the file aiopquic-0.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: aiopquic-0.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 3.9 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e2f9f33e7bd6d80836244225c93a95f06d78359d8647b4047f9fbae3b5c93e8
|
|
| MD5 |
818f1a0c252db78ab0560fbf2b03e76f
|
|
| BLAKE2b-256 |
228e4095fec219caf5908d44d4eddabd5feb3ca7b54a788e4633f6da451e6e20
|
File details
Details for the file aiopquic-0.2.0-cp312-cp312-macosx_14_0_arm64.whl.
File metadata
- Download URL: aiopquic-0.2.0-cp312-cp312-macosx_14_0_arm64.whl
- Upload date:
- Size: 3.5 MB
- Tags: CPython 3.12, macOS 14.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9577c3da7caa2a739d7492e4cb3dfc9b34d073c71817c001d7755feff245a539
|
|
| MD5 |
d86075cb8290ebbd54d7d3efb3dbb7a7
|
|
| BLAKE2b-256 |
1b5ee8c9d87f311faded61c562adb2eed48be5f6ea3959a57773852fdf0a966a
|