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.7.tar.gz (733.7 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.7-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.7-cp314-cp314-manylinux_2_34_aarch64.whl (4.9 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.34+ ARM64

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

Uploaded CPython 3.14macOS 14.0+ ARM64

aiopquic-0.3.7-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.7-cp313-cp313-manylinux_2_34_aarch64.whl (4.9 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ ARM64

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

Uploaded CPython 3.13macOS 14.0+ ARM64

aiopquic-0.3.7-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.7-cp312-cp312-manylinux_2_34_aarch64.whl (4.9 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ ARM64

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

File metadata

  • Download URL: aiopquic-0.3.7.tar.gz
  • Upload date:
  • Size: 733.7 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.7.tar.gz
Algorithm Hash digest
SHA256 329f6139ab391b26439500dd9252787b367d3363af22b7500514bdfbc719598b
MD5 64379443f2724758e2ccc5637dec2395
BLAKE2b-256 97dbbba397012d5272402e8b264c357def18d09a3a01bbd1134e23831b67b51e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.7-cp314-cp314-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 925369cab300df158455162a7662a1ce8e8206d2fa42db5955923ef3d59a9bba
MD5 034e91d859c4a4386ed0fc9cafa05621
BLAKE2b-256 809ef90498437394618928d78880b3c480108ea6b0dd19aceebb4a182da13ea8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.7-cp314-cp314-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 ddc989111f8a8b4c6d978eebff4eeb3efc12bb9514959630dce22b85b9eb9c15
MD5 e8e813822a990da9ff8cd3e6ac9f4ad1
BLAKE2b-256 44e646c6de156e734438b25d4475223c061de2aaecdf8bdf33154410e24c864e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.7-cp314-cp314-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 c4b79968c1fcbf5d0b29af5546253285938f5a0eb2a27c1ca1808db5827bb537
MD5 d1db904b3c9a176e98c9a3425917d3da
BLAKE2b-256 1b293fc162f0cc818ec27aa90450021571ef23fb75a0ba755da3dcf34e57680a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.7-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 bd36ea496044629ecfb37b9885f1f0feb88bcf59da56bf469b0905121f10c83a
MD5 61b5a2fd88302f44b79816ad59cc3374
BLAKE2b-256 2343c99b0bf5e092219555bc11079942c3971b6079a48fbde0512e807a6e5aca

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.7-cp313-cp313-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 60a27b2c53d91f6809bb6f6ec79545c60b800c2a1f6f77fb2601b94722db3e08
MD5 6c6e8186a880220917bc167294907e7f
BLAKE2b-256 b2034ea1079764375a0e2b6c513c9bfa28951f529cf8f9c0fc78b7b66fecbf4d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.7-cp313-cp313-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 8146f436315fd16d6828072302acab99e70bb7fd2f2b51a1df854d4d697d8840
MD5 e154497fbf0fa94464b856e44bb969d7
BLAKE2b-256 d25c650ca069beb7409607dd54054b59478de6d9ee21a15e2b2fcd7f4e049d7b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.7-cp312-cp312-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 534e809abfa816937c1e213b3fd8eb1136f31d158b77bfa801dee6f967f1ca39
MD5 09ab860cf306bd9abcae303d3f7602f3
BLAKE2b-256 09c419037133034e92ac4b840d92d0d5ceb1ac3804743d8c3ecd02c5524e7f77

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.7-cp312-cp312-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 b002cdc6495a1770cb225c10db283fbd52d14163607bb18d219ad85c45ffc481
MD5 85fbbc05383dca54741c1897c95e7244
BLAKE2b-256 9656dd00657d22445a9874e8e4932345547229f5559a7f04fc4e5645d9b4271a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.3.7-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 669e1caa30226b010c5def45b9ad4c7b10b784ecca6cd8fd174cb492bed0b0f5
MD5 3c2e5ddb56abd16b7eddd4278f3dec54
BLAKE2b-256 1d57c263bbb81b9d837a96c20e300de21a7ee71db5291d86d84775a1ab80611d

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