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.2.tar.gz (403.3 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.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (3.9 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

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

Uploaded CPython 3.14macOS 14.0+ ARM64

aiopquic-0.2.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (3.9 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

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

Uploaded CPython 3.13macOS 14.0+ ARM64

aiopquic-0.2.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (3.9 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

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

File metadata

  • Download URL: aiopquic-0.2.2.tar.gz
  • Upload date:
  • Size: 403.3 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.2.tar.gz
Algorithm Hash digest
SHA256 18d667be50859f9e1634ac2f8638edaf28d18d5a8ed39fce3c5b46e24453607c
MD5 939eb1978de881f03b5ae84ffb7b2db4
BLAKE2b-256 1b7c904dfcec955b06afb4b74aa751f6d0f31a00e8c818cb3cd23b073b64a766

See more details on using hashes here.

File details

Details for the file aiopquic-0.2.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aiopquic-0.2.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 dae9d08a36a97e14ab57cfda4f111f3dc469b9aa6be4986f3d4b2a658f763dd0
MD5 0f7134f890c653aac5129d1db48c715f
BLAKE2b-256 acdc95784ccbe1ae84a3cf8978549146ff9347cf7a157aec37795a2fbda1b217

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.2.2-cp314-cp314-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 bacf1997b7be8bcfd4e6277f976401edb7195de47427ed071a6aa4db0ea4363e
MD5 331327f050633443139451283e107059
BLAKE2b-256 3f99bbf664d64b7f93771ea39653dc004452fcdf29c64bd5e25345717df3c95e

See more details on using hashes here.

File details

Details for the file aiopquic-0.2.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aiopquic-0.2.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 82da21bd1f101e6244893726f5bb49f2d33b80fe43ed1af97b9949af624aabfa
MD5 a03c35af86e4fde07427b1d92fb6281e
BLAKE2b-256 5df6ebc53929e4fe350d3cbeccc147399e94f7f3f0b3268e5c50a369d1a7cd2e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.2.2-cp313-cp313-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 12d0c186b282d6e3fe0f800056a7749bd4d170b3faec76cf6826e95eeee17633
MD5 9bb53e8b17324de97c6b49667fc3f84d
BLAKE2b-256 19e48e3380c20e051c03a4526961527d1017848cb427ffb2ce486df979118cd3

See more details on using hashes here.

File details

Details for the file aiopquic-0.2.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for aiopquic-0.2.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1382edd78db2261b314f3620253bce872f4efedfa355d3055ae8c55cb2a02492
MD5 c18bfbe478a6a1232b0d0440cbea3e90
BLAKE2b-256 edccdd0e061251f8ba76edd3efc13bddeea3ebe1ea715b3dad69318f2f5ed8d5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.2.2-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 f9e3ee173ccf2d80b7d30346dbc2fe5ca2c95bb7a09e945197b14b3083ab5b09
MD5 d2db1fcb6cadf0937c29d473cdd34502
BLAKE2b-256 b885d134a9f002eda1751486c9c361fc0964aa33e9aafb9063a51f5f1a5a32b5

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