Asterisk - The Open Source Telephony Project GIT-master-2de1a68
Typedefs | Functions
data_buffer.h File Reference

Data Buffer API. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef void(* ast_data_buffer_free_callback) (void *data)
 A callback function to free a data payload in a data buffer. More...
 

Functions

struct ast_data_bufferast_data_buffer_alloc (ast_data_buffer_free_callback free_fn, size_t size)
 Allocate a data buffer. More...
 
size_t ast_data_buffer_count (const struct ast_data_buffer *buffer)
 Return the number of payloads in a data buffer. More...
 
void ast_data_buffer_free (struct ast_data_buffer *buffer)
 Free a data buffer (and all held data payloads) More...
 
void * ast_data_buffer_get (const struct ast_data_buffer *buffer, size_t pos)
 Retrieve a data payload from the data buffer. More...
 
size_t ast_data_buffer_max (const struct ast_data_buffer *buffer)
 Return the maximum number of payloads a data buffer can hold. More...
 
int ast_data_buffer_put (struct ast_data_buffer *buffer, size_t pos, void *payload)
 Place a data payload at a position in the data buffer. More...
 
void * ast_data_buffer_remove (struct ast_data_buffer *buffer, size_t pos)
 Remove a data payload from the data buffer. More...
 
void * ast_data_buffer_remove_head (struct ast_data_buffer *buffer)
 Remove the first payload from the data buffer. More...
 
void ast_data_buffer_resize (struct ast_data_buffer *buffer, size_t size)
 Resize a data buffer. More...
 

Detailed Description

Data Buffer API.

A data buffer acts as a ring buffer of data. It is given a fixed number of data packets to store (which may be dynamically changed). Given a number it will store a data packet at that position relative to the others. Given a number it will retrieve the given data packet if it is present. This is purposely a storage of arbitrary things so that it can be used for multiple things.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om
Ben Ford bford.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file data_buffer.h.

Typedef Documentation

◆ ast_data_buffer_free_callback

typedef void(* ast_data_buffer_free_callback) (void *data)

A callback function to free a data payload in a data buffer.

Parameters
dataThe data payload

Definition at line 48 of file data_buffer.h.

Function Documentation

◆ ast_data_buffer_alloc()

struct ast_data_buffer * ast_data_buffer_alloc ( ast_data_buffer_free_callback  free_fn,
size_t  size 
)

Allocate a data buffer.

Parameters
free_fnCallback function to free a data payload
sizeThe maximum number of data payloads to contain in the data buffer
Return values
non-NULLsuccess
NULLfailure
Note
free_fn can be NULL. It is up to the consumer of this API to ensure that memory is managed appropriately.
Since
15.4.0

Definition at line 145 of file data_buffer.c.

146{
147 struct ast_data_buffer *buffer;
148
149 ast_assert(size != 0);
150
151 buffer = ast_calloc(1, sizeof(*buffer));
152 if (!buffer) {
153 return NULL;
154 }
155
158
159 /* If free_fn is NULL, just use free_fn_do_nothing as a default */
161 buffer->max = size;
162
164
165 return buffer;
166}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static void ast_data_buffer_cache_adjust(struct ast_data_buffer *buffer)
Helper function that sets the cache to its maximum number of payloads.
Definition: data_buffer.c:100
static void free_fn_do_nothing(void *data)
Definition: data_buffer.c:74
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
#define NULL
Definition: resample.c:96
Data buffer containing fixed number of data payloads.
Definition: data_buffer.c:59
size_t max
Maximum number of data payloads in the buffer.
Definition: data_buffer.c:69
struct ast_data_buffer::@340 payloads
A linked list of data payloads.
ast_data_buffer_free_callback free_fn
Callback function to free a data payload.
Definition: data_buffer.c:61
struct ast_data_buffer::@341 cached_payloads
A linked list of unused cached data payloads.
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_calloc, ast_data_buffer_cache_adjust(), AST_LIST_HEAD_INIT_NOLOCK, ast_data_buffer::cached_payloads, ast_data_buffer::free_fn, free_fn_do_nothing(), ast_data_buffer::max, NULL, and ast_data_buffer::payloads.

