32 #include "contiki-lib.h" 36 #include "mqtt-prop.h" 40 #if MQTT_PROP_USE_MEMB 41 MEMB(prop_lists_mem,
struct mqtt_prop_list, MQTT_PROP_MAX_OUT_PROP_LISTS);
42 MEMB(props_mem,
struct mqtt_prop_out_property, MQTT_PROP_MAX_OUT_PROPS);
48 #if MQTT_PROP_USE_MEMB 55 encode_prop_fixed_len_int(
struct mqtt_prop_out_property **prop_out,
60 DBG(
"MQTT - Creating %d-byte int property %i\n", len, val);
62 if(len > MQTT_PROP_MAX_PROP_LENGTH) {
63 DBG(
"MQTT - Error, property too long (max %i bytes)", MQTT_PROP_MAX_PROP_LENGTH);
67 for(i = len - 1; i >= 0; i--) {
68 (*prop_out)->val[i] = val & 0x00FF;
72 (*prop_out)->property_len = len;
76 encode_prop_utf8(
struct mqtt_prop_out_property **prop_out,
81 DBG(
"MQTT - Encoding UTF-8 Property %s\n", str);
82 str_len = strlen(str);
85 if((str_len + 2) > MQTT_PROP_MAX_PROP_LENGTH) {
86 DBG(
"MQTT - Error, property too long (max %i bytes)", MQTT_PROP_MAX_PROP_LENGTH);
90 (*prop_out)->val[0] = str_len >> 8;
91 (*prop_out)->val[1] = str_len & 0x00FF;
92 memcpy((*prop_out)->val + 2, str, str_len);
94 (*prop_out)->property_len = str_len + 2;
98 encode_prop_binary(
struct mqtt_prop_out_property **prop_out,
99 const char *data,
int data_len)
101 DBG(
"MQTT - Encoding Binary Data (%d bytes)\n", data_len);
103 if((data_len + 2) > MQTT_PROP_MAX_PROP_LENGTH) {
104 DBG(
"MQTT - Error, property too long (max %i bytes)", MQTT_PROP_MAX_PROP_LENGTH);
108 (*prop_out)->val[0] = data_len >> 8;
109 (*prop_out)->val[1] = data_len & 0x00FF;
110 memcpy((*prop_out)->val + 2, data, data_len);
112 (*prop_out)->property_len = data_len + 2;
116 encode_prop_var_byte_int(
struct mqtt_prop_out_property **prop_out,
121 DBG(
"MQTT - Encoding Variable Byte Integer %d\n", val);
123 mqtt_encode_var_byte_int(
128 (*prop_out)->property_len = id_len;
132 mqtt_prop_encode(
struct mqtt_prop_out_property **prop_out, mqtt_vhdr_prop_t prop_id,
135 DBG(
"MQTT - Creating property with ID %i\n", prop_id);
138 DBG(
"MQTT - Error, property target NULL!\n");
142 (*prop_out)->property_len = 0;
143 (*prop_out)->id = prop_id;
147 case MQTT_VHDR_PROP_PAYLOAD_FMT_IND:
148 case MQTT_VHDR_PROP_REQ_PROBLEM_INFO:
149 case MQTT_VHDR_PROP_REQ_RESP_INFO: {
152 val = va_arg(args,
int);
153 encode_prop_fixed_len_int(prop_out, val, 1);
157 case MQTT_VHDR_PROP_RECEIVE_MAX:
158 case MQTT_VHDR_PROP_TOPIC_ALIAS_MAX:
159 case MQTT_VHDR_PROP_TOPIC_ALIAS: {
162 val = va_arg(args,
int);
163 encode_prop_fixed_len_int(prop_out, val, 2);
167 case MQTT_VHDR_PROP_MSG_EXP_INT:
168 case MQTT_VHDR_PROP_SESS_EXP_INT:
169 case MQTT_VHDR_PROP_WILL_DELAY_INT:
170 case MQTT_VHDR_PROP_MAX_PKT_SZ: {
173 val = va_arg(args,
int);
174 encode_prop_fixed_len_int(prop_out, val, 4);
178 case MQTT_VHDR_PROP_CONTENT_TYPE:
179 case MQTT_VHDR_PROP_RESP_TOPIC:
180 case MQTT_VHDR_PROP_AUTH_METHOD: {
183 str = va_arg(args,
const char *);
184 encode_prop_utf8(prop_out, str);
188 case MQTT_VHDR_PROP_CORRELATION_DATA:
189 case MQTT_VHDR_PROP_AUTH_DATA: {
193 data = va_arg(args,
const char *);
194 data_len = va_arg(args,
int);
196 encode_prop_binary(prop_out, data, data_len);
200 case MQTT_VHDR_PROP_SUB_ID: {
203 val = va_arg(args,
int);
205 encode_prop_var_byte_int(prop_out, val);
209 case MQTT_VHDR_PROP_USER_PROP: {
215 name = va_arg(args,
const char *);
216 value = va_arg(args,
const char *);
218 name_len = strlen(name);
219 val_len = strlen(value);
221 DBG(
"MQTT - Encoding User Property '%s: %s'\n", name, value);
224 if((name_len + val_len + 4) > MQTT_PROP_MAX_PROP_LENGTH) {
225 DBG(
"MQTT - Error, property '%i' too long (max %i bytes)", prop_id, MQTT_PROP_MAX_PROP_LENGTH);
229 (*prop_out)->val[0] = name_len >> 8;
230 (*prop_out)->val[1] = name_len & 0x00FF;
231 memcpy((*prop_out)->val + 2, name, strlen(name));
232 (*prop_out)->val[name_len + 2] = val_len >> 8;
233 (*prop_out)->val[name_len + 3] = val_len & 0x00FF;
234 memcpy((*prop_out)->val + name_len + 4, value, strlen(value));
236 (*prop_out)->property_len = strlen(name) + strlen(value) + 4;
240 DBG(
"MQTT - Error, no such property '%i'\n", prop_id);
245 DBG(
"MQTT - Property encoded length %i\n", (*prop_out)->property_len);
247 return (*prop_out)->property_len;
252 mqtt_prop_decode_input_props(
struct mqtt_connection *conn)
254 uint8_t prop_len_bytes;
256 DBG(
"MQTT - Parsing input properties\n");
259 if(((conn->in_packet.fhdr & 0xF0) == MQTT_FHDR_MSG_TYPE_PINGREQ) ||
260 ((conn->in_packet.fhdr & 0xF0) == MQTT_FHDR_MSG_TYPE_PINGRESP)) {
264 DBG(
"MQTT - Getting length\n");
267 mqtt_decode_var_byte_int(conn->in_packet.payload_start,
268 conn->in_packet.remaining_length - (conn->in_packet.payload_start - conn->in_packet.payload),
269 NULL, NULL, &conn->in_packet.properties_len);
271 if(prop_len_bytes == 0) {
272 DBG(
"MQTT - Error decoding input properties (out of bounds)\n");
276 DBG(
"MQTT - Received %i VBI property bytes\n", prop_len_bytes);
277 DBG(
"MQTT - Input properties length %i\n", conn->in_packet.properties_len);
282 conn->in_packet.properties_enc_len = prop_len_bytes;
284 conn->in_packet.props_start = conn->in_packet.payload_start + prop_len_bytes;
285 conn->in_packet.payload_start += prop_len_bytes;
286 conn->in_packet.curr_props_pos = conn->in_packet.props_start;
288 DBG(
"MQTT - First byte of first prop %i\n", *conn->in_packet.curr_props_pos);
290 conn->in_packet.has_props = 1;
295 decode_prop_utf8(
struct mqtt_connection *conn,
301 len = (buf_in[0] << 8) + buf_in[1];
303 DBG(
"MQTT - Decoding %d-char UTF8 string property\n", len);
306 if((len + MQTT_STRING_LEN_SIZE + 1) > MQTT_PROP_MAX_PROP_LENGTH) {
307 DBG(
"MQTT - Error, property too long (max %i bytes)", MQTT_PROP_MAX_PROP_LENGTH);
311 memcpy(data, buf_in, len + MQTT_STRING_LEN_SIZE);
312 data[len + MQTT_STRING_LEN_SIZE] =
'\0';
315 return len + MQTT_STRING_LEN_SIZE;
319 decode_prop_fixed_len_int(
struct mqtt_connection *conn,
320 uint8_t *buf_in,
int len,
326 DBG(
"MQTT - Decoding %d-byte int property\n", len);
328 if(len > MQTT_PROP_MAX_PROP_LENGTH) {
329 DBG(
"MQTT - Error, property too long (max %i bytes)", MQTT_PROP_MAX_PROP_LENGTH);
336 data_out = (uint32_t *)data;
338 for(i = 0; i < 4; i++) {
339 *data_out = *data_out << 8;
342 *data_out += buf_in[i];
350 decode_prop_vbi(
struct mqtt_connection *conn,
354 uint8_t prop_len_bytes;
356 DBG(
"MQTT - Decoding Variable Byte Integer property\n");
362 mqtt_decode_var_byte_int(buf_in, 4, NULL, NULL, (uint16_t *)data);
364 if(prop_len_bytes == 0) {
365 DBG(
"MQTT - Error decoding Variable Byte Integer\n");
369 if(prop_len_bytes > MQTT_PROP_MAX_PROP_LENGTH) {
370 DBG(
"MQTT - Error, property too long (max %i bytes)", MQTT_PROP_MAX_PROP_LENGTH);
374 return prop_len_bytes;
378 decode_prop_binary_data(
struct mqtt_connection *conn,
384 DBG(
"MQTT - Decoding Binary Data property\n");
386 data_len = (buf_in[0] << 8) + buf_in[1];
389 DBG(
"MQTT - Error decoding Binary Data property length\n");
393 if((data_len + 2) > MQTT_PROP_MAX_PROP_LENGTH) {
394 DBG(
"MQTT - Error, property too long (max %i bytes)", MQTT_PROP_MAX_PROP_LENGTH);
398 memcpy(data, buf_in, data_len + 2);
404 decode_prop_utf8_pair(
struct mqtt_connection *conn,
412 len1 = (buf_in[0] << 8) + buf_in[1];
413 len2 = (buf_in[len1 + MQTT_STRING_LEN_SIZE] << 8) + buf_in[len1 + MQTT_STRING_LEN_SIZE + 1];
414 total_len = len1 + len2;
416 DBG(
"MQTT - Decoding %d-char UTF8 string pair property (%i + %i)\n", total_len, len1, len2);
418 if((total_len + 2 * MQTT_STRING_LEN_SIZE) > MQTT_PROP_MAX_PROP_LENGTH) {
419 DBG(
"MQTT - Error, property too long (max %i bytes)", MQTT_PROP_MAX_PROP_LENGTH);
423 memcpy(data, buf_in, total_len + 2 * MQTT_STRING_LEN_SIZE);
426 return total_len + 2 * MQTT_STRING_LEN_SIZE;
430 parse_prop(
struct mqtt_connection *conn,
431 mqtt_vhdr_prop_t prop_id, uint8_t *buf_in, uint8_t *data)
434 case MQTT_VHDR_PROP_PAYLOAD_FMT_IND:
435 case MQTT_VHDR_PROP_REQ_PROBLEM_INFO:
436 case MQTT_VHDR_PROP_REQ_RESP_INFO:
437 case MQTT_VHDR_PROP_MAX_QOS:
438 case MQTT_VHDR_PROP_RETAIN_AVAIL:
439 case MQTT_VHDR_PROP_WILD_SUB_AVAIL:
440 case MQTT_VHDR_PROP_SUB_ID_AVAIL:
441 case MQTT_VHDR_PROP_SHARED_SUB_AVAIL: {
442 return decode_prop_fixed_len_int(conn, buf_in, 1, data);
444 case MQTT_VHDR_PROP_RECEIVE_MAX:
445 case MQTT_VHDR_PROP_TOPIC_ALIAS_MAX:
446 case MQTT_VHDR_PROP_SERVER_KEEP_ALIVE: {
447 return decode_prop_fixed_len_int(conn, buf_in, 2, data);
449 case MQTT_VHDR_PROP_MSG_EXP_INT:
450 case MQTT_VHDR_PROP_SESS_EXP_INT:
451 case MQTT_VHDR_PROP_WILL_DELAY_INT:
452 case MQTT_VHDR_PROP_MAX_PKT_SZ: {
453 return decode_prop_fixed_len_int(conn, buf_in, 4, data);
455 case MQTT_VHDR_PROP_CONTENT_TYPE:
456 case MQTT_VHDR_PROP_RESP_TOPIC:
457 case MQTT_VHDR_PROP_AUTH_METHOD:
458 case MQTT_VHDR_PROP_ASSIGNED_CLIENT_ID:
459 case MQTT_VHDR_PROP_RESP_INFO:
460 case MQTT_VHDR_PROP_SERVER_REFERENCE:
461 case MQTT_VHDR_PROP_REASON_STRING: {
462 return decode_prop_utf8(conn, buf_in, data);
464 case MQTT_VHDR_PROP_CORRELATION_DATA:
465 case MQTT_VHDR_PROP_AUTH_DATA: {
466 return decode_prop_binary_data(conn, buf_in, data);
468 case MQTT_VHDR_PROP_SUB_ID: {
469 return decode_prop_vbi(conn, buf_in, data);
471 case MQTT_VHDR_PROP_USER_PROP: {
472 return decode_prop_utf8_pair(conn, buf_in, data);
475 DBG(
"MQTT - Error, no such property '%i'", prop_id);
484 mqtt_get_next_in_prop(
struct mqtt_connection *conn,
485 mqtt_vhdr_prop_t *prop_id, uint8_t *data)
488 uint8_t prop_id_len_bytes;
490 if(!conn->in_packet.has_props) {
491 DBG(
"MQTT - Message has no input properties");
495 DBG(
"MQTT - Curr prop pos %i; len %i; byte %i\n", (conn->in_packet.curr_props_pos - conn->in_packet.props_start),
496 conn->in_packet.properties_len,
497 *conn->in_packet.curr_props_pos);
499 if((conn->in_packet.curr_props_pos - conn->in_packet.props_start)
500 >= conn->in_packet.properties_len) {
501 DBG(
"MQTT - Message has no more input properties\n");
506 mqtt_decode_var_byte_int(conn->in_packet.curr_props_pos,
507 conn->in_packet.properties_len - (conn->in_packet.curr_props_pos - conn->in_packet.props_start),
508 NULL, NULL, (uint16_t *)prop_id);
510 DBG(
"MQTT - Decoded property ID %i (encoded using %i bytes)\n", *prop_id, prop_id_len_bytes);
512 prop_len = parse_prop(conn, *prop_id, conn->in_packet.curr_props_pos + 1, data);
514 DBG(
"MQTT - Decoded property len %i bytes\n", prop_len);
516 conn->in_packet.curr_props_pos += prop_id_len_bytes + prop_len;
522 mqtt_prop_parse_connack_props(
struct mqtt_connection *conn)
525 mqtt_vhdr_prop_t prop_id;
526 uint8_t data[MQTT_PROP_MAX_PROP_LENGTH];
529 DBG(
"MQTT - Parsing CONNACK properties for server capabilities\n");
531 prop_len = mqtt_get_next_in_prop(conn, &prop_id, data);
534 case MQTT_VHDR_PROP_RETAIN_AVAIL: {
535 val_int = (uint32_t)*data;
537 conn->srv_feature_en &= ~MQTT_CAP_RETAIN_AVAIL;
541 case MQTT_VHDR_PROP_WILD_SUB_AVAIL: {
542 val_int = (uint32_t)*data;
544 conn->srv_feature_en &= ~MQTT_CAP_WILD_SUB_AVAIL;
548 case MQTT_VHDR_PROP_SUB_ID_AVAIL: {
549 val_int = (uint32_t)*data;
551 conn->srv_feature_en &= ~MQTT_CAP_SUB_ID_AVAIL;
555 case MQTT_VHDR_PROP_SHARED_SUB_AVAIL: {
556 val_int = (uint32_t)*data;
558 conn->srv_feature_en &= ~MQTT_CAP_SHARED_SUB_AVAIL;
563 DBG(
"MQTT - Error, unexpected CONNACK property '%i'", prop_id);
568 prop_len = mqtt_get_next_in_prop(conn, &prop_id, data);
573 mqtt_prop_parse_auth_props(
struct mqtt_connection *conn,
struct mqtt_prop_auth_event *event)
576 mqtt_vhdr_prop_t prop_id;
577 uint8_t data[MQTT_PROP_MAX_PROP_LENGTH];
579 DBG(
"MQTT - Parsing CONNACK properties for server capabilities\n");
581 event->auth_data.len = 0;
582 event->auth_method.length = 0;
584 prop_len = mqtt_get_next_in_prop(conn, &prop_id, data);
587 case MQTT_VHDR_PROP_AUTH_DATA: {
588 event->auth_data.len = prop_len - 2;
589 memcpy(event->auth_data.data, data, prop_len - 2);
592 case MQTT_VHDR_PROP_AUTH_METHOD: {
593 event->auth_method.length = prop_len - 2;
594 memcpy(event->auth_method.string, data, prop_len - 2);
598 DBG(
"MQTT - Unhandled AUTH property '%i'", prop_id);
603 prop_len = mqtt_get_next_in_prop(conn, &prop_id, data);
608 mqtt_prop_print_input_props(
struct mqtt_connection *conn)
611 mqtt_vhdr_prop_t prop_id;
612 uint8_t data[MQTT_PROP_MAX_PROP_LENGTH];
615 DBG(
"MQTT - Printing all input properties\n");
617 prop_len = mqtt_get_next_in_prop(conn, &prop_id, data);
619 DBG(
"MQTT - Property ID %i, length %i\n", prop_id, prop_len);
622 case MQTT_VHDR_PROP_PAYLOAD_FMT_IND:
623 case MQTT_VHDR_PROP_REQ_PROBLEM_INFO:
624 case MQTT_VHDR_PROP_REQ_RESP_INFO:
625 case MQTT_VHDR_PROP_MSG_EXP_INT:
626 case MQTT_VHDR_PROP_SESS_EXP_INT:
627 case MQTT_VHDR_PROP_WILL_DELAY_INT:
628 case MQTT_VHDR_PROP_MAX_PKT_SZ:
629 case MQTT_VHDR_PROP_RECEIVE_MAX:
630 case MQTT_VHDR_PROP_TOPIC_ALIAS_MAX:
631 case MQTT_VHDR_PROP_SUB_ID: {
632 DBG(
"MQTT - Decoded property value '%i'\n", (uint32_t)*data);
635 case MQTT_VHDR_PROP_CONTENT_TYPE:
636 case MQTT_VHDR_PROP_RESP_TOPIC:
637 case MQTT_VHDR_PROP_AUTH_METHOD: {
638 DBG(
"MQTT - Decoded property value ");
639 DBG(
"(%i %i) %s", data[0], data[1], data + MQTT_STRING_LEN_SIZE);
643 case MQTT_VHDR_PROP_CORRELATION_DATA:
644 case MQTT_VHDR_PROP_AUTH_DATA: {
645 DBG(
"MQTT - Decoded property value (%i %i) ", data[0], data[1]);
646 for(i = 2; i < prop_len; i++) {
652 case MQTT_VHDR_PROP_USER_PROP: {
657 len1 = (data[0] << 8) + data[1];
658 len2 = (data[len1 + MQTT_STRING_LEN_SIZE] << 8) + data[len1 + MQTT_STRING_LEN_SIZE + 1];
660 DBG(
"MQTT - Decoded property value [(%i %i) %.*s, (%i %i) %.*s]",
661 data[0], data[1], len1, data + MQTT_STRING_LEN_SIZE,
662 data[len1 + MQTT_STRING_LEN_SIZE], data[len1 + MQTT_STRING_LEN_SIZE + 1], len2, data + len1 + 2 * MQTT_STRING_LEN_SIZE);
667 DBG(
"MQTT - Error, no such property '%i'\n", prop_id);
672 prop_len = mqtt_get_next_in_prop(conn, &prop_id, data);
681 mqtt_prop_create_list(
struct mqtt_prop_list **prop_list_out)
683 DBG(
"MQTT - Creating Property List\n");
685 #if MQTT_PROP_USE_MEMB 689 if(!(*prop_list_out)) {
690 DBG(
"MQTT - Error, allocated too many property lists (max %i)\n", MQTT_PROP_MAX_OUT_PROP_LISTS);
694 DBG(
"MQTT - Allocated Property list\n");
698 DBG(
"MQTT - mem %p prop_list\n", *prop_list_out);
700 (*prop_list_out)->properties_len = 0;
701 (*prop_list_out)->properties_len_enc_bytes = 1;
709 mqtt_prop_print_list(
struct mqtt_prop_list *prop_list, mqtt_vhdr_prop_t prop_id)
711 struct mqtt_prop_out_property *prop;
713 if(prop_list == NULL || prop_list->props == NULL) {
714 DBG(
"MQTT - Prop list empty\n");
716 prop = (
struct mqtt_prop_out_property *)
list_head(prop_list->props);
719 if(prop != NULL && (prop->id == prop_id || prop_id == MQTT_VHDR_PROP_ANY)) {
720 DBG(
"Property %p ID %i len %i\n", prop, prop->id, prop->property_len);
723 }
while(prop != NULL);
728 mqtt_prop_register(
struct mqtt_prop_list **prop_list,
729 struct mqtt_prop_out_property **prop_out,
730 #
if !MQTT_PROP_USE_MEMB
731 struct mqtt_prop_out_property *prop,
734 mqtt_vhdr_prop_t prop_id, ...)
736 #if MQTT_PROP_USE_MEMB 737 struct mqtt_prop_out_property *prop;
742 va_start(args, prop_id);
747 DBG(
"MQTT - Error encoding prop %i on msg %i; list NULL\n", prop_id, msg);
752 DBG(
"MQTT - prop list %p\n", *prop_list);
753 DBG(
"MQTT - prop list->list %p\n", (*prop_list)->props);
755 #if MQTT_PROP_USE_MEMB 756 prop = (
struct mqtt_prop_out_property *)
memb_alloc(&props_mem);
760 DBG(
"MQTT - Error, allocated too many properties (max %i)\n", MQTT_PROP_MAX_OUT_PROPS);
765 DBG(
"MQTT - Allocated prop %p\n", prop);
767 prop_len = mqtt_prop_encode(&prop, prop_id, args);
770 DBG(
"MQTT - Adding prop %p to prop_list %p\n", prop, *prop_list);
771 list_add((*prop_list)->props, prop);
772 (*prop_list)->properties_len += 1;
773 (*prop_list)->properties_len += prop_len;
774 mqtt_encode_var_byte_int(
775 (*prop_list)->properties_len_enc,
776 &((*prop_list)->properties_len_enc_bytes),
777 (*prop_list)->properties_len);
778 DBG(
"MQTT - New prop_list length %i\n", (*prop_list)->properties_len);
780 DBG(
"MQTT - Error encoding prop %i on msg %i\n", prop_id, msg);
781 #if MQTT_PROP_USE_MEMB 798 mqtt_remove_prop(
struct mqtt_prop_list **prop_list,
799 struct mqtt_prop_out_property *prop)
801 if(prop != NULL && prop_list != NULL &&
list_contains((*prop_list)->props, prop)) {
802 DBG(
"MQTT - Removing property %p from list %p\n", prop, *prop_list);
808 (*prop_list)->properties_len -= prop->property_len;
809 (*prop_list)->properties_len -= 1;
811 mqtt_encode_var_byte_int(
812 (*prop_list)->properties_len_enc,
813 &((*prop_list)->properties_len_enc_bytes),
814 (*prop_list)->properties_len);
817 #if MQTT_PROP_USE_MEMB 822 DBG(
"MQTT - Cannot remove property\n");
828 mqtt_prop_clear_list(
struct mqtt_prop_list **prop_list)
830 struct mqtt_prop_out_property *prop;
832 DBG(
"MQTT - Clearing Property List\n");
834 if(prop_list == NULL ||
list_length((*prop_list)->props) == 0) {
835 DBG(
"MQTT - Prop list empty\n");
838 prop = (
struct mqtt_prop_out_property *)
list_head((*prop_list)->props);
842 (void)mqtt_remove_prop(prop_list, prop);
844 prop = (
struct mqtt_prop_out_property *)
list_head((*prop_list)->props);
845 }
while(prop != NULL);
850 if((*prop_list)->properties_len != 0 || (*prop_list)->properties_len_enc_bytes != 1) {
851 DBG(
"MQTT - Something went wrong when clearing property list!\n");
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
bool list_contains(list_t list, void *item)
Check if the list contains an item.
void * list_head(list_t list)
Get a pointer to the first element of a list.
Header file for the Contiki MQTT engine.
Memory block allocation routines.
void list_add(list_t list, void *item)
Add an item at the end of a list.
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
void list_remove(list_t list, void *item)
Remove a specific element from a list.
void * list_item_next(void *item)
Get the next item following this item.
#define MEMB(name, structure, num)
Declare a memory block.
int list_length(list_t list)
Get the length of a list.