< Previous: Performance Metrics | π Home
Architecture & Examples
cpp-quic is designed as a layered protocol implementation, with the QUIC layer sitting cleanly on top of cpp-udpnetβs UDP transport.
Protocol Stack
βββββββββββββββββββββββββββββββββββββββββββ
β Application (Your Code) β
βββββββββββββββββββββββββββββββββββββββββββ€
β QuicServer / QuicClient β
β (Connection mgmt, stream dispatch) β
βββββββββββββββββββββββββββββββββββββββββββ€
β QuicConnection β
β (Handshake, ACKs, retransmission, β
β packet numbers, stream mux) β
βββββββββββββββββββββββββββββββββββββββββββ€
β QuicStream β
β (Ordered byte-stream, flow control, β
β FIN handling, reassembly) β
βββββββββββββββββββββββββββββββββββββββββββ€
β QuicPacket (Serialization/Deser) β
βββββββββββββββββββββββββββββββββββββββββββ€
β cpp-udpnet (UdpListener/Sender) β
β (UDP transport, socket mgmt, polling) β
βββββββββββββββββββββββββββββββββββββββββββ€
β OS UDP Sockets β
βββββββββββββββββββββββββββββββββββββββββββ
Threading Model & Event Loop
cpp-quic is built around an event-driven architecture powered by cpp-pubsub and cpp-asyncworker to maximize performance and avoid blocking:
- I/O Polling Loop (via
cpp-udpnet): A background thread polls the UDP socket, reads incoming packets, processes the QUIC protocol layer, and publishes events (e.g., connection events, stream data events) to an internal event broker. - Event Worker Thread (via
cpp-pubsub): A background thread monitors the event broker, dispatches events to subscribers, and drives the protocolβs maintenance ticks (running every 10ms to handle packet retransmissions, pacing, idle timeouts, and connection cleanup). - Asynchronous Callback Dispatch (via
cpp-asyncworker): Application-level callbacks (such as the connection handler, stream data handler, and flow control handler) are enqueued to an internal thread pool. This ensures that user code does not block the time-critical I/O or protocol maintenance loops.
[!WARNING] Because application callbacks run asynchronously on thread pool threads, your callback code must be thread-safe when accessing shared application state.
Packet Pipeline
When a datagram arrives at the server:
UdpListenerreceives the raw bytes from the UDP socket.- The QUIC layer deserializes the bytes into a
QuicPacket. - The packetβs connection ID is used to look up the
QuicConnection. - Each frame in the packet is processed:
- CRYPTO β Reassemble crypto fragments in order per encryption level (RFC 9000 Β§7.4) and feed the data into TLS to drive the handshake.
- STREAM β Deliver data to the target
QuicStream, send ACK in the corresponding packet number space. - ACK β Process RFC 9000-compliant ACK ranges (gaps and lengths) and remove acknowledged packets from the retransmission queue.
- PING β Touch connection activity, send ACK
- CONNECTION_CLOSE β Transition connection to Closed
- RESET_STREAM β Reset the target stream
- PATH_CHALLENGE β Respond with a PATH_RESPONSE frame
- PATH_RESPONSE β Validate path and update active path status
- STOP_SENDING β Reset stream and send a RESET_STREAM frame
- MAX_DATA / MAX_STREAM_DATA β Update flow control send limits and trigger queued packet generation
- HANDSHAKE_DONE β Confirm client connection handshake completion
Included Examples
The examples/ directory contains several complete, buildable programs:
server.cpp: Demonstrates setting up aQuicServer, accepting connections, handling stream data with echo logic, and subscribing to connection events.client.cpp: Shows how to useQuicClientto connect to a server, open a bidirectional stream, and send/receive data.stream_transfer.cpp: Demonstrates multi-stream concurrent data transfer with performance metrics.throughput.cpp: Measures QUIC throughput usingQuicProfile::HighThroughput()with detailed metrics including retransmissions, peak/average throughput, backpressure mode, and packet counts.
To build the examples, configure CMake from the project root:
mkdir build && cd build
cmake ..
cmake --build .
| < Previous: Performance Metrics | π Home |