libchat/crates/c-test/c/delivery.c

89 lines
2.5 KiB
C
Raw Normal View History

2026-03-26 22:38:38 +01:00
/*
* C delivery implementation for the c-test platform.
*
* Provides a simple fixed-size queue and a delivery callback. The queue acts
* as the outbox for a client: every outbound envelope is pushed here; the test
* (orchestrated from Rust) pops envelopes and routes them to the receiving
* client via client_push_inbound.
*
* This file has NO dependencies on the client-ffi or libchat Rust crates.
*/
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
/* ------------------------------------------------------------------
* Queue implementation
* ------------------------------------------------------------------ */
#define MAX_ENVELOPES 64
#define MAX_ENVELOPE_SZ 32768
typedef struct {
uint8_t data[MAX_ENVELOPE_SZ];
size_t len;
} Envelope;
typedef struct Queue {
Envelope items[MAX_ENVELOPES];
int head;
int tail;
int count;
} Queue;
Queue *c_queue_new(void)
{
Queue *q = (Queue *)calloc(1, sizeof(Queue));
assert(q && "out of memory");
return q;
}
void c_queue_free(Queue *q)
{
free(q);
}
/**
* Pop the oldest envelope from the queue.
*
* @param q Queue to pop from.
* @param data_out Set to a pointer into the queue's internal buffer.
* Valid only until the next push or free.
* @param len_out Set to the envelope length in bytes.
* @return 1 if an envelope was available, 0 if the queue was empty.
*/
int c_queue_pop(Queue *q, const uint8_t **data_out, size_t *len_out)
{
if (q->count == 0) return 0;
*data_out = q->items[q->head].data;
*len_out = q->items[q->head].len;
q->head = (q->head + 1) % MAX_ENVELOPES;
q->count--;
return 1;
}
/* ------------------------------------------------------------------
* Delivery callback
*
* `userdata` must be a Queue* for the sending client's outbox.
* ------------------------------------------------------------------ */
int32_t c_deliver_cb(
const uint8_t *addr_ptr, size_t addr_len,
const uint8_t *data_ptr, size_t data_len,
void *userdata)
{
(void)addr_ptr; (void)addr_len; /* routing is done externally */
Queue *q = (Queue *)userdata;
assert(q->count < MAX_ENVELOPES && "delivery queue overflow");
assert(data_len <= MAX_ENVELOPE_SZ && "envelope too large for queue");
memcpy(q->items[q->tail].data, data_ptr, data_len);
q->items[q->tail].len = data_len;
q->tail = (q->tail + 1) % MAX_ENVELOPES;
q->count++;
return 0;
}