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 events
  • xqc_conn_callbacks_t – Connection lifecycle events
  • xqc_stream_callbacks_t – Stream operations
  • xqc_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 changes
  • path_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" in xquic.h lines 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 per xquic.h lines 780-800)
  • stream_read_notify – Required by both sides
  • stream_write_notify – Required by both sides
  • stream_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 server
  • save_session_cb – Persist TLS session information for 0-RTT
  • save_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_notify
  • stream_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_notify and stream_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, and stream_close_notify for 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →