What Is xqc_engine_register_alpn in XQUIC? ALPN Registration Explained
xqc_engine_register_alpn binds an Application-Layer Protocol Negotiation (ALPN) identifier to an XQUIC engine, enabling the TLS handshake to advertise supported protocols while routing incoming connections to the correct protocol-specific callback handlers.
After creating an xqc_engine_t instance in the alibaba/xquic repository, developers use xqc_engine_register_alpn to declare which application protocols the engine supports. This function serves as the bridge between TLS-level ALPN negotiation and XQUIC's modular protocol stack, allowing a single engine to simultaneously handle HTTP/3, HQ, or custom transport protocols without reconstruction.
How xqc_engine_register_alpn Works
The function performs three coordinated tasks to integrate protocol support into the engine:
-
TLS Context Registration – Calls
xqc_tls_ctx_register_alpnto append raw ALPN bytes to the internalalpn_listbuffer, ensuring the TLS handshake advertises supported protocols to peers. -
Callback Storage – Saves an
xqc_app_proto_callbacks_tstructure in anxqc_alpn_registration_tentry within the engine'salpn_reg_list. This table contains functions for connection creation, packet processing, and stream handling specific to the protocol. -
Lookup Helper Registration – Enables subsequent retrieval via
xqc_engine_get_alpn_callbacksandxqc_engine_get_alpn_ctx, allowing the engine to route packets to the correct module after ALPN selection.
This architecture enables multi-protocol support and runtime callback updates without rebuilding the engine. The internal relationship between components follows this structure:
+-------------------+ +------------------------+
| xqc_engine_t | <----> | xqc_tls_ctx_t |
| - alpn_reg_list | | - alpn_list (raw bytes)|
| - callbacks ... | +------------------------+
+-------------------+
|
| xqc_engine_register_alpn(...)
v
+-------------------------------+
| xqc_alpn_registration_t |
| - alpn string |
| - ap_cbs (protocol callbacks)|
| - alp_ctx (user data) |
+-------------------------------+
Implementation in the XQUIC Source
The registration logic resides in src/transport/xqc_engine.c, where the public API validates inputs and delegates to internal helpers that synchronize state with the TLS layer.
Engine Registration Logic
In src/transport/xqc_engine.c (lines 1396–1420), xqc_engine_register_alpn validates parameters and delegates to xqc_engine_add_alpn:
xqc_int_t
xqc_engine_register_alpn(xqc_engine_t *engine, const char *alpn, size_t alpn_len,
xqc_app_proto_callbacks_t *ap_cbs, void *alp_ctx)
{
/* validation, duplicate check, and delegation */
return xqc_engine_add_alpn(engine, alpn, alpn_len, ap_cbs, alp_ctx);
}
The internal xqc_engine_add_alpn function checks for duplicate entries at lines 1007–1015. If the ALPN already exists, it updates the stored callbacks rather than creating a new registration, enabling hot-swapping of protocol handlers.
TLS Layer Integration
The TLS context receives length-prefixed ALPN bytes through xqc_tls_ctx_register_alpn in src/tls/xqc_tls_ctx.c (lines 38–73):
xqc_int_t
xqc_tls_ctx_register_alpn(xqc_tls_ctx_t *ctx, const char *alpn, size_t alpn_len)
{
/* buffer growth and formatting via snprintf("%c%s", len, alpn) */
return XQC_OK;
}
This appends the ALPN to the alpn_list buffer used during ClientHello and ServerHello processing, as documented in the public API at docs/API.md.
Practical Code Examples
Registering a Custom Transport Protocol
To add support for a custom protocol like "myproto", define the callbacks and register them after engine creation:
/* Define protocol-specific callbacks */
static xqc_app_proto_callbacks_t my_proto_cbs = {
.conn_cbs.conn_create_notify = my_conn_create,
.stream_cbs.stream_open_notify = my_stream_open,
/* additional handlers... */
};
/* Create engine and register ALPN */
xqc_engine_t *engine = xqc_engine_create(...);
xqc_int_t ret = xqc_engine_register_alpn(engine,
"myproto", 7,
&my_proto_cbs,
NULL); /* optional user context */
if (ret != XQC_OK) {
/* handle registration failure */
}
Source: Reference implementation in tests/unittest/xqc_packet_test.c (lines 69–71) demonstrates this pattern for the "transport" ALPN.
Updating Callbacks at Runtime
XQUIC supports dynamic callback replacement by re-registering the same ALPN. When duplicate detection triggers at lines 1007–1015 in src/transport/xqc_engine.c, the engine replaces the existing callback table:
/* Define updated callback table */
xqc_app_proto_callbacks_t new_cbs = {
.conn_cbs.conn_create_notify = new_conn_create,
.stream_cbs.stream_write_notify = new_stream_write,
};
/* Re-register to hot-swap handlers for existing "transport" ALPN */
xqc_engine_register_alpn(engine, "transport", 9, &new_cbs, NULL);
Retrieving User Context
Store and retrieve protocol-specific user data via the registration API:
/* Register with custom context pointer */
void *my_ctx = custom_protocol_state;
xqc_engine_register_alpn(engine, "hq", 2, &hq_cbs, my_ctx);
/* Later retrieval during connection handling */
void *retrieved_ctx = xqc_engine_get_alpn_ctx(engine, "hq", 2);
if (retrieved_ctx) {
/* access custom protocol state */
}
The xqc_engine_get_alpn_ctx function is implemented in src/transport/xqc_engine.c (lines 24–38).
Key Source Files
-
src/transport/xqc_engine.c– Core registration logic, duplicate detection (lines 1007–1015), and lookup helpersxqc_engine_get_alpn_ctxandxqc_engine_get_alpn_callbacks.
View source -
src/tls/xqc_tls_ctx.c– TLS-level ALPN buffer management viaxqc_tls_ctx_register_alpn.
View source -
include/xquic/xquic.h– Public API declarations forxqc_engine_register_alpnand thexqc_app_proto_callbacks_tstructure.
View source -
demo/xqc_hq_ctx.c– Production example registering "hq" and "hq-29" ALPNs with complete callback implementations.
View source
Summary
xqc_engine_register_alpnis the mandatory API for binding ALPN identifiers to protocol implementations in alibaba/xquic.- The function registers ALPN strings with the underlying TLS context while storing callback tables in the engine's
alpn_reg_list. - It supports multi-protocol engines by allowing multiple registrations on a single
xqc_engine_tinstance. - Runtime updates are supported through duplicate detection logic that replaces existing callback tables rather than failing.
- Lookup helpers like
xqc_engine_get_alpn_ctxenable protocol-specific state retrieval during connection and stream processing.
Frequently Asked Questions
What does ALPN negotiation accomplish in XQUIC?
ALPN (Application-Layer Protocol Negotiation) allows the client and server to agree on which application protocol to use—such as HTTP/3 ("h3") or HQ ("hq")—during the TLS handshake. The xqc_engine_register_alpn function ensures the engine advertises supported protocols via the TLS layer and routes negotiated connections to the appropriate callback handlers.
Can a single XQUIC engine support multiple protocols simultaneously?
Yes. By calling xqc_engine_register_alpn multiple times with different ALPN strings, a single engine instance can handle multiple protocols concurrently. The engine maintains an alpn_reg_list (a linked list of xqc_alpn_registration_t entries), with each node containing distinct callback tables for its respective protocol.
How does xqc_engine_register_alpn handle duplicate ALPN registrations?
When the function detects an existing registration for the same ALPN string (implemented in xqc_engine_add_alpn at lines 1007–1015 of src/transport/xqc_engine.c), it updates the stored xqc_app_proto_callbacks_t pointer and user context rather than returning an error. This design enables hot-swapping of protocol handlers at runtime without destroying the engine.
Where is the ALPN data stored after registration?
The ALPN identifier exists in two locations: the raw length-prefixed bytes reside in the TLS context's alpn_list buffer (managed in src/tls/xqc_tls_ctx.c), while the structured registration entry containing the callback table and user context resides in the engine's alpn_reg_list (managed in src/transport/xqc_engine.c). This separation allows the TLS layer to handle handshake advertisement while the transport layer manages protocol-specific behavior.
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 →