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. 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 malloc with ownership transfer at pop (1-copy delivery to Python via StreamChunk).
  • 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().
  • 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 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, 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.
  • 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_error from 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


A Marz Research project.

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.2.3.tar.gz (403.5 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.2.3-cp314-cp314-manylinux_2_34_x86_64.whl (4.2 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.34+ x86-64

aiopquic-0.2.3-cp314-cp314-macosx_14_0_arm64.whl (3.6 MB view details)

Uploaded CPython 3.14macOS 14.0+ ARM64

aiopquic-0.2.3-cp313-cp313-manylinux_2_34_x86_64.whl (4.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ x86-64

aiopquic-0.2.3-cp313-cp313-macosx_14_0_arm64.whl (3.6 MB view details)

Uploaded CPython 3.13macOS 14.0+ ARM64

aiopquic-0.2.3-cp312-cp312-manylinux_2_34_x86_64.whl (4.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ x86-64

aiopquic-0.2.3-cp312-cp312-macosx_14_0_arm64.whl (3.6 MB view details)

Uploaded CPython 3.12macOS 14.0+ ARM64

File details

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

File metadata

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

File hashes

Hashes for aiopquic-0.2.3.tar.gz
Algorithm Hash digest
SHA256 c2c5a9b7f9651dff82c497a2983bfbac517592cc78e74f861a0c7ba934cf4b69
MD5 9938d13130228102e150f4359c74e84a
BLAKE2b-256 1adee0af6962781d6bb6ab1d8599f5b37eeeb257a0ff46a53b89174820189c4d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.2.3-cp314-cp314-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 e6c1c9592aa191761f21d6e0b64e791892e7d490d631aa94ba058f4adf996d39
MD5 a323b7752acd691ddebea25e60e872f8
BLAKE2b-256 dd01047d6e4147534c9c84bf995468a7b16786aebcfea3948b86eaba958c8ab3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.2.3-cp314-cp314-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 3c4c5253a38a0f7493f424ffc5e73548f64cf14b2f7baa20d5435dec2eda9c7c
MD5 6ad4286492605f406fe67249d5ef4233
BLAKE2b-256 348872fe2cfdf724d822dd1ddc98f758f26061055e340c920149f41455f531cd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.2.3-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 d0e1633d2fbc4bce1456cfa19b9fbafc6aba276920bf438cbdd1ca4dc785944c
MD5 637dfe554bc9c8f2e625f2ee57f5b2eb
BLAKE2b-256 6ac63b172941bd447a309e176d2fb2aa01831f2908e778d5e20a3d4211195f32

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.2.3-cp313-cp313-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 84843120c1bc44259cd996439139a4dd47b8c71f86158ed4631c82e5bf17b755
MD5 863151d962dfa6e7c2c2f406fafae239
BLAKE2b-256 540e52de682e2562918e20d6ce7f4f4ba11f389d7e3166854062ef675f01dba1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.2.3-cp312-cp312-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 286f3b063abca9d5a03cc9240b55894bc3f07a41c65b7604226cc1ec2c88eacb
MD5 2de6d6a2c6483653ba34f70e136a0721
BLAKE2b-256 552ef43998811b47b3fcb17ca0a7959a5c767e4736a830a1d05f519c2de87f48

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.2.3-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 5f83b3af0fa4aed72408a848e0d5f51498e7b2877e9f7652bea15a835a209071
MD5 5f858826a0653e88cf81f01853541a9a
BLAKE2b-256 4a55ae86539fc0db85b2a2343264fe921e225de54d76853e01c653f59066cdbc

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