ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
queue.h File Reference

Go to the source code of this file.

Data Structures

struct  queued_packet_t
struct  packet_queue_config_t

Typedefs

typedef struct packet_queue packet_queue_t

Enumerations

enum  packet_queue_overflow_t { PACKET_QUEUE_REJECT , PACKET_QUEUE_DROP_OLDEST }

Functions

packet_queue_t * packet_queue_create (size_t max_packets)
packet_queue_t * packet_queue_create_config (const packet_queue_config_t *config)
void packet_queue_destroy (packet_queue_t *queue)
void packet_queue_stop (packet_queue_t *queue)
void packet_queue_clear (packet_queue_t *queue)
asciichat_error_t packet_queue_push_copy (packet_queue_t *queue, packet_type_t type, const void *data, size_t length, uint32_t client_id)
asciichat_error_t packet_queue_push_take (packet_queue_t *queue, packet_type_t type, void **data, size_t length, uint32_t client_id)
asciichat_error_t packet_queue_push_shared (packet_queue_t *queue, packet_type_t type, const void *data, size_t length, uint32_t client_id)
queued_packet_t * packet_queue_dequeue (packet_queue_t *queue)
queued_packet_t * packet_queue_try_dequeue (packet_queue_t *queue)
void packet_queue_free_packet (queued_packet_t *packet)
size_t packet_queue_size (packet_queue_t *queue)
bool packet_queue_is_empty (packet_queue_t *queue)
bool packet_queue_is_full (packet_queue_t *queue)
void packet_queue_get_stats (packet_queue_t *queue, uint64_t *enqueued, uint64_t *dequeued, uint64_t *dropped)
bool packet_queue_validate_packet (const queued_packet_t *packet)

Typedef Documentation

◆ packet_queue_t

typedef struct packet_queue packet_queue_t

Definition at line 12 of file queue.h.

Enumeration Type Documentation

◆ packet_queue_overflow_t

Enumerator
PACKET_QUEUE_REJECT 
PACKET_QUEUE_DROP_OLDEST 

Definition at line 13 of file queue.h.

packet_queue_overflow_t
Definition queue.h:13
@ PACKET_QUEUE_REJECT
Definition queue.h:13
@ PACKET_QUEUE_DROP_OLDEST
Definition queue.h:13

Function Documentation

◆ packet_queue_clear()

void packet_queue_clear ( packet_queue_t * queue)

Definition at line 195 of file queue.c.

195 {
196 if (!queue)
197 return;
198 mutex_lock(&queue->mutex);
199 packet_node_t *node;
200 while ((node = pop_locked(queue)))
202 mutex_unlock(&queue->mutex);
203}
void packet_queue_free_packet(queued_packet_t *packet)
Definition queue.c:78
struct packet_node packet_node_t
queued_packet_t packet
Definition queue.c:12
mutex_t mutex
Definition queue.c:24

References packet_queue::mutex, packet_node::packet, and packet_queue_free_packet().

Referenced by packet_queue_destroy().

◆ packet_queue_create()

packet_queue_t * packet_queue_create ( size_t max_packets)

Defaults: 16 MiB byte limit and rejection on overflow. Zero packet count disables only the item limit, never the byte limit or memory budget.

Definition at line 59 of file queue.c.

59 {
60 packet_queue_config_t config = {max_packets, 16 * 1024 * 1024, PACKET_QUEUE_REJECT};
61 return packet_queue_create_config(&config);
62}
packet_queue_t * packet_queue_create_config(const packet_queue_config_t *config)
Definition queue.c:37

References packet_queue_create_config(), and PACKET_QUEUE_REJECT.

◆ packet_queue_create_config()

packet_queue_t * packet_queue_create_config ( const packet_queue_config_t * config)

Definition at line 37 of file queue.c.

