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.1.tar.gz (402.2 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.1-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.1-cp314-cp314-macosx_14_0_arm64.whl (3.6 MB view details)

Uploaded CPython 3.14macOS 14.0+ ARM64

aiopquic-0.2.1-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.1-cp313-cp313-macosx_14_0_arm64.whl (3.5 MB view details)

Uploaded CPython 3.13macOS 14.0+ ARM64

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

File metadata

  • Download URL: aiopquic-0.2.1.tar.gz
  • Upload date:
  • Size: 402.2 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.1.tar.gz
Algorithm Hash digest
SHA256 e7d078b1b4bb2961acfaa5537c40ce3b5971c219716fe52b8842ec9ed48c3757
MD5 4b9514dddea1992de3dcccdf0a901722
BLAKE2b-256 7eb229703321a6d9adfd8833dd0a861b8e1fc50bd92c93b13af84dd6d90db917

See more details on using hashes here.

File details

Details for the file aiopquic-0.2.1-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.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5c8a19f5abb9d887145adde8878edead149ba86d73e0d5e3f13cc2dd31c511c7
MD5 49264273548af0a792a1b7a3b4803107
BLAKE2b-256 b064ae7bac01607c08f667d93ab08bd9ef611ae7961608313840d02b0cb7abce

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.2.1-cp314-cp314-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 70b654ab689eb4a5eb0d5f8f4a44c4cc81018032bd75d5cb41c468a842b7ed5d
MD5 e8cabaf82bd725068de59fae5a8d8133
BLAKE2b-256 533dfadba1c0a46d1c8c017810d402699fad9ef30c7609eb197f8d19033ff56b

See more details on using hashes here.

File details

Details for the file aiopquic-0.2.1-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.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8d0120f7bf76429403ef9d1f48956adacb2cab159127c769b455057c102360ef
MD5 c2e64c81ce63d9d63cc6f1335098d71b
BLAKE2b-256 ca9c4c6fe45f58645141ba000ad8d7f8932c890b021e3b086bf6f8ee296ae801

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.2.1-cp313-cp313-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 f0630a2d097d1830c081287f6fc8ffd6fabc058799893d19c9e4842de118e0e7
MD5 d6b85f5999f06c8cca83ab3887c91602
BLAKE2b-256 ba227ae2ad15d044ed10ba32cc224f512daff501d6061968a95255268e463b67

See more details on using hashes here.

File details

Details for the file aiopquic-0.2.1-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.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5e9a11f27ad336dd4b28a86cfe40ef837e6d9995f85eec6193e692d63c49e66c
MD5 a8ac2d61401e372c001dcbb8e4e02b92
BLAKE2b-256 8ec9a9685837d7b720798b8530d8ba89f5732920088561041ff9e349af4ebbe6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for aiopquic-0.2.1-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 455f5faa35af8bfaa2e822143af0b9570662226e523574e4024e63200b8260fd
MD5 db94ac26cb2953b65ab5b4e50dcbca0f
BLAKE2b-256 1ca9b473fe84c418be2fff2d39e8904b0221dbcc2ca45d56f328d314d4365899

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