|
Csilk 0.2.1
A lightweight, high-performance C HTTP web framework
|
Internal framework primitives — crypto, codec, MQ, and dispatch. More...
#include <setjmp.h>#include <stddef.h>#include <stdint.h>#include <uv.h>#include "csilk/csilk.h"#include "csilk/test/test.h"

Go to the source code of this file.
Data Structures | |
| struct | csilk_sha1_ctx |
| SHA-1 hashing context. More... | |
| struct | csilk_sha256_ctx |
| SHA-256 hashing context. More... | |
| struct | csilk_mq_msg_t |
Internal: A single message in the MQ linked-list queue. Messages are heap-allocated and linked via next. More... | |
| struct | csilk_mq_topic_t |
| Internal: A topic node in the MQ's linked list of topics. Holds the topic name and its associated middleware + subscriber chain. More... | |
| struct | csilk_mq_t |
| Internal: The Message Queue instance. More... | |
| struct | csilk_mq_ctx_t |
| Internal: Per-message MQ context passed to middleware and subscribers. More... | |
| struct | csilk_mq_work_ctx_t |
| Internal: Context passed to libuv's thread-pool work callback. More... | |
Functions | |
| void | csilk_sha1_init (csilk_sha1_ctx *context) |
| Initialise a SHA-1 hashing context. | |
| void | csilk_sha1_update (csilk_sha1_ctx *context, const uint8_t *data, size_t len) |
| Feed data into the SHA-1 hashing context. | |
| void | csilk_sha1_final (csilk_sha1_ctx *context, uint8_t digest[20]) |
| Finalise the SHA-1 hash and write the 20-byte digest. | |
| void | csilk_sha256_init (csilk_sha256_ctx *context) |
| Initialise a SHA-256 hashing context. | |
| void | csilk_sha256_update (csilk_sha256_ctx *context, const uint8_t *data, size_t len) |
| Feed data into the SHA-256 hashing context. | |
| void | csilk_sha256_final (csilk_sha256_ctx *context, uint8_t digest[32]) |
| Finalise the SHA-256 hash and write the 32-byte digest. | |
| void | csilk_hmac_sha256 (const uint8_t *key, size_t key_len, const uint8_t *data, size_t data_len, uint8_t out[32]) |
| Compute HMAC-SHA256 (keyed-hash message authentication code). | |
| void | csilk_base64_encode (const uint8_t *src, size_t len, char *out) |
| Encode raw bytes as a standard Base64 string. | |
| void | csilk_base64url_encode (const uint8_t *src, size_t len, char *out) |
| Encode raw bytes as a Base64URL (RFC 4648 §5) string. | |
| int | csilk_base64url_decode (const char *src, uint8_t *out) |
| Decode a Base64URL (RFC 4648 §5) string to raw bytes. | |
| void | csilk_ws_parse_frame (csilk_ctx_t *c, const uint8_t *buf, size_t nread) |
| Parse an incoming WebSocket frame from the raw TCP stream. | |
| void | _csilk_send_response (csilk_ctx_t *c) __attribute__((weak)) |
| Internal: Trigger the response send path. | |
| void | _csilk_send_data (csilk_ctx_t *c, const uint8_t *data, size_t len) |
| Internal: Send data through the appropriate I/O path. | |
| void | _csilk_hmac_sha256 (csilk_ctx_t *c, const uint8_t *key, size_t key_len, const uint8_t *data, size_t data_len, uint8_t out[32]) |
| Internal: Compute HMAC-SHA256 using the server's crypto driver (if set) or the built-in software implementation. | |
| void | _csilk_generate_uuid (csilk_ctx_t *c, char buf[37]) |
| Internal: Generate a random UUID v4 string using the crypto driver (if set) or the built-in /dev/urandom-based implementation. | |
| void * | _csilk_get_internal_client (csilk_ctx_t *c) |
| Get the internal client connection object. | |
| void | _csilk_set_internal_client (csilk_ctx_t *c, void *client) |
| Set the internal client connection object. | |
| int | _csilk_symmetric_encrypt (csilk_ctx_t *c, const uint8_t *key, size_t key_len, const uint8_t *plaintext, size_t plaintext_len, const uint8_t *iv, size_t iv_len, uint8_t *ciphertext, size_t *ciphertext_len, uint8_t *tag, size_t tag_len) |
| Internal: Symmetric encrypt using the context's cipher driver or the built-in OpenSSL AES-256-GCM implementation. | |
| int | _csilk_symmetric_decrypt (csilk_ctx_t *c, const uint8_t *key, size_t key_len, const uint8_t *ciphertext, size_t ciphertext_len, const uint8_t *iv, size_t iv_len, const uint8_t *tag, size_t tag_len, uint8_t *plaintext, size_t *plaintext_len) |
| Internal: Symmetric decrypt using the context's cipher driver or the built-in OpenSSL AES-256-GCM implementation. | |
| int | _csilk_generate_keypair (csilk_ctx_t *c, char *public_key, size_t *pub_len, char *private_key, size_t *priv_len) |
| Internal: Generate an RSA-2048 key pair using the context's cipher driver or the built-in OpenSSL implementation. | |
| int | _csilk_asymmetric_encrypt (csilk_ctx_t *c, const char *public_key, size_t pub_len, const uint8_t *plaintext, size_t plaintext_len, uint8_t *ciphertext, size_t *ciphertext_len) |
| Internal: Asymmetric encrypt using the context's cipher driver or the built-in OpenSSL RSA-OAEP implementation. | |
| int | _csilk_asymmetric_decrypt (csilk_ctx_t *c, const char *private_key, size_t priv_len, const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *plaintext, size_t *plaintext_len) |
| Internal: Asymmetric decrypt using the context's cipher driver or the built-in OpenSSL RSA-OAEP implementation. | |
| int | _csilk_sign (csilk_ctx_t *c, const char *private_key, size_t priv_len, const uint8_t *data, size_t data_len, uint8_t *signature, size_t *sig_len) |
| Internal: Sign data using the context's cipher driver or the built-in OpenSSL RSA-PSS implementation. | |
| int | _csilk_verify (csilk_ctx_t *c, const char *public_key, size_t pub_len, const uint8_t *data, size_t data_len, const uint8_t *signature, size_t sig_len) |
| Internal: Verify a signature using the context's cipher driver or the built-in OpenSSL RSA-PSS implementation. | |
| size_t | csilk_url_decode (char *str) |
| URL-decode a percent-encoded string in-place. | |
| void | csilk_generate_uuid (char *buf) |
| Generate a random UUID v4 string (standalone, no context needed). | |
| csilk_mq_t * | _csilk_mq_new (uv_loop_t *loop) |
| Internal: Create a new MQ instance bound to a libuv loop. | |
| void | _csilk_mq_free (csilk_mq_t *mq) |
| Internal: Destroy an MQ instance and release all resources. | |
Internal framework primitives — crypto, codec, MQ, and dispatch.
This header exposes functions and types used internally by the csilk framework. They are NOT part of the public API and may change without notice. External consumers should not rely on them.
| struct csilk_sha1_ctx |
SHA-1 hashing context.
Holds intermediate state and buffered data during a multi-step SHA-1 computation. Use csilk_sha1_init / _update / _final.
| struct csilk_sha256_ctx |
SHA-256 hashing context.
Holds intermediate state and buffered data during a multi-step SHA-256 computation. Use csilk_sha256_init / _update / _final.
| Data Fields | ||
|---|---|---|
| uint8_t | buffer[64] |
512-bit block buffer for data not yet processed. |
| uint64_t | count |
Total message length in bits. |
| uint32_t | state[8] |
256-bit intermediate hash state (8 × 32-bit words). |
| struct csilk_mq_msg_t |
Internal: A single message in the MQ linked-list queue. Messages are heap-allocated and linked via next.
| struct csilk_mq_topic_t |
Internal: A topic node in the MQ's linked list of topics. Holds the topic name and its associated middleware + subscriber chain.
| Data Fields | ||
|---|---|---|
| size_t | handler_capacity |
Allocated capacity of |
| size_t | handler_count |
Number of handlers currently registered. |
| csilk_mq_handler_t * | handlers |
Dynamically-grown array of handler function pointers (middleware + subscribers). |
| char * | name |
NUL-terminated topic name (e.g., "user.created"). |
| struct csilk_mq_topic_s * | next |
Pointer to the next topic in the linked list. |
| struct csilk_mq_s |
Internal: The Message Queue instance.
Opaque Message Queue (event bus) instance.
Manages the message queue, topic registry, global middleware, and optional WAL persistence. Publishes are thread-safe (guarded by queue_mutex) and are delivered asynchronously on the main event loop via a uv_async_t handle.
Not intended for direct manipulation by user code.
Provides an in-process pub/sub system built on libuv async handles. Thread-safe publishing allows worker threads to send messages to the main event loop. The full lifecycle is:
Supports middleware chains, persistence via WAL, and background offloading to libuv's thread pool.
Provides an in-process pub/sub system built on libuv async handles. Thread-safe publishing allows worker threads to send messages to the main event loop. Supports middleware chains, persistence via WAL, and background offloading.