37 {
38 if (!config || !config->max_bytes ||
40 SET_ERRNO(ERROR_INVALID_PARAM, "Queue needs a byte limit and a valid overflow policy");
41 return NULL;
42 }
44 queue->config = *config;
45 if (mutex_init(&queue->mutex, "packet_queue") != 0) {
46 return NULL;
47 }
48 defer_named(queue_mutex, mutex_destroy(&queue->mutex));
49 buffer_domain_config_t memory = {64 * 1024 * 1024, 8 * 1024 * 1024, 5000000000ULL, false};
50 if (buffer_domain_create(&memory, &queue->domain) != ASCIICHAT_OK) {
51 return NULL;
52 }
53 defer_cancel(queue_mutex);
54 packet_queue_t *result = queue;
55 queue = NULL;
56 return result;
57}
#define SET_ERRNO(code,...)
asciichat_error_t buffer_domain_create(const buffer_domain_config_t *config, buffer_domain_t **out)
Definition buffer.c:125
#define SAFE_CALLOC_DEFER_FREE(name, count, size, cast)
Definition common.h:389
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
struct packet_queue packet_queue_t
Definition queue.h:12
packet_queue_overflow_t overflow
Definition queue.h:18

References ASCIICHAT_OK, buffer_domain_create(), ERROR_INVALID_PARAM, packet_queue_config_t::max_bytes, packet_queue_config_t::overflow, PACKET_QUEUE_DROP_OLDEST, PACKET_QUEUE_REJECT, SAFE_CALLOC_DEFER_FREE, and SET_ERRNO.

Referenced by packet_queue_create().

◆ packet_queue_dequeue()

queued_packet_t * packet_queue_dequeue ( packet_queue_t * queue)

Definition at line 191 of file queue.c.

191 {
192 return packet_queue_try_dequeue(queue);
193}
queued_packet_t * packet_queue_try_dequeue(packet_queue_t *queue)
Definition queue.c:176

References packet_queue_try_dequeue().

◆ packet_queue_destroy()

void packet_queue_destroy ( packet_queue_t * queue)

Join queue users before destruction. Dequeued packets may outlive the queue.

Definition at line 213 of file queue.c.

213 {
214 if (!queue)
215 return;
216 packet_queue_stop(queue);
217 packet_queue_clear(queue);
219 mutex_destroy(&queue->mutex);
220 SAFE_FREE(queue);
221}
void buffer_domain_close(buffer_domain_t **slot)
Definition buffer.c:156
#define SAFE_FREE(ptr)
Definition common.h:377
void packet_queue_clear(packet_queue_t *queue)
Definition queue.c:195
void packet_queue_stop(packet_queue_t *queue)
Definition queue.c:205
buffer_domain_t * domain
Definition queue.c:27

References buffer_domain_close(), packet_queue::domain, packet_queue::mutex, packet_queue_clear(), packet_queue_stop(), and SAFE_FREE.

◆ packet_queue_free_packet()

void packet_queue_free_packet ( queued_packet_t * packet)

Definition at line 78 of file queue.c.

78 {
79 if (!packet)
80 return;
81 buffer_release(packet->data);
82 /* packet is the first member of the owning node allocation. */
83 buffer_release(packet);
84}
#define buffer_release(data)
Definition buffer.h:91
const void * data
Definition queue.h:8

References buffer_release, and queued_packet_t::data.

Referenced by packet_queue_clear(), and packet_queue_try_dequeue().

◆ packet_queue_get_stats()

void packet_queue_get_stats ( packet_queue_t * queue,
uint64_t * enqueued,
uint64_t * dequeued,
uint64_t * dropped )

Definition at line 246 of file queue.c.

246 {
247 if (!queue)
248 return;
249 mutex_lock(&queue->mutex);
250 if (enqueued)
251 *enqueued = queue->enqueued;
252 if (dequeued)
253 *dequeued = queue->dequeued;
254 if (dropped)
255 *dropped = queue->dropped;
256 mutex_unlock(&queue->mutex);
257}
uint64_t enqueued
Definition queue.c:31
uint64_t dequeued
Definition queue.c:32
uint64_t dropped
Definition queue.c:33

References packet_queue::dequeued, packet_queue::dropped, packet_queue::enqueued, and packet_queue::mutex.

◆ packet_queue_is_empty()

bool packet_queue_is_empty ( packet_queue_t * queue)

