|
cwist
Modern C web framework with libttak runtime
|
Implementation of the CWIST sequenced-message protocol. More...

Go to the source code of this file.
Functions | |
| bool | cwist_seq_chunk_parse (const uint8_t *data, size_t len, cwist_seq_chunk_t *out) |
| Parse and validate a sequenced chunk header. | |
| void | cwist_seq_chunk_build_header (uint8_t out[CWIST_SEQ_HEADER_SIZE], uint16_t seq, uint16_t total, uint16_t payload_len, uint16_t chunk_size) |
| Serialize a chunk header into an 8-byte buffer. | |
| bool | cwist_seq_split (const uint8_t *data, size_t len, uint16_t chunk_payload_size, cwist_seq_message_t *out) |
| Split a message buffer into sequenced chunks. | |
| void | cwist_seq_message_free (cwist_seq_message_t *msg) |
| Free all memory owned by a cwist_seq_message_t. | |
| cwist_seq_assembler_t * | cwist_seq_assembler_create (void) |
| Create an assembler with no reassembled-size limit. | |
| cwist_seq_assembler_t * | cwist_seq_assembler_create_limited (size_t max_data_len) |
| Create an assembler with a reassembled-size limit. | |
| void | cwist_seq_assembler_destroy (cwist_seq_assembler_t *a) |
| Destroy an assembler and free all its buffers. | |
| void | cwist_seq_assembler_reset (cwist_seq_assembler_t *a) |
| Discard all received state, keeping the size limit. | |
| bool | cwist_seq_assembler_feed (cwist_seq_assembler_t *a, const cwist_seq_chunk_t *chunk) |
| Feed one sequenced chunk into the assembler. | |
| bool | cwist_seq_assembler_is_complete (const cwist_seq_assembler_t *a) |
| Check whether all chunks of the message have been received intact. | |
| size_t | cwist_seq_assembler_recovery_targets (const cwist_seq_assembler_t *a, uint16_t *out, size_t out_cap) |
| List the sequence numbers of missing chunks. | |
| bool | cwist_seq_assembler_get_data (cwist_seq_assembler_t *a, const uint8_t **out_data, size_t *out_len) |
| Access the fully reassembled message. | |
Implementation of the CWIST sequenced-message protocol.
Definition in file seq.c.
| cwist_seq_assembler_t * cwist_seq_assembler_create | ( | void | ) |
Create an assembler with no reassembled-size limit.
Create an empty assembler.
Definition at line 196 of file seq.c.
References cwist_seq_assembler_create_limited().
Referenced by cwist_jwt_join_chunks(), and cwist_websocket_receive_sequenced().
| cwist_seq_assembler_t * cwist_seq_assembler_create_limited | ( | size_t | max_data_len | ) |
Create an assembler with a reassembled-size limit.
Create an assembler with a maximum possible reassembled size.
Allocates an empty assembler state; buffers are allocated lazily on the first cwist_seq_assembler_feed() call. Destroy with cwist_seq_assembler_destroy().
| max_data_len | Maximum accepted reassembled size in bytes, or 0 to use the CWIST_SEQ_MAX_REASSEMBLED_SIZE default. |
Definition at line 211 of file seq.c.
References cap, and cwist_alloc().
Referenced by cwist_http2_serve_connection_ex(), and cwist_seq_assembler_create().
| void cwist_seq_assembler_destroy | ( | cwist_seq_assembler_t * | a | ) |
Destroy an assembler and free all its buffers.
Destroy an assembler and its internal buffer.
| a | Assembler to destroy; may be NULL. |
Definition at line 223 of file seq.c.
References cap, and cwist_free().
Referenced by cwist_jwt_join_chunks(), and cwist_websocket_receive_sequenced().
| bool cwist_seq_assembler_feed | ( | cwist_seq_assembler_t * | a, |
| const cwist_seq_chunk_t * | chunk | ||
| ) |
Feed one sequenced chunk into the assembler.
Feed one parsed chunk into the assembler.
The first valid chunk establishes the message's total and chunk_size; subsequent chunks must match them or are rejected. Identical duplicates are accepted idempotently; a conflicting duplicate is flagged as contamination (retaining the original bytes) and never overwrites good data. The total message length is determined only when the final chunk (seq == total) arrives, so reordered delivery is tolerated. On allocation failure all state is cleared and false is returned.
| a | Assembler to feed. |
| chunk | Parsed chunk to accept; payload bytes are copied into the reassembly buffer. |
| true | The chunk was accepted (new data or an identical duplicate). |
| false | Invalid or inconsistent chunk, conflicting duplicate (contamination), size-limit exceeded, or allocation failure. |
Definition at line 268 of file seq.c.
References cap, cwist_alloc(), cwist_alloc_array(), cwist_free(), CWIST_SEQ_MAX_CHUNKS, and CWIST_SEQ_MAX_REASSEMBLED_SIZE.
Referenced by cwist_http2_serve_connection_ex(), cwist_jwt_join_chunks(), and cwist_websocket_receive_sequenced().
| bool cwist_seq_assembler_get_data | ( | cwist_seq_assembler_t * | a, |
| const uint8_t ** | out_data, | ||
| size_t * | out_len | ||
| ) |
Access the fully reassembled message.
Borrow the assembled message when complete.
Succeeds only when cwist_seq_assembler_is_complete() is true. The returned pointer refers to the assembler's internal buffer, which remains valid until the assembler is reset, destroyed, or fed another chunk; ownership stays with the assembler.
| a | Assembler to query. |
| out_data | Receives a pointer to the reassembled bytes. |
| out_len | Receives the reassembled length in bytes. |
| true | The message is complete; outputs are populated. |
| false | The message is incomplete or an output pointer is NULL. |
Definition at line 390 of file seq.c.
References cap, and cwist_seq_assembler_is_complete().
Referenced by cwist_http2_serve_connection_ex(), cwist_jwt_join_chunks(), and cwist_websocket_receive_sequenced().
| bool cwist_seq_assembler_is_complete | ( | const cwist_seq_assembler_t * | a | ) |
Check whether all chunks of the message have been received intact.
Return true when every expected chunk has been received.
Completion requires every chunk to be present, no conflicting duplicates (contamination), and the final chunk to have arrived so the total length is known.
| a | Assembler to query; may be NULL. |
| true | The message is fully reassembled and clean. |
| false | Not complete, or a is NULL. |
Definition at line 343 of file seq.c.
References cap.
Referenced by cwist_seq_assembler_get_data(), cwist_seq_assembler_recovery_targets(), and cwist_websocket_receive_sequenced().
| size_t cwist_seq_assembler_recovery_targets | ( | const cwist_seq_assembler_t * | a, |
| uint16_t * | out, | ||
| size_t | out_cap | ||
| ) |
List the sequence numbers of missing chunks.
Return the sequence numbers still required to complete a message.
Returns the count of missing chunks and, when out has capacity, writes their 1-based sequence numbers in ascending order. Returns 0 if the assembler has no state or the message is already complete; in those cases nothing is written to out.
| a | Assembler to query; may be NULL. |
| out | Optional array to receive missing sequence numbers. |
| out_cap | Number of elements out can hold; ignored when out is NULL. |
out_cap). Definition at line 362 of file seq.c.
References cap, and cwist_seq_assembler_is_complete().
| void cwist_seq_assembler_reset | ( | cwist_seq_assembler_t * | a | ) |
Discard all received state, keeping the size limit.
Reset an assembler so it can receive a new message.
Frees the reassembly buffers but retains the max_data_len configured at creation so the assembler can be reused for a new message. Does nothing if a is NULL.
| a | Assembler to reset; may be NULL. |
Definition at line 240 of file seq.c.
References cap, and cwist_free().
| void cwist_seq_chunk_build_header | ( | uint8_t | out[CWIST_SEQ_HEADER_SIZE], |
| uint16_t | seq, | ||
| uint16_t | total, | ||
| uint16_t | payload_len, | ||
| uint16_t | chunk_size | ||
| ) |
Serialize a chunk header into an 8-byte buffer.
Write an 8-byte sequence header.
Encodes seq, total, payload_len, and chunk_size as big-endian 16-bit fields. Performs no validation; callers must supply a consistent sequence pair (see cwist_seq_chunk_parse()).
| out | Buffer of CWIST_SEQ_HEADER_SIZE bytes to write. |
| seq | Chunk sequence number (1-based). |
| total | Total number of chunks in the message. |
| payload_len | Payload bytes in this chunk. |
| chunk_size | Full payload size of every non-final chunk. |
Definition at line 97 of file seq.c.
Referenced by cwist_seq_split().
| bool cwist_seq_chunk_parse | ( | const uint8_t * | data, |
| size_t | len, | ||
| cwist_seq_chunk_t * | out | ||
| ) |
Parse and validate a sequenced chunk header.
Parse a sequence chunk from raw bytes.
Reads the fixed-size chunk header from data and fills out. The payload pointer in out references memory inside data and is not copied. The chunk is rejected if the sequence pair (seq/total) is missing, out of range, or inconsistent, or if the payload length fields disagree with the buffer length.
| data | Buffer containing at least CWIST_SEQ_HEADER_SIZE bytes. |
| len | Length of data in bytes. |
| out | Receives the parsed chunk fields on success. |
| true | The chunk is valid and out is populated. |
| false | Invalid arguments or a malformed chunk; out is untouched. |
Definition at line 63 of file seq.c.
References cap, cwist_seq_chunk::chunk_size, CWIST_SEQ_HEADER_SIZE, CWIST_SEQ_MAX_CHUNKS, cwist_seq_chunk::payload, cwist_seq_chunk::payload_len, cwist_seq_chunk::seq, and cwist_seq_chunk::total.
Referenced by cwist_http2_serve_connection_ex(), cwist_jwt_join_chunks(), cwist_seq_auth_wrap(), and cwist_websocket_receive_sequenced().
| void cwist_seq_message_free | ( | cwist_seq_message_t * | msg | ) |
Free all memory owned by a cwist_seq_message_t.
Free all buffers allocated by cwist_seq_split().
Releases each chunk buffer plus the chunk and length arrays, then zeroes the struct so it is safe to reuse. Does nothing if msg is NULL.
| msg | Message to free; may be NULL. |
Definition at line 178 of file seq.c.
References cap, and cwist_free().
Referenced by cwist_jwt_split_chunks(), and cwist_websocket_send_sequenced().
| bool cwist_seq_split | ( | const uint8_t * | data, |
| size_t | len, | ||
| uint16_t | chunk_payload_size, | ||
| cwist_seq_message_t * | out | ||
| ) |
Split a message buffer into sequenced chunks.
Split data into sequenced chunks.
Allocates each chunk with cwist_alloc() and writes it into out; the result is released with cwist_seq_message_free(). Every chunk except the last carries exactly chunk_payload_size payload bytes. out is zeroed before use and again on failure.
| data | Message bytes to split. |
| len | Length of data in bytes. |
| chunk_payload_size | Payload bytes per chunk; must be non-zero. |
| out | Receives the chunk array on success. |
| true | out holds out->count chunks. |
| false | Invalid arguments, or the message would exceed the chunk or reassembled-size limits, or allocation failed; out is zeroed. |
Definition at line 125 of file seq.c.
References cap, cwist_seq_message::chunk_lens, cwist_seq_message::chunks, cwist_seq_message::count, cwist_alloc(), cwist_alloc_array(), cwist_free(), cwist_seq_chunk_build_header(), CWIST_SEQ_HEADER_SIZE, CWIST_SEQ_MAX_CHUNKS, and CWIST_SEQ_MAX_REASSEMBLED_SIZE.
Referenced by cwist_jwt_split_chunks(), and cwist_websocket_send_sequenced().