Referenced by ast_rtp_prop_set(), and AST_TEST_DEFINE().

◆ ast_data_buffer_count()

size_t ast_data_buffer_count ( const struct ast_data_buffer buffer)

Return the number of payloads in a data buffer.

Parameters
bufferThe data buffer
Returns
the number of data payloads
Since
15.4.0

Definition at line 356 of file data_buffer.c.

357{
358 ast_assert(buffer != NULL);
359
360 return buffer->count;
361}
size_t count
The current number of data payloads in the buffer.
Definition: data_buffer.c:67

References ast_assert, ast_data_buffer::count, and NULL.

Referenced by ast_rtp_read(), and AST_TEST_DEFINE().

◆ ast_data_buffer_free()

void ast_data_buffer_free ( struct ast_data_buffer buffer)

Free a data buffer (and all held data payloads)

Parameters
bufferThe data buffer
Since
15.4.0

Definition at line 338 of file data_buffer.c.

339{
340 struct data_buffer_payload_entry *buffer_payload;
341
342 ast_assert(buffer != NULL);
343
344 while ((buffer_payload = AST_LIST_REMOVE_HEAD(&buffer->payloads, list))) {
345 buffer->free_fn(buffer_payload->payload);
346 ast_free(buffer_payload);
347 }
348
349 while ((buffer_payload = AST_LIST_REMOVE_HEAD(&buffer->cached_payloads, list))) {
350 ast_free(buffer_payload);
351 }
352
353 ast_free(buffer);
354}
#define ast_free(a)
Definition: astmm.h:180
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
Payload entry placed inside of the data buffer list.
Definition: data_buffer.c:47
struct data_buffer_payload_entry::@339 list
Linked list information.
void * payload
The payload for this position.
Definition: data_buffer.c:49

References ast_assert, ast_free, AST_LIST_REMOVE_HEAD, ast_data_buffer::cached_payloads, ast_data_buffer::free_fn, data_buffer_payload_entry::list, NULL, data_buffer_payload_entry::payload, and ast_data_buffer::payloads.

Referenced by ast_data_buffer_free_wrapper(), ast_rtp_destroy(), and ast_rtp_prop_set().

◆ ast_data_buffer_get()

void * ast_data_buffer_get ( const struct ast_data_buffer buffer,
size_t  pos 
)

Retrieve a data payload from the data buffer.

Parameters
bufferThe data buffer
posThe position of the data payload
Return values
non-NULLsuccess
NULLfailure
Note
This does not remove the data payload from the data buffer. It will be removed when it is displaced.
Since
15.4.0

Definition at line 269 of file data_buffer.c.

270{
271 struct data_buffer_payload_entry *buffer_payload;
272
273 ast_assert(buffer != NULL);
274
275 AST_LIST_TRAVERSE(&buffer->payloads, buffer_payload, list) {
276 if (buffer_payload->pos == pos) {
277 return buffer_payload->payload;
278 }
279 }
280
281 return NULL;
282}
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
size_t pos
The provided position for this.
Definition: data_buffer.c:51

References ast_assert, AST_LIST_TRAVERSE, data_buffer_payload_entry::list, NULL, data_buffer_payload_entry::payload, ast_data_buffer::payloads, and data_buffer_payload_entry::pos.

Referenced by ast_rtp_read(), ast_rtp_rtcp_handle_nack(), and AST_TEST_DEFINE().

◆ ast_data_buffer_max()

size_t ast_data_buffer_max ( const struct ast_data_buffer buffer)

Return the maximum number of payloads a data buffer can hold.

Parameters
bufferThe data buffer
Returns
the maximum number of data payloads
Since
15.4.0