Definition at line 232 of file queue.c.

232 {
233 return packet_queue_size(queue) == 0;
234}
size_t packet_queue_size(packet_queue_t *queue)
Definition queue.c:223

References packet_queue_size().

◆ packet_queue_is_full()

bool packet_queue_is_full ( packet_queue_t * queue)

Definition at line 236 of file queue.c.

236 {
237 if (!queue)
238 return false;
239 mutex_lock(&queue->mutex);
240 bool full = (queue->config.max_packets && queue->count >= queue->config.max_packets) ||
241 queue->bytes >= queue->config.max_bytes;
242 mutex_unlock(&queue->mutex);
243 return full;
244}
size_t bytes
Definition queue.c:30
size_t count
Definition queue.c:29
packet_queue_config_t config
Definition queue.c:28

References packet_queue::bytes, packet_queue::config, packet_queue::count, packet_queue_config_t::max_bytes, packet_queue_config_t::max_packets, and packet_queue::mutex.

◆ packet_queue_push_copy()

asciichat_error_t packet_queue_push_copy ( packet_queue_t * queue,
packet_type_t type,
const void * data,
size_t length,
uint32_t client_id )

Copy a borrowed view into queue-owned storage.

Definition at line 160 of file queue.c.

161 {
162 if (!queue || (length && !data) || length > queue->config.max_bytes)
163 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid packet copy");
164 void *copy = NULL;
165 if (length) {
166 copy = buffer_alloc(queue->domain, length);
167 if (!copy)
168 return SET_ERRNO(ERROR_MEMORY, "Cannot copy packet within memory budget");
169 memcpy(copy, data, length);
170 }
171 asciichat_error_t result = packet_queue_push_take(queue, type, &copy, length, client_id);
172 buffer_release(copy);
173 return result;
174}
void * buffer_alloc(buffer_domain_t *domain, size_t size)
Definition buffer.c:274
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ERROR_MEMORY
Definition error_codes.h:51
asciichat_error_t packet_queue_push_take(packet_queue_t *queue, packet_type_t type, void **data, size_t length, uint32_t client_id)
Definition queue.c:137

References buffer_alloc(), buffer_release, packet_queue::config, packet_queue::domain, ERROR_INVALID_PARAM, ERROR_MEMORY, packet_queue_config_t::max_bytes, packet_queue_push_take(), and SET_ERRNO.

◆ packet_queue_push_shared()

asciichat_error_t packet_queue_push_shared ( packet_queue_t * queue,
packet_type_t type,
const void * data,
size_t length,
uint32_t client_id )

Queue a shared immutable buffer, retaining an independent reference.

Definition at line 147 of file queue.c.

148 {
149 if (length > buffer_capacity(data))
150 return SET_ERRNO(ERROR_INVALID_PARAM, "Shared packet exceeds buffer capacity");
151 const void *shared = buffer_share(data);
152 if (data && !shared)
153 return SET_ERRNO(ERROR_INVALID_STATE, "Cannot share packet buffer");
154 asciichat_error_t result = push(queue, type, shared, length, client_id);
155 if (result != ASCIICHAT_OK)
156 buffer_release(shared);
157 return result;
158}
size_t buffer_capacity(const void *data)
Definition buffer.c:280
const void * buffer_share(const void *data)
Definition buffer.c:304
@ ERROR_INVALID_STATE

References ASCIICHAT_OK, buffer_capacity(), buffer_release, buffer_share(), ERROR_INVALID_PARAM, ERROR_INVALID_STATE, and SET_ERRNO.

◆ packet_queue_push_take()

asciichat_error_t packet_queue_push_take ( packet_queue_t * queue,
packet_type_t type,
void ** data,
size_t length,
uint32_t client_id )

On success, transfers the owning buffer pointer and clears *data. On any error, the caller retains ownership and *data is unchanged.

Definition at line 137 of file queue.c.

138 {
139 if (!data || (length && !*data) || length > buffer_capacity(*data))
140 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid owned packet buffer");
141 asciichat_error_t result = push(queue, type, *data, length, client_id);
142 if (result == ASCIICHAT_OK)
143 *data = NULL;
144 return result;
145}

