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.c File Reference

Go to the source code of this file.

Data Structures

struct  packet_node
struct  packet_queue
 For packet node, this is the live record that ties packet, next together. The owning code creates it, updates it while work is active, and releases its handles and pointed-to storage before freeing the record. More...

Typedefs

typedef struct packet_node packet_node_t

Functions

packet_queue_t * packet_queue_create_config (const packet_queue_config_t *config)
packet_queue_t * packet_queue_create (size_t max_packets)
void packet_queue_free_packet (queued_packet_t *packet)
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)
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)
queued_packet_t * packet_queue_try_dequeue (packet_queue_t *queue)
queued_packet_t * packet_queue_dequeue (packet_queue_t *queue)
void packet_queue_clear (packet_queue_t *queue)
void packet_queue_stop (packet_queue_t *queue)
void packet_queue_destroy (packet_queue_t *queue)
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_node_t

typedef struct packet_node packet_node_t

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
@ PACKET_QUEUE_REJECT
Definition queue.h:13

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
@ PACKET_QUEUE_DROP_OLDEST
Definition queue.h:13
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().