/* * 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 #include #include #include #include /* ------------------------------------------------------------------ * 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; }