- Zig 94.9%
- C 3.5%
- Shell 1.5%
Align vif-argent with fonceuse's reactor-seizure containment and h2→h1 pump-stall investigation: - Document D.drain as non-blocking by contract (reactor el_mutex held); reframe 4 lock-free comments as historical rationale — drain no longer calls group.cancel. - Export FakeTcpHandle, FakeTcpConnState.create, StreamSocketOptions so fonceuse's RecordingH1Socket repro harness can create standalone socketpairs without a server listen target. - E0 ring test: formal elimination of M2 EOF/close ordering (data-pending check at ring.zig:333 evaluated before close_received at :352). Gate: 358/358 tests pass. |
||
|---|---|---|
| .claude | ||
| certs | ||
| deps | ||
| docs | ||
| examples | ||
| interop | ||
| src | ||
| www | ||
| .dockerignore | ||
| .gitignore | ||
| .gitmodules | ||
| build.zig | ||
| build.zig.zon | ||
| docker-compose.local.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
| run_endpoint.sh | ||
vif-argent
A pure-Zig QUIC (RFC 9000) implementation plus a TCP+TLS 1.3 transport, sharing one comptime-driver transport model. "Vif-argent" is French for quicksilver — often shortened to vif.
What's here
vif-argent is a transport library, not an HTTP framework. It exposes two peer transports plus the pieces they're built from:
| Module | Description |
|---|---|
vif_argent.transport / VifEngine |
Pure-Zig QUIC v1 transport — uses picotls for TLS. |
vif_argent.tcp |
TCP transport with pluggable TLS engine (PtlsEngine, picotls-based) or cleartext |
vif_argent.tls |
Shared TLS utilities: cert store, mTLS verifier |
vif_argent.o11y |
Structured Logger/Meter seam (duck-typed vtables) for both transports |
vif_argent.h09 |
HTTP/0.9-over-QUIC driver, used for interop testing |
vif_argent.dispatch |
Transport-agnostic stream dispatch (thread-pool vs. reactive) |
Both UdpTransportWith/UdpTransport (QUIC) and TcpTransportWith/TcpTransport
follow the same shape: comptime-parameterized over an application driver
(onConnect/onBeginStream/onEndStream/onDisconnect) and, for testing, a
swappable socket implementation (RealSocket vs. FakeSocket/FakeTcpSocket).
There is currently no HTTP/3, QPACK, or high-level Client/Server request API
in this repo — those were removed; consumers implement their own protocol driver
on top of the QUIC/TCP transport (see fonceuse/exutoire for an example).
Quick start
# Clone with submodules
git clone --recursive <repository-url>
cd vif-argent
# Build C libs (aws-lc, picotls) + all Zig binaries (first run: 5-10 min)
zig build
# Run the unit + integration test suite
zig build test --summary all
Build requirements
- Zig 0.16.0
- CMake 3.10+
- C/C++ compiler (clang on macOS, gcc on Linux)
- Perl (for aws-lc)
- Git (for submodules)
Build commands
| Command | Description |
|---|---|
zig build |
Build C deps (aws-lc, picotls) + all executables |
zig build deps |
Build and test C library dependencies only |
zig build test |
Full test suite (unit + transport + vif↔vif harness) |
zig build test-transport |
Transport-layer tests only (no h09/dispatch imports) |
zig build test-vif-vif |
vif↔vif QUIC harness (handshake, streams, loss, reorder) |
zig build test-tcp / test-fake-tcp |
TCP transport tests (real sockets / FakeTcpSocket) |
zig build test-tls |
TLS/picotls-bridge harness |
zig build test-mux |
TCP mux harness |
zig build test-lifecycle / test-lifecycle-tcp |
Connection/stream lifecycle invariants |
zig build test-l4 |
Simulated-socket (FakeSocket) QUIC tests |
zig build test-qlog |
qlog semantic validation |
zig build test-scaling |
100-stream / long-lived-stream scaling tests |
zig build test-deadlock |
Deadlock regression tests |
zig build test-listener-revents / test-logger-injection / test-meter-injection |
Focused regression suites |
zig build fuzzer-tests |
h4_harness fuzz-style tests |
zig build run-perf |
Combined QUIC + TCP throughput benchmark |
zig build debug-handshake / run-debug-handshake |
Standalone verbose vif↔vif handshake app |
zig build run-debug-handshake-loss |
Handshake profiler under simulated packet loss |
zig build run-debug-stream-loss |
Stream transfer profiler under simulated packet loss |
zig build clean |
Remove all build artifacts |
First build compiles aws-lc and picotls from source (5-10 min). Subsequent
builds skip the C step if the libraries are present for the current target
triple (tracked via zig-out/lib/.target).
Run zig build test alone is not sufficient to catch everything — dead code
in examples/ is not exercised by test; run plain zig build as well to
confirm the example binaries still compile.
Interop and example binaries
| Binary | Source | Purpose |
|---|---|---|
server |
examples/hq_server.zig |
HTTP/0.9-over-QUIC server (ALPN hq-interop), used by the Docker interop harness |
client |
examples/hq_client.zig |
HTTP/0.9-over-QUIC client, drives interop test cases from $REQUESTS |
perf_server / perf_client |
examples/perf_*.zig |
QUIC perf-scenario server/client |
perf_combined |
examples/perf_combined.zig |
QUIC server+client in one process |
perf_tcp_combined |
examples/perf_tcp_combined.zig |
TCP server+client in one process (cleartext) |
# HTTP/0.9-over-QUIC smoke test
zig build run-perf # QUIC + TCP throughput, both directions
Testing
vif-argent uses a layered testing pyramid (L1 unit -> L7 Docker interop); see docs/harness-architecture.md for the full breakdown of each layer, and docs/test-coverage-assessment.md for a per-file coverage audit against docs/quic-testable-behaviors-with-spec.md.
zig build test --summary all # unit + vif-vif + transport-layer tests
zig build deps # C library tests (aws-lc, picotls)
Interop testing (Docker)
interop/run.sh tests vif-argent's QUIC engine (VifEngine) against
independent QUIC implementations using the
QUIC interop runner container protocol.
# Build the vif-argent interop image
docker build -t vif-argent-server:latest .
# Run the full suite or a subset
./interop/run.sh
./interop/run.sh picoquic
./interop/run.sh ngtcp2 msquic
# Output: interop/RESULTS.md
docker-compose.yml / docker-compose.local.yml spin up a server+client pair
directly (see run_endpoint.sh for the entrypoint contract).
Project structure
vif-argent/
├── build.zig # Build configuration
├── build.zig.zon # Dependencies manifest
├── src/
│ ├── root.zig # Package root: transport, tcp, tls, o11y, h09, dispatch
│ ├── udp/
│ │ ├── transport.zig # UdpTransportWith event loop (QUIC)
│ │ ├── engine.zig # Engine driver contract
│ │ ├── socket.zig / real_socket.zig / fake_socket.zig # Socket trait + impls
│ │ └── *_harness.zig, *_test.zig # L2-L6 test harnesses (vif-vif, l4, lifecycle, scaling, qlog)
│ ├── tcp/
│ │ ├── transport.zig # TcpTransportWith event loop (TCP)
│ │ ├── engine.zig # PtlsEngine (picotls TLS 1.3), cleartext engine
│ │ ├── mux.zig # IdentityMux (stream multiplexing seam)
│ │ ├── ptls_bridge.c/h # C bridge over picotls's bitfield APIs
│ │ └── *_harness.zig, *_test.zig # TCP/TLS/mux/deadlock/lifecycle test suites
│ └── tls/
│ ├── cert_store.zig # Shared certificate loading
│ └── mtls_verifier.zig # Mutual-TLS verification
├── examples/
│ ├── hq_server.zig / hq_client.zig # HTTP/0.9-over-QUIC interop binaries
│ └── perf_*.zig # QUIC/TCP perf benchmark binaries
├── www/ # Static content served by the interop server
├── certs/ # Bundled test certificates (CN=test.example.com)
├── interop/
│ └── run.sh # QUIC interop test runner (Docker-based)
├── docs/
│ ├── harness-architecture.md # Test pyramid, harness internals
│ ├── udp-transport-event-loop.md # QUIC event loop design
│ ├── test-coverage-assessment.md # Per-file test coverage audit
│ ├── quic-testable-behaviors-with-spec.md
│ └── plans/ # Design docs for in-flight/completed work
├── deps/
│ ├── aws-lc/ # AWS cryptographic library (submodule)
│ └── picotls/ # TLS 1.3 (submodule)
├── Dockerfile, docker-compose*.yml, run_endpoint.sh # Interop container harness
└── zig-out/
├── bin/ # server, client, perf_*, debug-handshake, …
└── lib/ # libcrypto.a, libssl.a, libpicotls-*.a, …
Dependencies
| Library | Role |
|---|---|
| aws-lc | Cryptography (libcrypto, libssl) |
| picotls | TLS 1.3, used by the TCP transport's PtlsEngine |
QUIC itself (VifEngine) is pure Zig — no C QUIC stack. picoquic is used only
as an interop peer in interop/run.sh, not as a build dependency.
All C dependencies are built from source via CMake; no system libraries required beyond a C compiler, CMake, and Perl.
Resources
- Zig 0.16.0 documentation
- RFC 9000 — QUIC
- RFC 9001 — Using TLS to Secure QUIC
- RFC 9002 — QUIC Loss Detection and Congestion Control
License
BSD 3-Clause License — see LICENSE.