CoQUIC is driven by the caller runtime. The library does not own the event loop, UDP sockets, timers, worker threads, or persistent storage.
Event Loop
A typical runtime loop:
- Read UDP datagrams from the socket.
- Convert each datagram to
coquic::core::InboundDatagram. - Call
Endpoint::input_datagramorquic::Endpoint::receive_datagram. - Send every returned
SendDatagrameffect. - Dispatch stream, DATAGRAM, lifecycle, state, token, qlog, and diagnostic effects to the application.
- Arm the next timer from
Result::next_wakeuporEndpoint::next_wakeup. - On timer expiry, call
timer_expired. - For application writes, call
advance_connectionor thequic::Connectionandquic::Streamhelpers.
Every endpoint method takes coquic::core::TimePoint. Use one monotonic runtime clock consistently for all calls on an endpoint.
Sending Datagrams
SendDatagram effects are the only network output. The runtime sends:
bytes: UDP payload.route_handle: selected local route, if present.ecn: ECN codepoint requested by the endpoint.is_pmtu_probe: whether the datagram is a PMTU probe.
Send all produced datagrams before waiting for more socket or timer input. If send_continuation_pending or Endpoint::has_send_continuation_pending() is true, call back into the endpoint without blocking so pending send work can continue.
Timers
Always arm the runtime timer from the most recent result:
- Prefer
Result::next_wakeupwhen processing a call result. - Use
Endpoint::next_wakeup()when the runtime needs the current endpoint deadline outside a call result. - If no wakeup is present, no timer is currently needed.
Timer callbacks should call timer_expired(now) and process the returned effects exactly like network or application input.
Errors
core::LocalError reports synchronous API misuse or locally detected failure. It does not send UDP bytes by itself. Treat it as an application signal and keep processing any returned effects that are valid for the call.
For HTTP/3, terminal_failure and has_failed() report protocol-layer failure. Request-level failures are returned as request error or cancellation events.
Checklist
- Include public headers from
include/coquic/. - Do not include internal headers from
src/. - Keep one monotonic clock source per endpoint.
- Preserve route-handle identity between inbound datagrams and outbound sends.
- Send every
SendDatagrameffect. - Re-arm the timer after each endpoint call.
- Feed HTTP/3
quic_inputsto the matching QUIC connection. - Persist resumption state and address-validation tokens only if the application wants to reuse them.
- Treat diagnostics as observability data, not protocol commands.
Build Notes
Inside this repository, zig build adds include/ to the project library, executables, and tests. Public API smoke tests live in tests/api/public_api_test.cpp and are run by:
nix develop -c zig build testPackaging and installation of exported headers for external consumers is still separate from the in-repo build.