This release is a pre-release and may not be stable for production use.
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. 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 event passing between threads, separate TX and RX rings per
TransportContext. - TX path -- Asyncio pushes into per-stream byte ring; picoquic pulls at wire rate via
prepare_to_send. - RX path -- picoquic pushes per-event
StreamChunks; ownership transfers at pop for 1-copy delivery. - 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(). One worker thread perTransportContext; multiple contexts share the asyncio event loop within a single Python process. - 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:
connect,serve,QuicConnectionProtocol - Stream data send/receive with FIN signaling, stream reset, stop_sending
- WebTransport client + server:
serve_webtransport,WebTransportSession - QUIC datagram TX + RX (note: WebTransport datagram TX not yet wired)
- 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 - TLS keylog (NSS Key Log Format) for pcap decryption
- Native picoquic_ct / picohttp_ct subprocess smoke (catches upstream regressions on every submodule update)
Performance
Multi-Gbps sustained throughput over loopback on commodity hardware: 2+ Gbps through the full asyncio API at the QUIC default MTU (where the kernel's sendmsg syscall rate is the wall), 11+ Gbps protocol-only. Numbers, methodology, reproduction commands, build flags, and runtime tuning (jemalloc, GSO, wake thresholds) live in PERFORMANCE.md. The TX/RX dataflow and flow-control model — including the TX backpressure configuration parameters — are documented in DATAFLOW.md.
Installation
Wheels for cp312 / cp313 / cp314 on Linux (manylinux_2_34, glibc 2.34+) and macOS arm64 are published to PyPI:
uv pip install aiopquic # or: pip install aiopquic
For older Linux (glibc 2.28–2.33) install via sdist; build toolchain required.
From source
git clone https://github.com/gmarzot/aiopquic.git
cd aiopquic
./bootstrap_python.sh # creates .venv with uv-managed Python 3.14 (GIL build) and pins cython 3.2+
source .venv/bin/activate
./build.sh # reconcile submodules, build picotls/picoquic + drivers, relink + verify
uv pip install -e '.[dev]' # add dev/test extras — or: pip install -e '.[dev]'
Re-run ./build.sh after any git checkout or submodule bump — it is idempotent (a matching fingerprint skips the compile) and guarantees the imported aiopquic reflects the current source, host-tuned. ./build.sh --check is a read-only doctor that reports submodule drift, a stale native build, or a portable wheel shadowing the editable install, and exits nonzero — handy as a pre-benchmark or CI gate.
On macOS, set OPENSSL_ROOT_DIR if Homebrew OpenSSL is not auto-detected (the build script tries openssl@3 then openssl@1.1).
Reporting issues
Include the full version report in any issue — it captures aiopquic plus the picoquic + picotls submodule SHAs the binding was built from:
python -m aiopquic.versions # or the console script: aiopquic-versions
Sample output:
aiopquic: 0.3.7.dev12+g6eef9caf6 (~/Projects/moq/aiopquic/src/aiopquic) [2026-06-12 08:55]
- picoquic: 1.1.49.2 (d6c5653d) [2026-06-05]
- picotls: master (bfa67875) [2026-04-20]
If you're running aiomoqt on top, prefer python -m aiomoqt.versions — it chains through to this report and includes the aiomoqt version too.
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")
Asyncio API
from aiopquic.asyncio.client import connect
from aiopquic.quic.configuration import QuicConfiguration
configuration = QuicConfiguration(alpn_protocols=["myproto"], is_client=True)
async with connect("server", 4433, configuration=configuration) as protocol:
quic = protocol._quic
stream_id = quic.get_next_available_stream_id()
quic.send_stream_data(stream_id, payload, end_stream=True)
payload is opaque bytes; the library doesn't impose framing. Consumers
that want HTTP/3 layer on top of aiopquic's picowt-backed h3zero
plumbing; consumers that want WebTransport use serve_webtransport /
connect_webtransport. Most direct users of the asyncio API ship their
own protocol bytes (MoQT, custom binary frames, etc.).
Clients verify the server's certificate chain and name against certifi's
roots. A private CA goes in QuicConfiguration.cafile (or
load_verify_locations(cafile=...)), and connect_webtransport(ca_file=...)
takes the same file. To accept any certificate, such as a self-signed test
server, set verify_mode=ssl.CERT_NONE or pass
connect_webtransport(verify_peer=False).
Clients offer a classic key share first; QuicConfiguration.key_exchange_groups
(or start(key_exchange_groups=...)) puts KEX_X25519MLKEM768 first for a
post-quantum key exchange with servers that support it.
WebTransport
from aiopquic.asyncio.webtransport import (
serve_webtransport, WebTransportSession,
)
# See src/aiopquic/asyncio/webtransport.py and tests/ for full examples.
Development
uv pip install -e '.[dev]' # or: pip install -e '.[dev]'
python -m pytest tests/ -v -m "not interop and not native"
# Microbenches (opt-in)
python -m pytest tests/bench
Test-suite coverage, benchmark methodology, performance builds (AIOPQUIC_PERF=1, io_uring scaffolding), and runtime tuning are documented in PERFORMANCE.md.
Known Limitations
- 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.
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) - WebTransport datagram TX path through the C bridge
- Datagram benches: latency percentiles, payload-size sweep, loss / jitter under load (today's
bench_datagramis fire-and-count throughput only) - Pure stream open/close microbench (lifecycle rate without payload, separate from
bench_stream_churn_highlevelwhich bundles writes + FIN) - Submit aiopquic to the QUIC interop runner for cross-implementation coverage
Resources
- picoquic -- QUIC implementation by Christian Huitema
- picotls -- TLS 1.3 implementation
- Media Over QUIC Working Group
A Marz Research project.
Author: G. S. Marzot <gmarzot@marzresearch.net>
License
MIT License -- see LICENSE
Metadata
Release files for aiopquic 0.5.0a3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| aiopquic-0.5.0a3.tar.gz | 3.6 MB | Without provenance | Details |
Built distributions (wheels)
Total release size: 48.2 MB
Release files / aiopquic-0.5.0a3.tar.gz
| Download URL | aiopquic-0.5.0a3.tar.gz |
|---|---|
| Size | 3.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d68cf91717a981df32e9c03681c79e09cf97a86b7682313279c4e70113782170
|
|
BLAKE2b-256 checksum How to use checksums |
63527c8e6572c9f4d65d7dcde5ee380e3a5f731a7c884271d5877227e697469a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / aiopquic-0.5.0a3-cp314-cp314-manylinux_2_34_x86_64.whl
| Download URL | aiopquic-0.5.0a3-cp314-cp314-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 5.5 MB |
| Tags | CPython 3.14 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
f0e88bff6a517d5454ce2cba1e3b6836b3f4d8daf6ef5877aa2ae328d3febb07
|
|
BLAKE2b-256 checksum How to use checksums |
0a8bc0fdfb7f96c96d90cb6f36c7a73bd7ebbf589ebc4af746e7faf03ef20379
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / aiopquic-0.5.0a3-cp314-cp314-manylinux_2_34_aarch64.whl
| Download URL | aiopquic-0.5.0a3-cp314-cp314-manylinux_2_34_aarch64.whl |
|---|---|
| Size | 5.2 MB |
| Tags | CPython 3.14 Linux glibc 2.34+ ARM64 |
|
SHA-256 checksum How to use checksums |
390ae7d2dac7cc29484e6632bfae9fe65741c6d3ddf5c2a968f971592a4e9622
|
|
BLAKE2b-256 checksum How to use checksums |
a696508ec2bb8ebcfe8226ae81a79c8de0f44f8f49190de45376ae5181bf8092
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / aiopquic-0.5.0a3-cp314-cp314-macosx_14_0_arm64.whl
| Download URL | aiopquic-0.5.0a3-cp314-cp314-macosx_14_0_arm64.whl |
|---|---|
| Size | 4.1 MB |
| Tags | CPython 3.14 macOS 14.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
b8834d0fbffd41f71251cc3da9241e1900588a6a43be1346a9de4c8e9a33334c
|
|
BLAKE2b-256 checksum How to use checksums |
ddc001c8c5f4c1ed1f9e60763b6d7355da5917e6216934e4aec5dae141459310
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / aiopquic-0.5.0a3-cp313-cp313-manylinux_2_34_x86_64.whl
| Download URL | aiopquic-0.5.0a3-cp313-cp313-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 5.5 MB |
| Tags | CPython 3.13 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
7b55856022de4c309bf1aec392bba084b48950433baf3fb2a2b12f2e8df00cbf
|
|
BLAKE2b-256 checksum How to use checksums |
9dd391692d0cecb59ec21dfa95bb41bc369c2ae2f05c2747f8070f858b370b9a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / aiopquic-0.5.0a3-cp313-cp313-manylinux_2_34_aarch64.whl
| Download URL | aiopquic-0.5.0a3-cp313-cp313-manylinux_2_34_aarch64.whl |
|---|---|
| Size | 5.2 MB |
| Tags | CPython 3.13 Linux glibc 2.34+ ARM64 |
|
SHA-256 checksum How to use checksums |
16f5d0d75b39aaef211862f081ab18e68de57fcfda298aca574661ae5becdfe4
|
|
BLAKE2b-256 checksum How to use checksums |
5e80fb06900cc2e361d283c2ff42428b49c28b588508e5a82ccc71b39ca60d9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / aiopquic-0.5.0a3-cp313-cp313-macosx_14_0_arm64.whl
| Download URL | aiopquic-0.5.0a3-cp313-cp313-macosx_14_0_arm64.whl |
|---|---|
| Size | 4.1 MB |
| Tags | CPython 3.13 macOS 14.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
74495b644de969bebe070ad84eeb887caac8e2b9903f8d32cf2e11ba674335d7
|
|
BLAKE2b-256 checksum How to use checksums |
2df3ea01b6bc45662f6a132e0ed4b3cb58f695b95bfa79944dd96a02faed04c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / aiopquic-0.5.0a3-cp312-cp312-manylinux_2_34_x86_64.whl
| Download URL | aiopquic-0.5.0a3-cp312-cp312-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 5.5 MB |
| Tags | CPython 3.12 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
d72ca3bcf8cc79b1edd3943eb85dca8fa894b80158a3f9275f31e2f12af967f8
|
|
BLAKE2b-256 checksum How to use checksums |
1bec8d669992405608504a4e6659ba64553edab0c66c7ab61bcc1f3ac7a4f151
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / aiopquic-0.5.0a3-cp312-cp312-manylinux_2_34_aarch64.whl
| Download URL | aiopquic-0.5.0a3-cp312-cp312-manylinux_2_34_aarch64.whl |
|---|---|
| Size | 5.2 MB |
| Tags | CPython 3.12 Linux glibc 2.34+ ARM64 |
|
SHA-256 checksum How to use checksums |
88fc2648ad84c95f9d16ae01f30480f596970ba1a6da503670969e86e3cc55d5
|
|
BLAKE2b-256 checksum How to use checksums |
a0647f7d321400262fee3714b00df79e6401dd04fb2e21ad543d6cea7393a7d3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / aiopquic-0.5.0a3-cp312-cp312-macosx_14_0_arm64.whl
| Download URL | aiopquic-0.5.0a3-cp312-cp312-macosx_14_0_arm64.whl |
|---|---|
| Size | 4.1 MB |
| Tags | CPython 3.12 macOS 14.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
ef67c1ee64245677842578f2da6f48122f1cb76aa300c6aa7b04169c9a44f892
|
|
BLAKE2b-256 checksum How to use checksums |
2293751043d6be90e90a492ca3c6f08656fae3fc5ff9e5b66a67346b95e34255
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Security for aiopquic 0.5.0a3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.