Skip to main content

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. 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
git submodule update --init --recursive
./bootstrap_python.sh    # creates .venv with uv-managed Python 3.14 (GIL build) and pins cython 3.2+
source .venv/bin/activate
./build_picoquic.sh      # builds picotls, picoquic, native test drivers
uv pip install -e '.[dev]'    # or: 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).

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

Project details


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.8.tar.gz (736.1 kB 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.8-cp314-cp314-manylinux_2_34_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.34+ x86-64

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

Uploaded CPython 3.14manylinux: glibc 2.34+ ARM64

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

Uploaded CPython 3.14macOS 14.0+ ARM64

aiopquic-0.3.8-cp313-cp313-manylinux_2_34_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ x86-64

aiopquic-0.3.8-cp313-cp313-manylinux_2_34_aarch64.whl (4.9 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ ARM64

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

Uploaded CPython 3.13macOS 14.0+ ARM64

aiopquic-0.3.8-cp312-cp312-manylinux_2_34_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ x86-64

aiopquic-0.3.8-cp312-cp312-manylinux_2_34_aarch64.whl (4.9 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ ARM64

aiopquic-0.3.8-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.8.tar.gz.

File metadata

  • Download URL: aiopquic-0.3.8.tar.gz
  • Upload date:
  • Size: 736.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for aiopquic-0.3.8.tar.gz
Algorithm Hash digest
SHA256 2422285da963152210f65a8143223d4f8c9b1e7e2f6c8f1b5065ee14dfb3a7ac
MD5 f00eff2322cbb3d0aef4d422bd0397ae
BLAKE2b-256 0ed8317649d1579d1b19b34f7b105b9ab49b107888e919cacfe82a8d7ebc4bdb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.8-cp314-cp314-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 8b2fced3ca756b05ab2f8ef2b51b8f91def7bc878fd8a29eaa0a89f646c14202
MD5 0ed6b08cb788ac3aa858b02ff6f4e923
BLAKE2b-256 7ee12b82933fb82156f825a45382268f51fe00ba9e96d72180f8a3c14121ac62

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.8-cp314-cp314-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 6c6f11cd56aef1638340695b5a2454a6e8c34baf341d4f0838444cf2d2b89a49
MD5 a5e9d3f9d3826259014545d0da92bc2f
BLAKE2b-256 494f3acac5431bc4bd54073e7a7931530473871adb0e9e0908db371c544b828e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.8-cp314-cp314-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 9cdf89a02fdf1c7a6b0a81cb3739584ee3803c6bc06ca8801e5edc23c66173c6
MD5 150c73c1d7ec76f9731cec153a5ec44e
BLAKE2b-256 5c97025c5a03018db77147ca99c006c59b1ea6bf48a37c5a196754b16b4c4304

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.8-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 f36923cf8b0b5aea6b4b833ac2f80a47aefc01e844ad68bfeb8fb30ffd8efd61
MD5 e17260905990f217b382128205aa8296
BLAKE2b-256 b6b105f18c9bc037639c9fb914e29946379947ecea9793b2b6a8535ebfdc3c3a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.8-cp313-cp313-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 b3f88ef517b854d614b0a17890282c8a6683a4eda12a75244526d359168d7dff
MD5 44fe195f8d598ab884ca7e98aaa4dc58
BLAKE2b-256 e20ddc9c120f0ae87918af8ef5a0b83073803df8bf917a67069827d445a8a0a3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.8-cp313-cp313-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 d6a20917d2d87614fc2bfb2512f064d08f0131376996c0f0863e175181489993
MD5 a421d36f82a8f9ebe5180fc5b472a27f
BLAKE2b-256 8468d68eb3819dae2de7ed2f40d2923c8d0cfc71113ee98f1030fb559925b4ae

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.8-cp312-cp312-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 b64036df34afc4126ba0e3015a17b68f3cec6910c6f1e9d13848d5f688ccdf0b
MD5 60c153425f87621fb6bae1de0c35077f
BLAKE2b-256 0fc191893927fcd17d16af2e7f58062a70494a1760213e0061b3aa10a508a813

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.8-cp312-cp312-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 d27c0f7a6735277dc399d0fb3010196f2136cb28683d7059abe47d5e2180ac04
MD5 43a7560f95b0bc655fea4f6005422d93
BLAKE2b-256 8be22c486b2f2d8e033c274db1cabe330fbcbd84dfcc3585dc36468be8bf37ee

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.8-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 339e3ee1c1b4846bb5d98477da6597f7d828afdfff0e74c25d96d191cbc6ebeb
MD5 472fbad6e42a70b29f2f412bf82dfb11
BLAKE2b-256 2abe7574bb38e6de7cae16af287daa05bbaf16266e5766ad70c3e7015d320963

See more details on using hashes here.

Supported by

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