libcoap 4.3.1
mem.c
Go to the documentation of this file.
1/* mem.c -- CoAP memory handling
2 *
3 * Copyright (C) 2014--2015,2019--2020 Olaf Bergmann <bergmann@tzi.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 *
7 * This file is part of the CoAP library libcoap. Please see
8 * README for terms of use.
9 */
10
16#include "coap3/coap_internal.h"
17
18#if defined(RIOT_VERSION) && defined(MODULE_MEMARRAY)
19#include <memarray.h>
20
21#undef PACKAGE_NAME
22#undef PACKAGE_STRING
23#undef PACKAGE_TARNAME
24#undef PACKAGE_VERSION
25#include <session.h>
26#undef PACKAGE_NAME
27#undef PACKAGE_STRING
28#undef PACKAGE_TARNAME
29#undef PACKAGE_VERSION
30
31#include "coap_session.h"
32#include "net.h"
33#include "pdu.h"
34#include "resource.h"
35
40#ifndef COAP_MAX_STRING_SIZE
41#define COAP_MAX_STRING_SIZE (64U)
42#endif /* COAP_MAX_STRING_SIZE */
43
48#ifndef COAP_MAX_STRINGS
49#define COAP_MAX_STRINGS (16U)
50#endif /* COAP_MAX_STRINGS */
51
56#ifndef COAP_MAX_ENDPOINTS
57#define COAP_MAX_ENDPOINTS (4U)
58#endif /* COAP_MAX_ENDPOINTS */
59
64#ifndef COAP_MAX_RESOURCES
65#define COAP_MAX_RESOURCES (8U)
66#endif /* COAP_MAX_RESOURCES */
67
72#ifndef COAP_MAX_ATTRIBUTES
73#define COAP_MAX_ATTRIBUTES \
74 ((COAP_MAX_RESOURCES) * 4U)
75#endif /* COAP_MAX_ATTRIBUTE_STRINGS */
76
83#ifndef COAP_MAX_ATTRIBUTE_STRINGS
84#define COAP_MAX_ATTRIBUTE_STRINGS (COAP_MAX_ATTRIBUTES)
85#endif /* COAP_MAX_ATTRIBUTE_STRINGS */
86
91#ifndef COAP_MAX_ATTRIBUTE_SIZE
92#define COAP_MAX_ATTRIBUTE_SIZE (16U)
93#endif /* COAP_MAX_ATTRIBUTE_SIZE */
94
99#ifndef COAP_MAX_PACKETS
100#define COAP_MAX_PACKETS (4U)
101#endif /* COAP_MAX_PACKETS */
102
108#ifndef COAP_MAX_NODES
109#define COAP_MAX_NODES \
110 ((COAP_MAX_ENDPOINTS) * (COAP_MAX_PACKETS))
111#endif /* COAP_MAX_NODES */
112
117#ifndef COAP_MAX_CONTEXTS
118#define COAP_MAX_CONTEXTS (1U)
119#endif /* COAP_MAX_CONTEXTS */
120
126#ifndef COAP_MAX_PDUS
127#define COAP_MAX_PDUS ((COAP_MAX_ENDPOINTS) * 4U)
128#endif /* COAP_MAX_PDUS */
129
134#ifndef COAP_MAX_DTLS_SESSIONS
135#define COAP_MAX_DTLS_SESSIONS (2U)
136#endif /* COAP_MAX_CONTEXTS */
137
142#ifndef COAP_MAX_SESSIONS
143#define COAP_MAX_SESSIONS (COAP_MAX_ENDPOINTS)
144#endif /* COAP_MAX_CONTEXTS */
145
150#ifndef COAP_MAX_OPTIONS
151#define COAP_MAX_OPTIONS (16U)
152#endif /* COAP_MAX_CONTEXTS */
153
158#ifndef COAP_MAX_OPTION_SIZE
159#define COAP_MAX_OPTION_SIZE (16U)
160#endif /* COAP_MAX_OPTION_SIZE */
161
166#ifndef COAP_MAX_CACHE_KEYS
167#define COAP_MAX_CACHE_KEYS (2U)
168#endif /* COAP_MAX_CACHE_KEYS */
169
174#ifndef COAP_MAX_CACHE_ENTRIES
175#define COAP_MAX_CACHE_ENTRIES (2U)
176#endif /* COAP_MAX_CACHE_ENTRIES */
177
178/* The memstr is the storage for holding coap_string_t structure
179 * together with its contents. */
180union memstr_t {
182 char buf[sizeof(coap_string_t) + COAP_MAX_STRING_SIZE];
183};
184
185/* The attrstr is the storage for holding coap_string_t structures to
186 * serve as attribute names or values. As these are typically short,
187 * they are stored in a different arena than generic strings. */
188union attrstr_t {
190 char buf[sizeof(coap_string_t) + COAP_MAX_ATTRIBUTE_SIZE];
191};
192
193static union memstr_t string_storage_data[COAP_MAX_STRINGS];
194static memarray_t string_storage;
195
196static coap_endpoint_t endpoint_storage_data[COAP_MAX_ENDPOINTS];
197static memarray_t endpoint_storage;
198
199static union attrstr_t attr_storage_data[COAP_MAX_ATTRIBUTE_STRINGS];
200static memarray_t attr_storage;
201
202static coap_attr_t resattr_storage_data[COAP_MAX_ATTRIBUTES];
203static memarray_t resattr_storage;
204
205static coap_packet_t pkt_storage_data[COAP_MAX_PACKETS];
206static memarray_t pkt_storage;
207
208static coap_queue_t node_storage_data[COAP_MAX_NODES];
209static memarray_t node_storage;
210
211static coap_context_t context_storage_data[COAP_MAX_CONTEXTS];
212static memarray_t context_storage;
213
214static coap_pdu_t pdu_storage_data[COAP_MAX_PDUS];
215static memarray_t pdu_storage;
216
217/* The pdubuf is the storage for holding the (assembled) PDU data in a
218 * coap_pdu_t structure. */
219union pdubuf_t {
220 void *p; /* try to convince the compiler to word-align this structure */
221 char buf[COAP_DEFAULT_MAX_PDU_RX_SIZE];
222};
223
224static union pdubuf_t pdubuf_storage_data[COAP_MAX_PDUS];
225static memarray_t pdubuf_storage;
226
227static coap_resource_t resource_storage_data[COAP_MAX_RESOURCES];
228static memarray_t resource_storage;
229
230#ifdef HAVE_LIBTINYDTLS
231static session_t dtls_storage_data[COAP_MAX_DTLS_SESSIONS];
232static memarray_t dtls_storage;
233#endif /* HAVE_LIBTINYDTLS */
234
235static coap_session_t session_storage_data[COAP_MAX_SESSIONS];
236static memarray_t session_storage;
237
238/* The optbuf_t is the storage for holding optlist nodes. */
239struct optbuf_t {
240 coap_optlist_t optlist;
241 char optbuf[COAP_MAX_OPTION_SIZE];
242};
243static struct optbuf_t option_storage_data[COAP_MAX_OPTIONS];
244static memarray_t option_storage;
245
246static coap_cache_key_t cache_key_storage_data[COAP_MAX_CACHE_KEYS];
247static memarray_t cache_key_storage;
248
249static coap_cache_entry_t cache_entry_storage_data[COAP_MAX_CACHE_ENTRIES];
250static memarray_t cache_entry_storage;
251
252#define INIT_STORAGE(Storage, Count) \
253 memarray_init(&(Storage ## _storage), (Storage ## _storage_data), sizeof(Storage ## _storage_data[0]), (Count));
254
255#define STORAGE_PTR(Storage) (&(Storage ## _storage))
256
257void
258coap_memory_init(void) {
259 INIT_STORAGE(string, COAP_MAX_STRINGS);
260 INIT_STORAGE(endpoint, COAP_MAX_ENDPOINTS);
261 INIT_STORAGE(attr, COAP_MAX_ATTRIBUTE_STRINGS);
262 INIT_STORAGE(pkt, COAP_MAX_PACKETS);
263 INIT_STORAGE(node, COAP_MAX_NODES);
264 INIT_STORAGE(context, COAP_MAX_CONTEXTS);
265 INIT_STORAGE(pdu, COAP_MAX_PDUS);
266 INIT_STORAGE(pdubuf, COAP_MAX_PDUS);
267 INIT_STORAGE(resource, COAP_MAX_RESOURCES);
268 INIT_STORAGE(resattr, COAP_MAX_ATTRIBUTES);
269#ifdef HAVE_LIBTINYDTLS
270 INIT_STORAGE(dtls, COAP_MAX_DTLS_SESSIONS);
271#endif
272 INIT_STORAGE(session, COAP_MAX_SESSIONS);
273 INIT_STORAGE(option, COAP_MAX_OPTIONS);
274 INIT_STORAGE(cache_key, COAP_MAX_CACHE_KEYS);
275 INIT_STORAGE(cache_entry, COAP_MAX_CACHE_ENTRIES);
276}
277
278static memarray_t *
279get_container(coap_memory_tag_t type) {
280 switch(type) {
282 /* fall through */
283 case COAP_ATTRIBUTE_VALUE: return &attr_storage;
284 case COAP_PACKET: return &pkt_storage;
285 case COAP_NODE: return &node_storage;
286 case COAP_CONTEXT: return STORAGE_PTR(context);
287 case COAP_ENDPOINT: return &endpoint_storage;
288 case COAP_PDU: return &pdu_storage;
289 case COAP_PDU_BUF: return &pdubuf_storage;
290 case COAP_RESOURCE: return &resource_storage;
291 case COAP_RESOURCEATTR: return &resattr_storage;
292#ifdef HAVE_LIBTINYDTLS
293 case COAP_DTLS_SESSION: return &dtls_storage;
294#endif
295 case COAP_SESSION: return &session_storage;
296 case COAP_OPTLIST: return &option_storage;
297 case COAP_CACHE_KEY: return &cache_key_storage;
298 case COAP_CACHE_ENTRY: return &cache_key_entry;
299 case COAP_STRING:
300 /* fall through */
301 default:
302 return &string_storage;
303 }
304}
305
306void *
307coap_malloc_type(coap_memory_tag_t type, size_t size) {
308 memarray_t *container = get_container(type);
309 void *ptr;
310 assert(container);
311
312 if (size > container->size) {
314 "coap_malloc_type: Requested memory exceeds maximum object "
315 "size (type %d, size %zu, max %d)\n",
316 type, size, container->size);
317 return NULL;
318 }
319
320 ptr = memarray_alloc(container);
321 if (!ptr)
323 "coap_malloc_type: Failure (no free blocks) for type %d\n",
324 type);
325 return ptr;
326}
327
328void
329coap_free_type(coap_memory_tag_t type, void *object) {
330 if (object != NULL)
331 memarray_free(get_container(type), object);
332}
333
334void *
335coap_realloc_type(coap_memory_tag_t type, void *p, size_t size) {
336 memarray_t *container = get_container(type);
337
338 assert(container);
339 /* The fixed container is all we have to work with */
340 if (p) {
341 if (size > container->size) {
343 "coap_realloc_type: Requested memory exceeds maximum object "
344 "size (type %d, size %zu, max %d)\n",
345 type, size, container->size);
346 return NULL;
347 }
348 if (size == 0) {
349 coap_free_type(type, p);
350 return NULL;
351 }
352 return p;
353 }
354 return coap_malloc_type(type, size);
355}
356#else /* ! RIOT_VERSION */
357
358#ifdef HAVE_MALLOC
359#include <stdlib.h>
360
361void
362coap_memory_init(void) {
363}
364
365void *
366coap_malloc_type(coap_memory_tag_t type, size_t size) {
367 (void)type;
368 return malloc(size);
369}
370
371void *
372coap_realloc_type(coap_memory_tag_t type, void* p, size_t size) {
373 (void)type;
374 return realloc(p, size);
375}
376
377void
378coap_free_type(coap_memory_tag_t type, void *p) {
379 (void)type;
380 free(p);
381}
382
383#else /* ! HAVE_MALLOC */
384
385#ifdef WITH_CONTIKI
386
391#ifndef COAP_MAX_STRING_SIZE
392#define COAP_MAX_STRING_SIZE 64
393#endif /* COAP_MAX_STRING_SIZE */
394
399#ifndef COAP_MAX_STRINGS
400#define COAP_MAX_STRINGS 10
401#endif /* COAP_MAX_STRINGS */
402
403struct coap_stringbuf_t {
404 char data[COAP_MAX_STRING_SIZE];
405};
406
407
408#define COAP_MAX_PACKET_SIZE (sizeof(coap_packet_t) + COAP_RXBUFFER_SIZE)
409#ifndef COAP_MAX_PACKETS
410#define COAP_MAX_PACKETS 2
411#endif /* COAP_MAX_PACKETS */
412
413typedef union {
414 coap_pdu_t packet; /* try to convince the compiler to word-align this structure */
415 char buf[COAP_MAX_PACKET_SIZE];
416} coap_packetbuf_t;
417
418MEMB(string_storage, struct coap_stringbuf_t, COAP_MAX_STRINGS);
419MEMB(packet_storage, coap_packetbuf_t, COAP_MAX_PACKETS);
420MEMB(session_storage, coap_session_t, COAP_MAX_SESSIONS);
421MEMB(node_storage, coap_queue_t, COAP_PDU_MAXCNT);
422MEMB(pdu_storage, coap_pdu_t, COAP_PDU_MAXCNT);
423MEMB(pdu_buf_storage, coap_packetbuf_t, COAP_PDU_MAXCNT);
424MEMB(resource_storage, coap_resource_t, COAP_MAX_RESOURCES);
425MEMB(attribute_storage, coap_attr_t, COAP_MAX_ATTRIBUTES);
426MEMB(cache_key_storage, coap_cache_key_t, COAP_MAX_CACHE_KEYS);
427MEMB(cache_entry_storage, coap_cache_entry_t, COAP_MAX_CACHE_ENTRIES);
428MEMB(lg_xmit_storage, coap_lg_xmit_t, COAP_MAX_LG_XMIT);
429MEMB(lg_crcv_storage, coap_lg_crcv_t, COAP_MAX_LG_CRCV);
430MEMB(lg_srcv_storage, coap_lg_srcv_t, COAP_MAX_LG_SRCV);
431
432static struct memb *
433get_container(coap_memory_tag_t type) {
434 switch(type) {
435 case COAP_PACKET: return &packet_storage;
436 case COAP_NODE: return &node_storage;
437 case COAP_SESSION: return &session_storage;
438 case COAP_PDU: return &pdu_storage;
439 case COAP_PDU_BUF: return &pdu_buf_storage;
440 case COAP_RESOURCE: return &resource_storage;
441 case COAP_RESOURCEATTR: return &attribute_storage;
442 case COAP_CACHE_KEY: return &cache_key_storage;
443 case COAP_CACHE_ENTRY: return &cache_entry_storage;
444 case COAP_LG_XMIT: return &lg_xmit_storage;
445 case COAP_LG_CRCV: return &lg_crcv_storage;
446 case COAP_LG_SRCV: return &lg_srcv_storage;
447 default:
448 return &string_storage;
449 }
450}
451
452void
453coap_memory_init(void) {
454 memb_init(&string_storage);
455 memb_init(&packet_storage);
456 memb_init(&node_storage);
457 memb_init(&session_storage);
458 memb_init(&pdu_storage);
459 memb_init(&pdu_buf_storage);
460 memb_init(&resource_storage);
461 memb_init(&attribute_storage);
462 memb_init(&cache_key_storage);
463 memb_init(&cache_entry_storage);
464 memb_init(&lg_xmit_storage);
465 memb_init(&lg_crcv_storage);
466 memb_init(&lg_srcv_storage);
467}
468
469void *
470coap_malloc_type(coap_memory_tag_t type, size_t size) {
471 struct memb *container = get_container(type);
472 void *ptr;
473
474 assert(container);
475
476 if (size > container->size) {
478 "coap_malloc_type: Requested memory exceeds maximum object "
479 "size (type %d, size %d, max %d)\n",
480 type, (int)size, container->size);
481 return NULL;
482 }
483
484 ptr = memb_alloc(container);
485 if (!ptr)
487 "coap_malloc_type: Failure (no free blocks) for type %d\n",
488 type);
489 return ptr;
490}
491
492void
493coap_free_type(coap_memory_tag_t type, void *object) {
494 memb_free(get_container(type), object);
495}
496
497void *
498coap_realloc_type(coap_memory_tag_t type, void *p, size_t size) {
499 struct memb *container = get_container(type);
500
501 assert(container);
502 /* The fixed container is all we have to work with */
503 if (p) {
504 if (size > container->size) {
506 "coap_realloc_type: Requested memory exceeds maximum object "
507 "size (type %d, size %zu, max %d)\n",
508 type, size, container->size);
509 return NULL;
510 }
511 if (size == 0) {
512 coap_free_type(type, p);
513 return NULL;
514 }
515 return p;
516 }
517 return coap_malloc_type(type, size);
518}
519#endif /* WITH_CONTIKI */
520
521#endif /* ! HAVE_MALLOC */
522
523#endif /* ! RIOT_VERSION */
Pulls together all the internal only header files.
Defines the application visible session information.
#define coap_log_warn(...)
Definition: coap_debug.h:45
struct coap_string_t coap_string_t
CoAP string data definition.
void coap_memory_init(void)
Initializes libcoap's memory management.
coap_memory_tag_t
Type specifiers for coap_malloc_type().
Definition: mem.h:36
@ COAP_DTLS_SESSION
Definition: mem.h:48
@ COAP_SESSION
Definition: mem.h:49
@ COAP_CACHE_KEY
Definition: mem.h:51
@ COAP_NODE
Definition: mem.h:41
@ COAP_CACHE_ENTRY
Definition: mem.h:52
@ COAP_RESOURCE
Definition: mem.h:46
@ COAP_RESOURCEATTR
Definition: mem.h:47
@ COAP_LG_XMIT
Definition: mem.h:53
@ COAP_ATTRIBUTE_VALUE
Definition: mem.h:39
@ COAP_ENDPOINT
Definition: mem.h:43
@ COAP_CONTEXT
Definition: mem.h:42
@ COAP_OPTLIST
Definition: mem.h:50
@ COAP_PDU
Definition: mem.h:44
@ COAP_LG_CRCV
Definition: mem.h:54
@ COAP_ATTRIBUTE_NAME
Definition: mem.h:38
@ COAP_LG_SRCV
Definition: mem.h:55
@ COAP_PACKET
Definition: mem.h:40
@ COAP_STRING
Definition: mem.h:37
@ COAP_PDU_BUF
Definition: mem.h:45
void * coap_realloc_type(coap_memory_tag_t type, void *p, size_t size)
Reallocates a chunk p of bytes created by coap_malloc_type() or coap_realloc_type() and returns a poi...
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
CoAP context interface.
Pre-defined constants that reflect defaults for CoAP.
Generic resource handling.
Abstraction of attribute associated with a resource.
The CoAP stack's global state is stored in a coap_context_t object.
Abstraction of virtual endpoint that can be attached to coap_context_t.
Structure to hold large body (many blocks) client receive information.
Structure to hold large body (many blocks) server receive information.
Structure to hold large body (many blocks) transmission information.
Representation of chained list of CoAP options to install.
Definition: coap_option.h:326
structure for CoAP PDUs
Queue entry.
Abstraction of resource that can be attached to coap_context_t.
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
CoAP string data definition.
Definition: coap_str.h:38