| Data Fields | ||
|---|---|---|
| uv_async_t | async_handle |
libuv async handle for bridging worker-thread publishes into the main loop. |
| uint64_t | delivered_total |
Total messages delivered. |
| uint64_t | failed_total |
Total messages failed. |
| csilk_mq_handler_t * | global_middlewares |
Array of global middleware (intercepts every topic). |
| size_t | global_mw_capacity |
Allocated capacity of |
| size_t | global_mw_count |
Number of global middleware handlers registered. |
| size_t | monitor_capacity |
Monitor array capacity. |
| size_t | monitor_count |
Number of monitors. |
| uv_mutex_t | monitor_mutex |
Protects monitor array. |
| csilk_ctx_t ** | monitors |
WebSocket monitor connections. |
| uint64_t | published_total |
Total messages published. |
| uint32_t | queue_depth |
Current messages in memory. |
| csilk_mq_msg_t * | queue_head |
Head of the pending-message linked list. |
| uv_mutex_t | queue_mutex |
Mutex guarding the message linked list. |
| csilk_mq_msg_t * | queue_tail |
Tail of the pending-message linked list. |
| csilk_mq_topic_t * | topics |
Linked list of registered topics. |
| uv_file | wal_fd |
File descriptor for the Write-Ahead Log, or -1 if disabled. |
| uv_mutex_t | wal_mutex |
Mutex guarding WAL append operations. |
| char * | wal_path |
Path to the WAL file (heap-allocated copy, NULL if disabled). |
| struct csilk_mq_ctx_s |
Internal: Per-message MQ context passed to middleware and subscribers.
Opaque Message Queue context.
Contains the resolved handler chain for the current topic and tracks the current position in the chain.
Created per-message and passed to middleware and subscriber handlers. Provides access to the topic, payload, and chain-control functions. Valid only during the handler invocation — do not store the pointer.

