Skip to main content

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 eventfd for efficient asyncio add_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 per TransportContext; 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's picowt_* 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)
    protocol.transmit()

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.).

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, TransportContext lifecycle, 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_error in picoquic_internal.h (no public getter). A small helper that pulls the field is straightforward future work — see TODO in src/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_error from 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_datagram is fire-and-count throughput only)
  • Pure stream open/close microbench (lifecycle rate without payload, separate from bench_stream_churn_highlevel which bundles writes + FIN)
  • Submit aiopquic to the QUIC interop runner for cross-implementation coverage

Resources



A Marz Research project.
Author: G. S. Marzot <gmarzot@marzresearch.net>

License

MIT License -- see LICENSE

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aiopquic-0.3.11.tar.gz (3.3 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

aiopquic-0.3.11-cp314-cp314-manylinux_2_34_x86_64.whl (5.3 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.34+ x86-64

aiopquic-0.3.11-cp314-cp314-manylinux_2_34_aarch64.whl (5.0 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.34+ ARM64

aiopquic-0.3.11-cp314-cp314-macosx_14_0_arm64.whl (3.9 MB view details)

Uploaded CPython 3.14macOS 14.0+ ARM64

aiopquic-0.3.11-cp313-cp313-manylinux_2_34_x86_64.whl (5.3 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ x86-64

aiopquic-0.3.11-cp313-cp313-manylinux_2_34_aarch64.whl (5.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ ARM64

aiopquic-0.3.11-cp313-cp313-macosx_14_0_arm64.whl (3.9 MB view details)

Uploaded CPython 3.13macOS 14.0+ ARM64

aiopquic-0.3.11-cp312-cp312-manylinux_2_34_x86_64.whl (5.3 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ x86-64

aiopquic-0.3.11-cp312-cp312-manylinux_2_34_aarch64.whl (5.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ ARM64

aiopquic-0.3.11-cp312-cp312-macosx_14_0_arm64.whl (3.9 MB view details)

Uploaded CPython 3.12macOS 14.0+ ARM64

File details

Details for the file aiopquic-0.3.11.tar.gz.

File metadata

  • Download URL: aiopquic-0.3.11.tar.gz
  • Upload date:
  • Size: 3.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for aiopquic-0.3.11.tar.gz
Algorithm Hash digest
SHA256 8fb64d17c8b7b606ff7cc82ac71086e5c56fd627a42175d582c0bac700a65c74
MD5 4acbec435f2cf64c1794c52657b44a9c
BLAKE2b-256 3e0e595bc8a1fc3791dfa5b04464f7a230b125e8cf84363c1d8c2c9d1f1ae783

See more details on using hashes here.

File details

Details for the file aiopquic-0.3.11-cp314-cp314-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for aiopquic-0.3.11-cp314-cp314-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 5448e75e531668dfdde8a28e38d16686bab744aea020fbb70797c3ce7bfc70d2
MD5 193a43c214cfab4a8664c99a6c998f28
BLAKE2b-256 5d53bba009959aab037707c18794ab635e42c18a4130b7b3cdfb7cb89f3c4dca

See more details on using hashes here.

File details

Details for the file aiopquic-0.3.11-cp314-cp314-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for aiopquic-0.3.11-cp314-cp314-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 047ff3957a9bcd9abbe6a2e2310a94ce589f86993c6f98c9362c80aa850138c1
MD5 d7e464208f699cc4c2d477dd3513d3b3
BLAKE2b-256 28e4cdb1cddc5352e3fb740adca701cd6f53b1e72b99a6ff7c0fbd899528f137

See more details on using hashes here.

File details

Details for the file aiopquic-0.3.11-cp314-cp314-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for aiopquic-0.3.11-cp314-cp314-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 daec9dcd2e534b1abd2cbb34d724e773200d5a28d6744772a7c99ec0824b3cef
MD5 7f9ecff62808b041751a8e22da27de05
BLAKE2b-256 147b23b3d3126553dcbb5a135bddbccc84f4f6edae8628a9a6b33d12d08317b1

See more details on using hashes here.

File details

Details for the file aiopquic-0.3.11-cp313-cp313-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for aiopquic-0.3.11-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 6fe4762aaf5bcc66f29316b4a1ec2029a202dcac22da0d77e387426853250c5e
MD5 4d0a427ce041fe8da22b2668581a57b7
BLAKE2b-256 12711d1299e6e9b6cb4108e1d183a0c69bc1b7e0cf9a052786f966c7154b4d92

See more details on using hashes here.

File details

Details for the file aiopquic-0.3.11-cp313-cp313-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for aiopquic-0.3.11-cp313-cp313-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 de73a58a0db453628ae25f1c9ca9618f98a0b73c08ca4e1d9253758675c86c22
MD5 2ff1cb9086187fe7461bba711782ad19
BLAKE2b-256 ce2ee0aa94fd0cab04e8efe2b0b019871b7328e32013e5bb029cb11523a2f254

See more details on using hashes here.

File details

Details for the file aiopquic-0.3.11-cp313-cp313-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for aiopquic-0.3.11-cp313-cp313-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 81c31c8815313eded10e8cdacc57221ae9f2fccd3068041f5366fe58e9b8f2bc
MD5 b18e4d749017e95cf67b3176a0f6982d
BLAKE2b-256 b208ae590b8307394f3101b81b9f986a65f5de40feb86660bc2822d9e583a841

See more details on using hashes here.

File details

Details for the file aiopquic-0.3.11-cp312-cp312-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for aiopquic-0.3.11-cp312-cp312-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 7379cf6272937fbdf8adc99ac04d678f0acd9a46be7a35258771e8f39a6149c1
MD5 26abd820aa8c276d39c5cef422e8e88e
BLAKE2b-256 d61b73184e8318654f78d87d02bed89f28945324c0187d78475d03b95c3d2f37

See more details on using hashes here.

File details

Details for the file aiopquic-0.3.11-cp312-cp312-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for aiopquic-0.3.11-cp312-cp312-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 1864e6f76cd556f82bfb20e69c1e731a27e60acae09cb12af1e1aa2efd2eef0b
MD5 902b9360c96cfa9e5b61a1a28d800820
BLAKE2b-256 487c55d93872c5f7a216fec9c28ca9a9095a62e56d46218b725ce92f8271ee11

See more details on using hashes here.

File details

Details for the file aiopquic-0.3.11-cp312-cp312-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for aiopquic-0.3.11-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 983e00e0df6ba1ffc06f6c53191ce4e2a86ac9b500db39a2e066405a8664d72a
MD5 d16c0fb5c09ad46a231f38aab23b9c07
BLAKE2b-256 f0120a939a62e6050bb216b17b216431f8b01b7a810b20b34fcc5bee37ec5278

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.3.11 This release

10 files

0.3.10

10 files

0.3.9

10 files

0.3.8

10 files

0.3.7

10 files

0.3.6

10 files

0.3.5

10 files

0.3.4

10 files

0.3.3

7 files

0.3.2

7 files

0.3.1

7 files

0.3.0

7 files

0.2.7

7 files

0.2.6

7 files

0.2.5

7 files

0.2.4

7 files

0.2.3

7 files

0.2.2

7 files

0.2.1

7 files

0.2.0

7 files

0.1.0

1 file

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page