mirror of
https://github.com/logos-messaging/libchat.git
synced 2026-03-27 22:53:07 +00:00
89 lines
2.5 KiB
C
89 lines
2.5 KiB
C
/*
|
|
* 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;
|
|
}
|