| Data Fields | ||
|---|---|---|
| int | aborted |
Non-zero if csilk_mq_abort was called. |
| size_t | handler_count |
Total number of handlers in |
| int | handler_index |
Index of the next handler to invoke. |
| csilk_mq_handler_t * | handlers |
Combined handler array (global mw + topic mw + subscribers). |
| csilk_mq_t * | mq |
Owning MQ instance. |
| csilk_mq_msg_t * | msg |
The message being processed. |
| struct csilk_mq_work_ctx_t |
Internal: Context passed to libuv's thread-pool work callback.
Carries the topic, payload, and worker function pointer for background message offloading.
| Data Fields | ||
|---|---|---|
| csilk_mq_worker_t | handler |
User-provided worker function. |
| size_t | len |
Byte length of |
| void * | payload |
Payload data (heap-allocated copy). |
| uv_work_t | req |
libuv work request (must be first for casting). |
| char * | topic |
Topic string (heap-allocated copy). |
| int _csilk_asymmetric_decrypt | ( | csilk_ctx_t * | c, |
| const char * | private_key, | ||
| size_t | priv_len, | ||
| const uint8_t * | ciphertext, | ||
| size_t | ciphertext_len, | ||
| uint8_t * | plaintext, | ||
| size_t * | plaintext_len | ||
| ) |
Internal: Asymmetric decrypt using the context's cipher driver or the built-in OpenSSL RSA-OAEP implementation.
| c | Request context (for driver lookup, may be NULL). | |
| private_key | PEM-encoded RSA private key. | |
| priv_len | Private key length. | |
| ciphertext | Data to decrypt (typically 256 bytes for RSA-2048). | |
| ciphertext_len | Ciphertext length. | |
| [out] | plaintext | Output buffer. |
| [in,out] | plaintext_len | In: capacity, Out: actual length. |
| int _csilk_asymmetric_encrypt | ( | csilk_ctx_t * | c, |
| const char * | public_key, | ||
| size_t | pub_len, | ||
| const uint8_t * | plaintext, | ||
| size_t | plaintext_len, | ||
| uint8_t * | ciphertext, | ||
| size_t * | ciphertext_len | ||
| ) |
Internal: Asymmetric encrypt using the context's cipher driver or the built-in OpenSSL RSA-OAEP implementation.
| c | Request context (for driver lookup, may be NULL). | |
| public_key | PEM-encoded RSA public key. | |
| pub_len | Public key length. | |
| plaintext | Data to encrypt (max ~190 bytes for RSA-2048). | |
| plaintext_len | Plaintext length. | |
| [out] | ciphertext | 256-byte output buffer. |
| [in,out] | ciphertext_len | In: capacity, Out: actual length. |
| int _csilk_generate_keypair | ( | csilk_ctx_t * | c, |
| char * | public_key, | ||
| size_t * | pub_len, | ||
| char * | private_key, | ||
| size_t * | priv_len | ||
| ) |
Internal: Generate an RSA-2048 key pair using the context's cipher driver or the built-in OpenSSL implementation.
Keys are output as PEM-encoded strings.
| c | Request context (for driver lookup, may be NULL). | |
| [out] | public_key | PEM public key buffer. |
| [in,out] | pub_len | In: capacity, Out: actual PEM length (incl. NUL). |
| [out] | private_key | PEM private key buffer. |
| [in,out] | priv_len | In: capacity, Out: actual PEM length (incl. NUL). |
| void _csilk_generate_uuid | ( | csilk_ctx_t * | c, |
| char | buf[37] | ||
| ) |
Internal: Generate a random UUID v4 string using the crypto driver (if set) or the built-in /dev/urandom-based implementation.
| c | Request context (for driver lookup). | |
| [out] | buf | Output buffer of at least 37 bytes. Receives a NUL-terminated UUID string (e.g., "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"). |
Internal: Generate a random UUID v4 string using the crypto driver (if set) or the built-in /dev/urandom-based implementation.
This is the late-bound UUID generator. If the context has a crypto driver with a cryptographically secure generate_uuid method (e.g., reading from a hardware RNG or via OpenSSL), that is used. Otherwise falls back to the built-in csilk_generate_uuid() which reads /dev/urandom.
The delegation pattern ensures callers always get the best available randomness source without explicit driver management.
| c | Request context (may be NULL — falls back to built-in). |
| buf | [out] 37-byte buffer for the UUID string. |
| void * _csilk_get_internal_client | ( | csilk_ctx_t * | c | ) |
Get the internal client connection object.
Opaque pointer used by protocol implementations (WebSocket, SSE).
| c | Request context. |
Get the internal client connection object.
| c | The request context. |
| void _csilk_hmac_sha256 | ( | csilk_ctx_t * | c, |
| const uint8_t * | key, | ||
| size_t | key_len, | ||
| const uint8_t * | data, | ||
| size_t | data_len, | ||
| uint8_t | out[32] | ||
| ) |
Internal: Compute HMAC-SHA256 using the server's crypto driver (if set) or the built-in software implementation.
| c | Request context (for driver lookup). | |
| key | HMAC key. | |
| key_len | Key length. | |
| data | Input data. | |
| data_len | Input length. | |
| [out] | out | 32-byte HMAC output. |
Internal: Compute HMAC-SHA256 using the server's crypto driver (if set) or the built-in software implementation.
This is the "late-bound" version of csilk_hmac_sha256(). It checks whether the request context has a crypto driver installed (e.g., OpenSSL, mbedTLS, or a hardware security module). If so, the driver's accelerated HMAC is used. Otherwise, the built-in software implementation serves as the portable fallback.
This pattern allows the application to use pluggable crypto backends without changing caller code. The default built-in implementation is always available for environments without hardware crypto.
| c | Request context (may be NULL — falls back to built-in). |
| key | HMAC key. |
| key_len | Key length. |
| data | Input data. |
| data_len | Data length. |
| out | [out] 32-byte HMAC output buffer. |
| void _csilk_mq_free | ( | csilk_mq_t * | mq | ) |
Internal: Destroy an MQ instance and release all resources.
Drains the message queue, frees topics, handlers, and the WAL file.
| mq | The MQ instance to free. |
Internal: Destroy an MQ instance and release all resources.
Triggers uv_close() on the async handle if it is not already closing. The actual cleanup (mutexes, WAL, queue, topics) happens in on_mq_close() when the close callback fires.
| mq | The MQ instance to free (may be NULL). |
| csilk_mq_t * _csilk_mq_new | ( | uv_loop_t * | loop | ) |
Internal: Create a new MQ instance bound to a libuv loop.
| loop | The libuv event loop. |
| void _csilk_send_data | ( | csilk_ctx_t * | c, |
| const uint8_t * | data, | ||
| size_t | len | ||
| ) |
Internal: Send data through the appropriate I/O path.
Routes data through the TLS wrapper if TLS is enabled, or writes directly to the TCP socket otherwise.
| c | Request context. |
| data | Bytes to send. |
| len | Number of bytes to send. |
| void _csilk_send_response | ( | csilk_ctx_t * | c | ) |
Internal: Trigger the response send path.
Weak symbol so that tests or custom builds can override it. Called when an async handler finishes and the response should be flushed.
| c | Request context. |
Internal: Trigger the response send path.
This is the central response-serialization function. It constructs the HTTP response bytes in memory and sends them via _csilk_send_data(). The response format is:
HTTP/1.1 <status> <reason>\r
[Transfer-Encoding: chunked\r
] Content-Length: <len>\r
Connection: keep-alive|close\r
<custom headers...>\r
\r
<body>
Response mode selection:
After the response is sent:
| c | Request context (must have _internal_client set). |
| void _csilk_set_internal_client | ( | csilk_ctx_t * | c, |
| void * | client | ||
| ) |
Set the internal client connection object.
| c | Request context. |
| client | Pointer to csilk_client_t (or mock marker). |
Set the internal client connection object.
| c | The request context. |
| client | Opaque pointer to csilk_client_t. |
| int _csilk_sign | ( | csilk_ctx_t * | c, |
| const char * | private_key, | ||
| size_t | priv_len, | ||
| const uint8_t * | data, | ||
| size_t | data_len, | ||
| uint8_t * | signature, | ||
| size_t * | sig_len | ||
| ) |
Internal: Sign data using the context's cipher driver or the built-in OpenSSL RSA-PSS implementation.
| c | Request context (for driver lookup, may be NULL). | |
| private_key | PEM-encoded RSA private key. | |
| priv_len | Private key length. | |
| data | Data to sign. | |
| data_len | Data length. | |
| [out] | signature | 256-byte signature buffer. |
| [in,out] | sig_len | In: capacity, Out: actual signature length. |
| int _csilk_symmetric_decrypt | ( | csilk_ctx_t * | c, |
| const uint8_t * | key, | ||
| size_t | key_len, | ||
| const uint8_t * | ciphertext, | ||
| size_t | ciphertext_len, | ||
| const uint8_t * | iv, | ||
| size_t | iv_len, | ||
| const uint8_t * | tag, | ||
| size_t | tag_len, | ||
| uint8_t * | plaintext, | ||
| size_t * | plaintext_len | ||
| ) |
Internal: Symmetric decrypt using the context's cipher driver or the built-in OpenSSL AES-256-GCM implementation.
| c | Request context (for driver lookup, may be NULL). | |
| key | Decryption key (must be 32 bytes for AES-256). | |
| key_len | Key length. | |
| ciphertext | Data to decrypt. | |
| ciphertext_len | Ciphertext length. | |
| iv | 12-byte initialisation vector (nonce). | |
| iv_len | IV length (must be 12 for GCM). | |
| tag | 16-byte authentication tag. | |
| tag_len | Tag length (must be 16). | |
| [out] | plaintext | Output buffer (must be at least ciphertext_len bytes). |
| [in,out] | plaintext_len | In: capacity, Out: actual plaintext length. |
| int _csilk_symmetric_encrypt | ( | csilk_ctx_t * | c, |
| const uint8_t * | key, | ||
| size_t | key_len, | ||
| const uint8_t * | plaintext, | ||
| size_t | plaintext_len, | ||
| const uint8_t * | iv, | ||
| size_t | iv_len, | ||
| uint8_t * | ciphertext, | ||
| size_t * | ciphertext_len, | ||
| uint8_t * | tag, | ||
| size_t | tag_len | ||
| ) |
Internal: Symmetric encrypt using the context's cipher driver or the built-in OpenSSL AES-256-GCM implementation.
| c | Request context (for driver lookup, may be NULL). | |
| key | Encryption key (must be 32 bytes for AES-256). | |
| key_len | Key length. | |
| plaintext | Data to encrypt. | |
| plaintext_len | Plaintext length. | |
| iv | 12-byte initialisation vector (nonce). | |
| iv_len | IV length (must be 12 for GCM). | |
| [out] | ciphertext | Output buffer (must be at least plaintext_len bytes). |
| [in,out] | ciphertext_len | In: capacity, Out: actual ciphertext length. |
| [out] | tag | 16-byte authentication tag buffer. |
| tag_len | Tag buffer size (must be 16). |
| int _csilk_verify | ( | csilk_ctx_t * | c, |
| const char * | public_key, | ||
| size_t | pub_len, | ||
| const uint8_t * | data, | ||
| size_t | data_len, | ||
| const uint8_t * | signature, | ||
| size_t | sig_len | ||
| ) |
Internal: Verify a signature using the context's cipher driver or the built-in OpenSSL RSA-PSS implementation.
| c | Request context (for driver lookup, may be NULL). |
| public_key | PEM-encoded RSA public key. |
| pub_len | Public key length. |
| data | Original signed data. |
| data_len | Data length. |
| signature | Signature to verify. |
| sig_len | Signature length. |
| void csilk_base64_encode | ( | const uint8_t * | src, |
| size_t | len, | ||
| char * | out | ||
| ) |
Encode raw bytes as a standard Base64 string.
Produces a NUL-terminated Base64 string per RFC 4648 §4.
| src | Source byte buffer. | |
| len | Byte length of src. | |
| [out] | out | Output buffer. Must be at least ((len + 2) / 3) * 4 + 1 bytes to hold the encoded output plus NUL terminator. |
Encode raw bytes as a standard Base64 string.
Processes input in 3-byte groups, producing 4 Base64 characters each. Padding with '=' is added if the input length is not a multiple of 3. The output string is null-terminated.
| src | Input byte buffer. |
| len | Input length in bytes. |
| out | [out] Output buffer (must be large enough: 4 * ceil(len/3) + 1). |
out has sufficient capacity. The worst-case output length is ((len + 2) / 3) * 4 + 1. | int csilk_base64url_decode | ( | const char * | src, |
| uint8_t * | out | ||
| ) |
Decode a Base64URL (RFC 4648 §5) string to raw bytes.
Handles both padded and unpadded input.
| src | NUL-terminated Base64URL string. | |
| [out] | out | Output buffer for decoded bytes (must be at least strlen(src) * 3 / 4 bytes). |
Decode a Base64URL (RFC 4648 §5) string to raw bytes.
The decoding process is the inverse of Base64URL encoding:
The reverse lookup maps each Base64 character (A-Z, a-z, 0-9, +, /) back to its 6-bit value. Characters outside this set (including whitespace) cause an immediate error return (-1). The '=' padding character terminates decoding early.
| src | Base64URL-encoded input string (null-terminated). |
| out | [out] Output buffer for decoded bytes. |
out is large enough (at least strlen(src) * 3 / 4 + 1 bytes). | void csilk_base64url_encode | ( | const uint8_t * | src, |
| size_t | len, | ||
| char * | out | ||
| ) |
Encode raw bytes as a Base64URL (RFC 4648 §5) string.
Like Base64 but uses '-' and '_' instead of '+' and '/', and omits padding '=' characters.
| src | Source byte buffer. | |
| len | Byte length of src. | |
| [out] | out | Output buffer (must be large enough for the encoded string). |
Encode raw bytes as a Base64URL (RFC 4648 §5) string.
Base64URL is the same as standard Base64 but replaces: '+' → '-' (URL-safe, as '+' is treated as space in URL query strings) '/' → '_' (URL-safe, as '/' has path separator meaning) '=' → '' (omitted — padding is unnecessary because length is inferred)
The output is produced by first encoding with standard Base64, then character-substituting and stripping padding.
| src | Input byte buffer. |
| len | Input length in bytes. |
| out | [out] Output buffer (must be large enough for the padded Base64 result + 1). |
| void csilk_generate_uuid | ( | char * | buf | ) |
Generate a random UUID v4 string (standalone, no context needed).
Uses /dev/urandom or an equivalent OS entropy source.
| [out] | buf | Output buffer of at least 37 bytes. Populated with a NUL-terminated UUID string. |
Generate a random UUID v4 string (standalone, no context needed).
UUID v4 (RFC 4122 §4.4) uses random or pseudo-random bytes for all 128 bits, with specific bits reserved for the version and variant:
Field Bits Purpose time_low 32 Random time_mid 16 Random time_hi_ver 16 Version (4 bits) + random (12 bits) clock_seq_hi 8 Variant (2 bits) + random (6 bits) clock_seq_low 8 Random node 48 Random
Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx where '4' indicates RFC 4122 version 4 (random UUID). where 'y' has the top 2 bits set to '10' (RFC 4122 variant).
Reads 16 random bytes from /dev/urandom. If /dev/urandom is unavailable, falls back to rand() (which is NOT cryptographically secure). Sets the UUID version nibble (4) and variant bits (10xx) per RFC 4122.
| buf | [out] 37-byte buffer to receive the UUID string (36 hex chars + 4 hyphens + null terminator). |
| void csilk_hmac_sha256 | ( | const uint8_t * | key, |
| size_t | key_len, | ||
| const uint8_t * | data, | ||
| size_t | data_len, | ||
| uint8_t | out[32] | ||
| ) |
Compute HMAC-SHA256 (keyed-hash message authentication code).
Implements RFC 2104 using SHA-256 as the underlying hash function.
| key | Secret key bytes. | |
| key_len | Byte length of key. | |
| data | Input data to authenticate. | |
| data_len | Byte length of data. | |
| [out] | out | 32-byte buffer receiving the HMAC output. |
Compute HMAC-SHA256 (keyed-hash message authentication code).
HMAC (Hash-based Message Authentication Code) provides both data integrity and authenticity via a shared secret. The construction is:
HMAC(K, m) = SHA256((K' XOR opad) || SHA256((K' XOR ipad) || m))
where:
The double-hashing protects against length-extension attacks on the underlying hash function. The ipad/opad XOR ensures that the inner and outer hashes use distinct keys derived from the same secret.
| key | HMAC secret key. |
| key_len | Key length in bytes. |
| data | Input message data. |
| data_len | Message length in bytes. |
| out | [out] 32-byte output buffer for the HMAC digest. |
| void csilk_sha1_final | ( | csilk_sha1_ctx * | context, |
| uint8_t | digest[20] | ||
| ) |
Finalise the SHA-1 hash and write the 20-byte digest.
After this call the context should not be used without re-initialising.
| context | SHA-1 context. | |
| [out] | digest | 20-byte array receiving the SHA-1 hash. |
Finalise the SHA-1 hash and write the 20-byte digest.
Pads the message according to RFC 3174 (SHA-1 specification), appends the 64-bit message length, and outputs the final hash digest. After this call, the context should not be used without re-initialization.
| context | SHA-1 context with accumulated data. |
| digest | [out] 20-byte buffer to receive the hash digest. |
| void csilk_sha1_init | ( | csilk_sha1_ctx * | context | ) |
Initialise a SHA-1 hashing context.
Must be called before the first csilk_sha1_update.
| context | Pointer to an uninitialised csilk_sha1_ctx. |
Initialise a SHA-1 hashing context.
Sets the five state words to the SHA-1 initial constants and resets the bit count to zero. Must be called before the first csilk_sha1_update().
| context | SHA-1 context to initialize (must not be NULL). |
| void csilk_sha1_update | ( | csilk_sha1_ctx * | context, |
| const uint8_t * | data, | ||
| size_t | len | ||
| ) |
Feed data into the SHA-1 hashing context.
Can be called multiple times with arbitrary-length inputs.
| context | SHA-1 context (initialised). |
| data | Input bytes. |
| len | Number of bytes in data. |
Feed data into the SHA-1 hashing context.
Processes the input data in 64-byte blocks, updating the context's state. Partial blocks are buffered until the next call or csilk_sha1_final().
| context | SHA-1 context (initialized via csilk_sha1_init()). |
| data | Input data buffer. |
| len | Length of input data in bytes. |
| void csilk_sha256_final | ( | csilk_sha256_ctx * | context, |
| uint8_t | digest[32] | ||
| ) |
Finalise the SHA-256 hash and write the 32-byte digest.
| context | SHA-256 context. | |
| [out] | digest | 32-byte array receiving the SHA-256 hash. |
Finalise the SHA-256 hash and write the 32-byte digest.
Pads the message according to FIPS 180-4, appends the 64-bit message length, and outputs the final 256-bit (32-byte) hash digest.
| context | SHA-256 context with accumulated data. |
| digest | [out] 32-byte buffer to receive the hash digest. |
| void csilk_sha256_init | ( | csilk_sha256_ctx * | context | ) |
Initialise a SHA-256 hashing context.
| context | Pointer to an uninitialised csilk_sha256_ctx. |
Initialise a SHA-256 hashing context.
Sets the eight state words to the SHA-256 initial constants and resets the bit count to zero.
| context | SHA-256 context to initialize (must not be NULL). |
| void csilk_sha256_update | ( | csilk_sha256_ctx * | context, |
| const uint8_t * | data, | ||
| size_t | len | ||
| ) |
Feed data into the SHA-256 hashing context.
| context | SHA-256 context (initialised). |
| data | Input bytes. |
| len | Number of bytes in data. |
Feed data into the SHA-256 hashing context.
Processes the input data in 64-byte blocks, updating the context's state. Partial blocks are buffered. Tracks the total bit count for final padding.
| context | SHA-256 context (initialized via csilk_sha256_init()). |
| data | Input data buffer. |
| len | Length of input data in bytes. |
| size_t csilk_url_decode | ( | char * | str | ) |
URL-decode a percent-encoded string in-place.
Converts XX sequences to their byte values and '+' to space. The decoded string is always shorter than or equal to the input.
| str | NUL-terminated percent-encoded string (modified in-place). |
Replaces XX sequences with the corresponding byte value and '+' with space. The decoding is done in-place so the output is never longer than the input.
| str | Null-terminated string to decode (modified in-place). |
str contains invalid % sequences (e.g., "%ZZ"), they are left as-is. | void csilk_ws_parse_frame | ( | csilk_ctx_t * | c, |
| const uint8_t * | buf, | ||
| size_t | nread | ||
| ) |
Parse an incoming WebSocket frame from the raw TCP stream.
Processes one or more frames from the receive buffer, dispatches data frames to the registered on_message callback, and handles control frames (ping/pong/close) internally.
| c | Request context (WebSocket mode must be active). |
| buf | Raw bytes received from the socket. |
| nread | Number of bytes in buf. |
Parse an incoming WebSocket frame from the raw TCP stream.
Parses the frame header (FIN, opcode, mask, payload length), extracts the payload, applies client-to-server masking if present, and dispatches based on opcode:
| c | The request context. |
| buf | Raw frame data received from the socket. |
| nread | Number of bytes available in buf. |