blob: 75004f1aa7df8a700bd1970b058a892875812c64 [file] [log] [blame]
James Kuszmaul28cc8252021-01-17 11:32:21 -08001#include <rawrtcc/code.h>
2#include <rawrtcc/message_buffer.h>
3#include <re.h>
4
5/*
6 * Message buffer.
7 */
8struct buffered_message {
9 struct le le;
10 struct mbuf* buffer; // referenced
11 void* context; // referenced, nullable
12};
13
14/*
15 * Destructor for an existing buffered message.
16 */
17static void rawrtc_message_buffer_destroy(void* arg) {
18 struct buffered_message* const buffered_message = arg;
19
20 // Un-reference
21 mem_deref(buffered_message->context);
22 mem_deref(buffered_message->buffer);
23}
24
25/*
26 * Create a message buffer and add it to a list.
27 *
28 * TODO: Add timestamp to be able to ignore old messages
29 */
30enum rawrtc_code rawrtc_message_buffer_append(
31 struct list* const message_buffer,
32 struct mbuf* const buffer, // referenced
33 void* const context // referenced, nullable
34) {
35 struct buffered_message* buffered_message;
36
37 // Check arguments
38 if (!message_buffer || !buffer) {
39 return RAWRTC_CODE_INVALID_ARGUMENT;
40 }
41
42 // Create buffered message
43 buffered_message = mem_zalloc(sizeof(*buffered_message), rawrtc_message_buffer_destroy);
44 if (!buffered_message) {
45 return RAWRTC_CODE_NO_MEMORY;
46 }
47
48 // Set fields
49 buffered_message->buffer = mem_ref(buffer);
50 buffered_message->context = mem_ref(context);
51
52 // Add to list
53 list_append(message_buffer, &buffered_message->le, buffered_message);
54 return RAWRTC_CODE_SUCCESS;
55}
56
57/*
58 * Apply a receive handler to buffered messages.
59 *
60 * Will stop iterating and return `RAWRTC_CODE_STOP_ITERATION` in case
61 * the message handler returned `false`.
62 */
63enum rawrtc_code rawrtc_message_buffer_clear(
64 struct list* const message_buffer,
65 rawrtc_message_buffer_handler* const message_handler,
66 void* arg) {
67 struct le* le;
68 bool unlink;
69
70 // Check arguments
71 if (!message_buffer || !message_handler) {
72 return RAWRTC_CODE_INVALID_ARGUMENT;
73 }
74
75 // Handle each message
76 le = list_head(message_buffer);
77 while (le != NULL) {
78 struct buffered_message* const buffered_message = le->data;
79
80 // Handle message
81 unlink = message_handler(buffered_message->buffer, buffered_message->context, arg);
82 if (unlink) {
83 list_unlink(le);
84 }
85
86 // Get next message
87 le = le->next;
88
89 // Remove message
90 if (unlink) {
91 mem_deref(buffered_message);
92 } else {
93 return RAWRTC_CODE_STOP_ITERATION;
94 }
95 }
96
97 // Done
98 return RAWRTC_CODE_SUCCESS;
99}