Definition at line 363 of file data_buffer.c.

364{
365 ast_assert(buffer != NULL);
366
367 return buffer->max;
368}

References ast_assert, ast_data_buffer::max, and NULL.

Referenced by ast_rtp_read(), ast_rtp_rtcp_handle_nack(), and AST_TEST_DEFINE().

◆ ast_data_buffer_put()

int ast_data_buffer_put ( struct ast_data_buffer buffer,
size_t  pos,
void *  payload 
)

Place a data payload at a position in the data buffer.

Parameters
bufferThe data buffer
posThe position of the data payload
payloadThe data payload
Return values
0success
-1failure
Note
It is up to the consumer of this API to ensure proper memory management of data payloads
Since
15.4.0

Definition at line 203 of file data_buffer.c.

204{
205 struct data_buffer_payload_entry *buffer_payload = NULL;
206 struct data_buffer_payload_entry *existing_payload;
207 int inserted = 0;
208
209 ast_assert(buffer != NULL);
211
212 /* If the data buffer has reached its maximum size then the head goes away and
213 * we will reuse its buffer payload
214 */
215 if (buffer->count == buffer->max) {
216 buffer_payload = AST_LIST_REMOVE_HEAD(&buffer->payloads, list);
217 buffer->free_fn(buffer_payload->payload);
218 buffer->count--;
219
220 /* Update this buffer payload with its new information */
221 buffer_payload->payload = payload;
222 buffer_payload->pos = pos;
223 }
224 if (!buffer_payload) {
225 if (!buffer->cache_count) {
227 }
228 buffer_payload = AST_LIST_REMOVE_HEAD(&buffer->cached_payloads, list);
229 buffer->cache_count--;
230
231 /* Update the payload from the cache with its new information */
232 buffer_payload->payload = payload;
233 buffer_payload->pos = pos;
234 }
235 if (!buffer_payload) {
236 return -1;
237 }
238
239 /* Given the position find its ideal spot within the buffer */
240 AST_LIST_TRAVERSE_SAFE_BEGIN(&buffer->payloads, existing_payload, list) {
241 /* If it's already in the buffer, drop it */
242 if (existing_payload->pos == pos) {
243 ast_debug(3, "Packet with position %zu is already in buffer. Not inserting.\n", pos);
244 inserted = -1;
245 break;
246 }
247
248 if (existing_payload->pos > pos) {
249 AST_LIST_INSERT_BEFORE_CURRENT(buffer_payload, list);
250 inserted = 1;
251 break;
252 }
253 }
255
256 if (inserted == -1) {
257 return -1;
258 }
259
260 if (!inserted) {
261 AST_LIST_INSERT_TAIL(&buffer->payloads, buffer_payload, list);
262 }
263
264 buffer->count++;
265
266 return 0;
267}
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
Definition: linkedlists.h:599
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
size_t cache_count
The current number of data payloads in the cache.
Definition: data_buffer.c:71

References ast_assert, ast_data_buffer_cache_adjust(), ast_debug, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_data_buffer::cache_count, ast_data_buffer::cached_payloads, ast_data_buffer::count, ast_data_buffer::free_fn, data_buffer_payload_entry::list, ast_data_buffer::max, NULL, data_buffer_payload_entry::payload, ast_data_buffer::payloads, and data_buffer_payload_entry::pos.

Referenced by ast_rtp_read(), AST_TEST_DEFINE(), and rtp_raw_write().

◆ ast_data_buffer_remove()

void * ast_data_buffer_remove ( struct ast_data_buffer buffer,
size_t  pos 
)

Remove a data payload from the data buffer.

Parameters
bufferThe data buffer
posThe position of the data payload
Return values
non-NULLsuccess
NULLfailure
Note
This DOES remove the data payload from the data buffer. It does not free it, though.
Since
15.5.0

Definition at line 299 of file data_buffer.c.

