XQUIC Callback Functions: Required Server vs Client Implementation Guide
Server and client modes in XQUIC require distinct mandatory callback functions—servers must implement connection and stream creation notifications along with address change handlers, while clients must implement state persistence callbacks for tokens, sessions, and transport parameters to support 0-RTT and connection resumption.
XQUIC is Alibaba's high-performance QUIC and HTTP/3 implementation. When building applications with this library, understanding which XQUIC callback functions are mandatory for server versus client mode is critical for proper connection lifecycle management. This guide maps the required callbacks based on the actual source code definitions in include/xquic/xquic.h and the reference implementations in the mini/ directory.
Understanding XQUIC Callback Architecture
XQUIC separates engine-level transport callbacks from application-layer callbacks for connections, streams, and datagrams. The library uses several key structures defined in include/xquic/xquic.h:
xqc_transport_callbacks_t– Low-level transport eventsxqc_conn_callbacks_t– Connection lifecycle eventsxqc_stream_callbacks_t– Stream operationsxqc_datagram_callbacks_t– QUIC datagram extension (optional)xqc_app_proto_callbacks_t– Bundles the above for ALPN registration
Required XQUIC Callback Functions for Server Mode
Server implementations must handle incoming connections and address changes. The mandatory callbacks differ significantly from client requirements.
Engine Transport Callbacks
According to include/xquic/xquic.h, servers must implement:
path_created_notify– Required when multipath is enabled (lines 90-112)conn_peer_addr_changed_notify– Mandatory for reporting peer address changespath_peer_addr_changed_notify– Mandatory for reporting path-specific address changes
Connection Callbacks
Servers must provide:
conn_create_notify– Invoked immediately after a new connection object is allocated (marked "REQUIRED for server" inxquic.hlines 730-750)conn_close_notify– Required by both server and client for proper cleanup
Stream Callbacks
For stream handling, servers must implement:
stream_create_notify– Called when a peer creates a new stream (required perxquic.hlines 780-800)stream_read_notify– Required by both sidesstream_write_notify– Required by both sidesstream_close_notify– Required by both sides
Required XQUIC Callback Functions for Client Mode
Client implementations focus on state persistence for 0-RTT and connection resumption rather than connection acceptance.
Engine Transport Callbacks for State Persistence
Clients must implement these callbacks to support 0-RTT and session resumption (defined in xquic.h lines 66-88):
save_token– Store the address validation token received from the serversave_session_cb– Persist TLS session information for 0-RTTsave_tp_cb– Persist transport parameters for subsequent connections
Connection and Stream Callbacks
Unlike servers, clients treat these as optional:
conn_create_notify– Optional for clients (NULL is acceptable)stream_create_notify– Optional for clients
However, clients must still provide:
conn_close_notifystream_read_notify,stream_write_notify,stream_close_notify
Multipath Support
If the client enables multipath:
ready_to_create_path_notify– Required to signal when additional paths can be established
Implementation Examples
The mini/ directory contains reference implementations demonstrating these requirements.
Server callback structure from mini/mini_server_cb.h:
static xqc_conn_callbacks_t sv_conn_cbs = {
.conn_create_notify = my_server_conn_create, /* REQUIRED */
.conn_close_notify = my_server_conn_close, /* REQUIRED */
.conn_handshake_finished = NULL,
};
static xqc_stream_callbacks_t sv_stream_cbs = {
.stream_read_notify = my_server_stream_read,
.stream_write_notify = my_server_stream_write,
.stream_create_notify = my_server_stream_create, /* REQUIRED */
.stream_close_notify = my_server_stream_close,
.stream_closing_notify = NULL,
};
static xqc_transport_callbacks_t sv_transport_cbs = {
.path_created_notify = my_server_path_created, /* REQUIRED for MP */
.conn_peer_addr_changed_notify = my_server_peer_addr_changed, /* REQUIRED */
.path_peer_addr_changed_notify = my_server_path_addr_changed, /* REQUIRED */
};
Client callback structure from mini/mini_client_cb.h:
static xqc_conn_callbacks_t cl_conn_cbs = {
.conn_create_notify = NULL, /* optional for client */
.conn_close_notify = my_client_conn_close, /* REQUIRED */
.conn_handshake_finished = NULL,
};
static xqc_stream_callbacks_t cl_stream_cbs = {
.stream_read_notify = my_client_stream_read,
.stream_write_notify = my_client_stream_write,
.stream_create_notify = NULL, /* optional for client */
.stream_close_notify = my_client_stream_close,
};
static xqc_transport_callbacks_t cl_transport_cbs = {
.save_token = my_client_save_token, /* REQUIRED */
.save_session_cb = my_client_save_session, /* REQUIRED */
.save_tp_cb = my_client_save_tp, /* REQUIRED */
.ready_to_create_path_notify = my_client_ready_path, /* REQUIRED for MP */
};
Key Source Files and References
When implementing XQUIC callback functions, consult these specific files in the Alibaba XQUIC repository:
| File | Purpose |
|---|---|
include/xquic/xquic.h |
Central definitions of all callback structures (xqc_transport_callbacks_t, xqc_conn_callbacks_t, xqc_stream_callbacks_t, xqc_datagram_callbacks_t) with "REQUIRED" annotations |
include/xquic/xquic_typedef.h |
Type aliases and callback function signatures |
src/transport/xqc_engine.h |
Engine configuration and xqc_engine_callback_t for timer, log, and CID management |
mini/mini_server_cb.h |
Reference server callback implementations |
mini/mini_client_cb.h |
Reference client callback implementations |
mini/mini_server.c / mini/mini_client.c |
Complete working examples showing registration via xqc_engine_register_alpn() |
Summary
Implementing XQUIC callback functions correctly depends entirely on whether you are building a server or client:
- Server mode requires handling incoming connections via
conn_create_notifyandstream_create_notify, plus address change notifications (conn_peer_addr_changed_notify,path_peer_addr_changed_notify) and multipath creation events when enabled. - Client mode requires state persistence callbacks (
save_token,save_session_cb,save_tp_cb) to support 0-RTT and session resumption, while connection and stream creation notifications remain optional. - Both modes must implement
conn_close_notify,stream_read_notify,stream_write_notify, andstream_close_notifyfor proper connection lifecycle management.
Frequently Asked Questions
What happens if I don't implement the required server callbacks in XQUIC?
If you omit mandatory server callbacks such as conn_create_notify or stream_create_notify, the XQUIC engine will fail to properly initialize incoming connections or streams, typically resulting in connection timeouts, protocol errors, or null pointer dereferences when the engine attempts to invoke the missing callback.
Are the XQUIC callback requirements different for HTTP/3 versus raw QUIC?
The core callback requirements remain the same for both HTTP/3 and raw QUIC applications because they operate at the transport layer. However, HTTP/3 implementations typically use additional application-layer callbacks for header processing and request handling, while the underlying xqc_transport_callbacks_t, xqc_conn_callbacks_t, and xqc_stream_callbacks_t requirements follow the same server vs. client rules outlined in this guide.
Do I need to implement all datagram callbacks for QUIC datagram support?
No, you only need to implement the specific datagram callbacks your application uses. For receiving datagrams, implement datagram_read_notify; for sending, implement datagram_write_notify. The other datagram callbacks such as datagram_acked_notify, datagram_lost_notify, and datagram_mss_updated_notify are optional and only needed if your application requires acknowledgment tracking or MSS change notifications.
Can I use the same callback functions for both server and client modes in XQUIC?
While some callbacks like conn_close_notify, stream_read_notify, stream_write_notify, and stream_close_notify are universal and can be shared, you cannot use identical callback sets for both modes because each mode has unique mandatory requirements. Servers must implement connection acceptance callbacks (conn_create_notify, stream_create_notify) and address change handlers, while clients must implement state persistence callbacks (save_token, save_session_cb, save_tp_cb). Attempting to register a server callback structure on a client engine (or vice versa) will result in missing required functionality or connection failures.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →