13 functions · signatures checked against lib/xtp2.h · fuzzed with libFuzzer

xtp2 Extension Reference

A binary application-layer protocol frame library over ordered byte streams: built in by build.bat xtp, a 32-byte header, four message types (REQUEST / RESPONSE / PUSH / EVENT), streaming incremental parsing, and a complete limits system. Two inline helpers (xtp2_text / xtp2_wants_reply) stay in the header for the script side to inline.

The wire format at a glance

xtp2 frame layout (big-endian) ┌──────────────────────────────────────────────┐ │ magic "xtp\2" 4B fixed tag + version │ │ total u32 whole-frame length │ │ id u64 message ID (request-response correlation) │ │ flags / type / command / params u16 each │ │ body u32 body length │ ├──────────────────────────────────────────────┤ │ [key:u16 value:u16] × params length table │ │ command data · parameter data · body │ └──────────────────────────────────────────────┘ type: REQUEST / RESPONSE / PUSH / EVENT · a request with id==0 needs no reply

Default limits: whole frame ≤1MiB, ≤256 parameters, command/key/value lengths each capped — all tighten-able in xtp2_config (see below). Parse errors are sticky: after an error, no further messages are produced until xtp2_reset.

Create & configure (3)

xtp2_config_init config

Initialize the configuration to defaults (all default limits + the default allocator).

void xtp2_config_init(xtp2_config *config);
Constraint: max_packet ∈ [32, UINT32_MAX]; the other limits must fit the wire

An invalid configuration (e.g. max_packet too small) returns E_ARGUMENT at create time — tightened limits never fail silently.

xtp2_create / xtp2_destroy lifecycle

Create / destroy a processor. Pass a NULL config for defaults.

xtp2_result xtp2_create(const xtp2_config *config, xtp2_processor **out); void xtp2_destroy(xtp2_processor *processor);
Threading: no concurrency within one processor; multiple processors are independentAllocator: config can inject a custom realloc (must be thread-safe)

Streaming parse (2)

xtp2_feed parse

Incrementally feed bytes: at most one message is produced per call; consumed tells you how much was taken.

xtp2_result xtp2_feed(xtp2_processor *processor, const void *data, size_t size, size_t *consumed, xtp2_message *message);
Returns: XTP2_MORE (need data) / XTP2_MESSAGE (produced) / negative (sticky error)Message: value-semantics out-param; use it in the callback/loop, then discard
Official usage (verbatim from lib/xtp2.h)source signatures
xtp2_processor *rx;
if ( xtp2_create(NULL, &rx) != XTP2_OK ) { ... }
while ( size ) {
    size_t iUsed;
    xtp2_message msg;
    xtp2_result r = xtp2_feed(rx, bytes, size, &iUsed, &msg);
    bytes += iUsed; size -= iUsed;
    if ( r < 0 ) break;                /* sticky error */
    if ( r == XTP2_MESSAGE ) { ... }  /* use/copy msg, then continue */
    if ( r == XTP2_MORE ) break;    /* wait for the next round of data */
}

xtp2_finish parse

End-of-stream check: at EOF with a partial frame pending, it returns an error (never a silent drop).

xtp2_result xtp2_finish(xtp2_processor *processor);
When: on reading EOF (connection closed)

Single frame & encode (3)

xtp2_decode parse

Single-frame decode of a complete buffer (zero incremental state).

xtp2_result xtp2_decode(xtp2_processor *processor, const void *data, size_t size, const xtp2_limits *limits, xtp2_message *message);
Scenario: the whole frame is already in hand (memory/file)

xtp2_measure / xtp2_encode encode

Measure, then write: measure computes the required byte count, encode writes into the buffer. On error the output buffer is never touched.

xtp2_result xtp2_measure(const xtp2_message *message, const xtp2_limits *limits, size_t *out_size); xtp2_result xtp2_encode(const xtp2_message *message, const xtp2_limits *limits, void *out, size_t out_size);
Discipline: source and destination of an encode must not overlapRound-trip: decode→encode is byte-identical (a fuzz invariant)

Parameters & errors (5)

xtp2_params / xtp2_param_next parameters

The parameter iterator: fetch the head pointer / advance to the next key-value span pair.

xtp2_iter xtp2_params(const xtp2_message *message); bool xtp2_param_next(xtp2_iter *iter, xtp2_span *key, xtp2_span *value);
span: explicit byte length, never an implicit strlen

xtp2_find parameters

Look up a parameter value by exact binary match.

bool xtp2_find(const xtp2_message *message, xtp2_span key, xtp2_span *value);

xtp2_reset / xtp2_error_string state

Clear the sticky error so the processor is reusable / turn an error code into description text.

void xtp2_reset(xtp2_processor *processor); const char *xtp2_error_string(xtp2_result result);
Semantics: errors are sticky until reset