zmuxio-aioquic
zmuxio-aioquic wraps an established aioquic connection behind the stable
zmux.AsyncSession API.
It is an adapter over QUIC streams. It does not create QUIC connections and it
does not expose native ZMux wire-session controls such as ping, go_away,
prefaces, or negotiated native settings.
Installation
pip install zmuxio-aioquic
The adapter depends on zmuxio and aioquic. The core package alone does not
install aioquic or cryptography:
pip install zmuxio
Usage
import zmux
import zmux_aioquic
async def run(connection) -> None:
session = zmux_aioquic.wrap_session(connection)
stream = await session.open_stream()
await stream.write_final(b"hello")
await session.close()
Use SessionOptions when the adapter needs prelude timeout or concurrency
tuning:
options = zmux_aioquic.SessionOptions(
accepted_prelude_read_timeout=2.0,
accepted_prelude_max_concurrent=16,
)
session = zmux_aioquic.wrap_session(connection, options)
Incoming streams can be accepted directly when the wrapped connection exposes
accept_stream(...) / accept_uni_stream(...). aioquic instead hands every
peer-opened stream, unidirectional ones included, to the protocol's
synchronous stream_handler(reader, writer) callback. Wrap the protocol when it
is created and enqueue streams from that callback:
from aioquic.asyncio import connect
from aioquic.asyncio.protocol import QuicConnectionProtocol
class ZmuxProtocol(QuicConnectionProtocol):
def __init__(self, quic, stream_handler=None):
super().__init__(quic, stream_handler=self._handle_stream)
self.session = zmux_aioquic.wrap_session(self)
def _handle_stream(self, reader, writer) -> None:
self.session.queue_incoming_stream(reader, writer)
async with connect(host, port, configuration=configuration,
create_protocol=ZmuxProtocol) as protocol:
stream = await protocol.session.accept_stream()
queue_incoming_stream(reader, writer) takes the QUIC stream ID from
writer.get_extra_info("stream_id") and the stream direction from that ID, so
peer unidirectional streams are delivered by accept_uni_stream(...). Pass
stream_id / bidirectional explicitly only for backends that cannot report
them; a direction that contradicts the QUIC stream ID is rejected with
zmux.AdapterUnsupported.
When the wrapped object is an aioquic QuicConnectionProtocol, the session
installs a per-instance quic_event_received wrapper so it can observe
StreamReset, StopSendingReceived, and ConnectionTerminated events before
aioquic's default handling.
Stable API Coverage
Wrapped sessions implement zmux.AsyncSession:
accept_stream(...)/accept_uni_stream(...)open_stream(...)/open_uni_stream(...)open_and_send(...)/open_uni_and_send(...)close(),close_with_error(...),wait(...),closed,state, andstats
Wrapped streams implement zmux.AsyncStream, zmux.AsyncSendStream, and
zmux.AsyncRecvStream:
stream_id,open_info,metadata, andupdate_metadata(...)read(...),readinto(...), andread_exact(...)write(...),write_all(...),write_vectored(...), andwrite_final(...)close_read(),cancel_read(...),close_write(),cancel_write(...), andclose_with_error(...)- read and write timeout helpers
Direction errors use the same core exception types as native ZMux:
zmux.StreamNotReadable for reads from send-only streams and
zmux.StreamNotWritable for writes to receive-only streams. Use
zmux.AdapterUnsupported only for adapter-only gaps such as native ZMux
session controls that QUIC streams cannot expose.
Options
accepted_prelude_read_timeout:
0: useDEFAULT_ACCEPTED_PRELUDE_READ_TIMEOUTNoneor a negative value: disable the adapter-managed timeout- positive number: timeout in seconds
Accepted QUIC streams whose adapter prelude does not arrive in time are discarded instead of blocking later ready streams.
accepted_prelude_max_concurrent:
Noneor0: usedefault_accepted_prelude_max_concurrent()- positive number: per-session bound for concurrently parsing accepted stream preludes
- values above
MAX_ACCEPTED_PRELUDE_MAX_CONCURRENTare clamped
Set the process-wide default during startup when many sessions should share the same value:
zmux_aioquic.set_default_accepted_prelude_max_concurrent(16)
Mapping
open_stream(...)andaccept_stream(...)map to QUIC bidirectional streams.open_uni_stream(...)andaccept_uni_stream(...)map to QUIC unidirectional streams.- Open-time ZMux metadata is carried in an adapter prelude:
varint(metadata_len)followed by stream metadata TLVs. OpenOptionssupports binary open info, initial priority, and initial group.open_infoandmetadataexpose decoded opener metadata on accepted streams.- Open-time metadata is validated before the QUIC stream is created, so an
oversized
open_infofails withzmux.OpenMetadataTooLargewithout using a QUIC stream ID. update_metadata(...)works only before the local stream prelude is emitted. Later updates fail withPriorityUpdateUnavailable.close_read()maps to QUIC read-side cancellation (STOP_SENDING) withErrorCode.CANCELLED.cancel_read(code)maps to QUIC read-side cancellation with that code.close_write()maps to QUIC send-side graceful close and returns once the FIN is queued.cancel_write(code)maps to QUIC send-side reset (RESET_STREAM) with that code.close_with_error(code, reason)is best-effort at stream scope.- Stream resets and stops issued through aioquic's
QuicConnectionare followed bytransmit(), so they reach the peer without waiting for other traffic. - An accepted stream whose adapter prelude is malformed, oversized, or not
received in time is never exposed; it is rejected with STOP_SENDING and, for
bidirectional streams, RESET_STREAM carrying
ErrorCode.PROTOCOL. - After the peer FIN has been consumed,
read(...)keeps returningb"". Ordinary zero-length writes return0without observing write-side state. - Writes either hand all of their bytes to the QUIC stream or raise. When an
error (such as
zmux.WriteTimeout) comes after part of the data was already handed to the QUIC stream, the error carries that count ascharacters_written, like native sessions andBlockingIOError, so a retry can resume after those bytes.
Fresh write-side reset or abort visibility is not a portable adapter guarantee because QUIC can discard previously written but unacknowledged stream data, including a just-submitted metadata prelude.
Errors
- A peer RESET_STREAM(code) fails reads on that stream with
zmux.ApplicationError(code)(remote, reset). The local send half is not affected. - A peer STOP_SENDING(code) fails later writes on that stream with
zmux.ApplicationError(code)(remote, stopped). aioquic itself answers the stop with RESET_STREAM carryingNO_ERROR, not the peer's code. - A peer QUIC application close with a nonzero code or a reason fails the
session with
zmux.ApplicationError(code, reason), reported bywait(),close_error, andpeer_close_error. A peer close with code 0 and no reason is a graceful close. Transport errors and idle timeouts fail the session withzmux.SessionClosed. - When the connection ends, blocked accepts fail with
zmux.SessionClosed, reads on streams without a peer FIN fail with the session error instead of returning EOF, and writes fail with the session error. - QUIC stream-limit failures are normalized to
zmux.OpenLimited.
Use helpers such as zmux.error_code(...), zmux.open_limited(...),
zmux.adapter_unsupported(...), zmux.priority_update_unavailable(...),
zmux.session_closed(...), zmux.stream_not_readable(...),
zmux.stream_not_writable(...), zmux.read_closed(...),
zmux.write_closed(...), and zmux.timeout(...) instead of depending on
aioquic exception classes.
Reduced Behavior
- No native ZMux
ping,go_away, peer-close diagnostics, prefaces, or negotiated settings. - No post-open native advisory frames such as native
PRIORITY_UPDATE. - No QUIC datagram, packet acknowledgement, RTT, or loss-state API.
statsreports adapter-visible counters, not native ZMux runtime internals.
Conformance
target_claims(), target_implementation_profiles(), and target_suites()
provide adapter conformance metadata for tests that exercise the stable async
session contract over aioquic.
Metadata
Release files for zmuxio-aioquic 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| zmuxio_aioquic-0.1.0.tar.gz | 34.3 kB | With provenance | Details for zmuxio_aioquic-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| zmuxio_aioquic-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for zmuxio_aioquic-0.1.0-py3-none-any.whl |
Total release size: 69.7 kB
Release files / zmuxio_aioquic-0.1.0.tar.gz
| Download URL | zmuxio_aioquic-0.1.0.tar.gz |
|---|---|
| Size | 34.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cecf6ad88e9ad70b874b783d859d838f16222e7daa011bebf0e0240cc45ca9d7
|
|
BLAKE2b-256 checksum How to use checksums |
0810d096deeac512f81e09c59d8d330c48fdf2a75ef81b550e06567ff34bb904
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / zmuxio_aioquic-0.1.0-py3-none-any.whl
| Download URL | zmuxio_aioquic-0.1.0-py3-none-any.whl |
|---|---|
| Size | 35.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b6e9b0ab2e2b98e1902f2a75f2cf08436631130900ffa08c9ad2e3e0c57a8ca2
|
|
BLAKE2b-256 checksum How to use checksums |
5cd07e34f3109cb6eb37bc27fc98324601b3f9a317630baa53db727452783d7d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logSecurity for zmuxio-aioquic 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for zmuxio_aioquic-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.