References ASCIICHAT_OK, buffer_capacity(), ERROR_INVALID_PARAM, and SET_ERRNO.

Referenced by packet_queue_push_copy().

◆ packet_queue_size()

size_t packet_queue_size ( packet_queue_t * queue)

Definition at line 223 of file queue.c.

223 {
224 if (!queue)
225 return 0;
226 mutex_lock(&queue->mutex);
227 size_t count = queue->count;
228 mutex_unlock(&queue->mutex);
229 return count;
230}

References packet_queue::count, and packet_queue::mutex.

Referenced by packet_queue_is_empty().

◆ packet_queue_stop()

void packet_queue_stop ( packet_queue_t * queue)

Definition at line 205 of file queue.c.

205 {
206 if (!queue)
207 return;
208 mutex_lock(&queue->mutex);
209 queue->stopped = true;
210 mutex_unlock(&queue->mutex);
211}
bool stopped
Definition queue.c:34

References packet_queue::mutex, and packet_queue::stopped.

Referenced by packet_queue_destroy().

◆ packet_queue_try_dequeue()

queued_packet_t * packet_queue_try_dequeue ( packet_queue_t * queue)

Definition at line 176 of file queue.c.

176 {
177 if (!queue)
178 return NULL;
179 mutex_lock(&queue->mutex);
180 packet_node_t *node = queue->stopped ? NULL : pop_locked(queue);
181 if (node)
182 queue->dequeued++;
183 mutex_unlock(&queue->mutex);
184 if (node && !packet_queue_validate_packet(&node->packet)) {
186 return NULL;
187 }
188 return node ? &node->packet : NULL;
189}
bool packet_queue_validate_packet(const queued_packet_t *packet)
Definition queue.c:259

References packet_queue::dequeued, packet_queue::mutex, packet_node::packet, packet_queue_free_packet(), packet_queue_validate_packet(), and packet_queue::stopped.

Referenced by packet_queue_dequeue().

◆ packet_queue_validate_packet()

bool packet_queue_validate_packet ( const queued_packet_t * packet)

Definition at line 259 of file queue.c.

259 {
260 return packet && NET_TO_HOST_U64(packet->header.magic) == PACKET_MAGIC && NET_TO_HOST_U16(packet->header.type) > 0 &&
261 NET_TO_HOST_U16(packet->header.type) <= 10000 && NET_TO_HOST_U32(packet->header.length) == packet->data_len &&
262 (!packet->data_len ||
263 (packet->data && NET_TO_HOST_U32(packet->header.crc32) == asciichat_crc32(packet->data, packet->data_len)));
264}
#define NET_TO_HOST_U64(val)
Definition endian.h:228
#define NET_TO_HOST_U16(val)
Definition endian.h:111
#define NET_TO_HOST_U32(val)
Definition endian.h:81
#define PACKET_MAGIC
Packet magic number (alias for MAGIC_PACKET_VALID).
Definition packet.h:270
#define asciichat_crc32(data, len)
Main CRC32 dispatcher macro - use this in application code.
Definition crc32.h:147
uint32_t length
Payload data length in bytes (0 for header-only packets).
Definition packet.h:634
uint64_t magic
Magic number (PACKET_MAGIC = 0xA5C11C4A1 "ASCIICHAT" in hex) for packet validation.
Definition packet.h:630
uint16_t type
Packet type (packet_type_t enumeration).
Definition packet.h:632
uint32_t crc32
CRC32 checksum of payload data (0 if length == 0).
Definition packet.h:636
size_t data_len
Definition queue.h:9
packet_header_t header
Definition queue.h:7

References asciichat_crc32, packet_header_t::crc32, queued_packet_t::data, queued_packet_t::data_len, queued_packet_t::header, packet_header_t::length, packet_header_t::magic, NET_TO_HOST_U16, NET_TO_HOST_U32, NET_TO_HOST_U64, PACKET_MAGIC, and packet_header_t::type.

Referenced by packet_queue_try_dequeue().