300{
301 struct data_buffer_payload_entry *buffer_payload;
302
303 ast_assert(buffer != NULL);
304
305 AST_LIST_TRAVERSE_SAFE_BEGIN(&buffer->payloads, buffer_payload, list) {
306 if (buffer_payload->pos == pos) {
307 void *payload = buffer_payload->payload;
308
310 data_buffer_free_buffer_payload(buffer, buffer_payload);
311
312 return payload;
313 }
314 }
316
317 return NULL;
318}
static void data_buffer_free_buffer_payload(struct ast_data_buffer *buffer, struct data_buffer_payload_entry *buffer_payload)
Definition: data_buffer.c:284
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557

References ast_assert, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, data_buffer_free_buffer_payload(), data_buffer_payload_entry::list, NULL, data_buffer_payload_entry::payload, ast_data_buffer::payloads, and data_buffer_payload_entry::pos.

Referenced by ast_rtp_read(), and AST_TEST_DEFINE().

◆ ast_data_buffer_remove_head()

void * ast_data_buffer_remove_head ( struct ast_data_buffer buffer)

Remove the first payload from the data buffer.

Parameters
bufferThe data buffer
Return values
non-NULLsuccess
NULLfailure
Note
This DOES remove the data payload from the data buffer.
Since
15.5.0

Definition at line 320 of file data_buffer.c.

321{
322 ast_assert(buffer != NULL);
323
324 if (buffer->count > 0) {
325 struct data_buffer_payload_entry *buffer_payload;
326 void *payload;
327
328 buffer_payload = AST_LIST_REMOVE_HEAD(&buffer->payloads, list);
329 payload = buffer_payload->payload;
330 data_buffer_free_buffer_payload(buffer, buffer_payload);
331
332 return payload;
333 }
334
335 return NULL;
336}

References ast_assert, AST_LIST_REMOVE_HEAD, ast_data_buffer::count, data_buffer_free_buffer_payload(), data_buffer_payload_entry::list, NULL, data_buffer_payload_entry::payload, and ast_data_buffer::payloads.

Referenced by AST_TEST_DEFINE().

◆ ast_data_buffer_resize()

void ast_data_buffer_resize ( struct ast_data_buffer buffer,
size_t  size 
)

Resize a data buffer.

Parameters
bufferThe data buffer
sizeThe new maximum size of the data buffer
Note
If the data buffer is shrunk any old data payloads will be freed using the configured callback. The data buffer is flexible and can be used for multiple purposes. Therefore it is up to the caller of the function to know whether or not a buffer should have its size changed. Increasing the size of the buffer may make sense in some scenarios, but shrinking should always be handled with caution since data can be lost.
Since
15.4.0

Definition at line 168 of file data_buffer.c.

169{
170 struct data_buffer_payload_entry *existing_payload;
171
172 ast_assert(buffer != NULL);
173
174 /* The buffer must have at least a size of 1 */
175 ast_assert(size > 0);
176
177 if (buffer->max == size) {
178 return;
179 }
180
181 /* If the size is decreasing, some payloads will need to be freed */
182 if (buffer->max > size) {
183 int remove = buffer->max - size;
184
185 AST_LIST_TRAVERSE_SAFE_BEGIN(&buffer->payloads, existing_payload, list) {
186 if (remove) {
188 buffer->free_fn(existing_payload->payload);
189 ast_free(existing_payload);
190 buffer->count--;
191 remove--;
192 continue;
193 }
194 break;
195 }
197 }
198
199 buffer->max = size;
201}
#define remove

References ast_assert, ast_data_buffer_cache_adjust(), ast_free, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_data_buffer::count, ast_data_buffer::free_fn, data_buffer_payload_entry::list, ast_data_buffer::max, NULL, data_buffer_payload_entry::payload, ast_data_buffer::payloads, and remove.

Referenced by ast_rtp_read(), ast_rtp_rtcp_handle_nack(), and AST_TEST_DEFINE().