libcoap 4.3.5rc1
Loading...
Searching...
No Matches
coap_mem.c
Go to the documentation of this file.
1/* coap_mem.c -- CoAP memory handling
2 *
3 * Copyright (C) 2014--2015,2019--2024 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
17
18#ifndef WITH_LWIP
19#if COAP_MEMORY_TYPE_TRACK
20static int track_counts[COAP_MEM_TAG_LAST];
21static int peak_counts[COAP_MEM_TAG_LAST];
22static int fail_counts[COAP_MEM_TAG_LAST];
23#endif /* COAP_MEMORY_TYPE_TRACK */
24#endif /* ! WITH_LWIP */
25
26#if defined(RIOT_VERSION) && defined(MODULE_MEMARRAY)
27#include <memarray.h>
28
29#undef PACKAGE_NAME
30#undef PACKAGE_STRING
31#undef PACKAGE_TARNAME
32#undef PACKAGE_VERSION
33#include <coap3/coap_session.h>
34#undef PACKAGE_NAME
35#undef PACKAGE_STRING
36#undef PACKAGE_TARNAME
37#undef PACKAGE_VERSION
38
39#include "coap3/coap_session.h"
40#include "coap3/coap_net.h"
41#include "coap3/coap_pdu.h"
42#include "coap3/coap_resource.h"
43
48#ifndef COAP_MAX_STRING_SIZE
49#define COAP_MAX_STRING_SIZE (64U)
50#endif /* COAP_MAX_STRING_SIZE */
51
56#ifndef COAP_MAX_STRINGS
57#define COAP_MAX_STRINGS (16U)
58#endif /* COAP_MAX_STRINGS */
59
64#ifndef COAP_MAX_ENDPOINTS
65#if !COAP_DISABLE_TCP
66#define COAP_MAX_ENDPOINTS (4U)
67#else /* COAP_DISABLE_TCP */
68#define COAP_MAX_ENDPOINTS (2U)
69#endif /* COAP_DISABLE_TCP */
70#endif /* COAP_MAX_ENDPOINTS */
71
76#ifndef COAP_MAX_RESOURCES
77#define COAP_MAX_RESOURCES (8U)
78#endif /* COAP_MAX_RESOURCES */
79
84#ifndef COAP_MAX_ATTRIBUTES
85#define COAP_MAX_ATTRIBUTES \
86 ((COAP_MAX_RESOURCES) * 4U)
87#endif /* COAP_MAX_ATTRIBUTE_STRINGS */
88
95#ifndef COAP_MAX_ATTRIBUTE_STRINGS
96#define COAP_MAX_ATTRIBUTE_STRINGS (COAP_MAX_ATTRIBUTES)
97#endif /* COAP_MAX_ATTRIBUTE_STRINGS */
98
103#ifndef COAP_MAX_ATTRIBUTE_SIZE
104#define COAP_MAX_ATTRIBUTE_SIZE (16U)
105#endif /* COAP_MAX_ATTRIBUTE_SIZE */
106
111#ifndef COAP_MAX_PACKETS
112#define COAP_MAX_PACKETS (4U)
113#endif /* COAP_MAX_PACKETS */
114
119#ifndef COAP_MAX_NODES
120#define COAP_MAX_NODES (COAP_MAX_PACKETS)
121#endif /* COAP_MAX_NODES */
122
127#ifndef COAP_MAX_CONTEXTS
128#define COAP_MAX_CONTEXTS (1U)
129#endif /* COAP_MAX_CONTEXTS */
130
135#ifndef COAP_MAX_PDUS
136#define COAP_MAX_PDUS (4U)
137#endif /* COAP_MAX_PDUS */
138
143#ifndef COAP_MAX_DTLS_SESSIONS
144#define COAP_MAX_DTLS_SESSIONS (2U)
145#endif /* COAP_MAX_CONTEXTS */
146
151#ifndef COAP_MAX_SESSIONS
152#define COAP_MAX_SESSIONS (4U)
153#endif /* COAP_MAX_CONTEXTS */
154
159#ifndef COAP_MAX_OPTIONS
160#define COAP_MAX_OPTIONS (16U)
161#endif /* COAP_MAX_CONTEXTS */
162
167#ifndef COAP_MAX_OPTION_SIZE
168#define COAP_MAX_OPTION_SIZE (16U)
169#endif /* COAP_MAX_OPTION_SIZE */
170
175#ifndef COAP_MAX_CACHE_KEYS
176#define COAP_MAX_CACHE_KEYS (2U)
177#endif /* COAP_MAX_CACHE_KEYS */
178
183#ifndef COAP_MAX_CACHE_ENTRIES
184#define COAP_MAX_CACHE_ENTRIES (2U)
185#endif /* COAP_MAX_CACHE_ENTRIES */
186
191#ifndef COAP_MAX_LG_CRCVS
192#if COAP_CLIENT_SUPPORT
193#define COAP_MAX_LG_CRCVS (1U)
194#else /* ! COAP_CLIENT_SUPPORT */
195#define COAP_MAX_LG_CRCVS (0U)
196#endif /* ! COAP_CLIENT_SUPPORT */
197#endif /* COAP_MAX_LG_CRCVS */
198
203#ifndef COAP_MAX_LG_SRCVS
204#if COAP_SERVER_SUPPORT
205#define COAP_MAX_LG_SRCVS (2U)
206#else /* ! COAP_SERVER_SUPPORT */
207#define COAP_MAX_LG_SRCVS (0U)
208#endif /* ! COAP_SERVER_SUPPORT */
209#endif /* COAP_MAX_LG_SRCVS */
210
215#ifndef COAP_MAX_LG_XMITS
216#if COAP_SERVER_SUPPORT
217#define COAP_MAX_LG_XMITS (2U)
218#else /* ! COAP_SERVER_SUPPORT */
219#define COAP_MAX_LG_XMITS (1U)
220#endif /* ! COAP_SERVER_SUPPORT */
221#endif /* COAP_MAX_LG_XMITS */
222
223/* The memstr is the storage for holding coap_string_t structure
224 * together with its contents. */
225union memstr_t {
227 char buf[sizeof(coap_string_t) + COAP_MAX_STRING_SIZE];
228};
229
230/* The attrstr is the storage for holding coap_string_t structures to
231 * serve as attribute names or values. As these are typically short,
232 * they are stored in a different arena than generic strings. */
233union attrstr_t {
235 char buf[sizeof(coap_string_t) + COAP_MAX_ATTRIBUTE_SIZE];
236};
237
238static union memstr_t string_storage_data[COAP_MAX_STRINGS];
239static memarray_t string_storage;
240
241#if COAP_SERVER_SUPPORT
242static coap_endpoint_t endpoint_storage_data[COAP_MAX_ENDPOINTS];
243static memarray_t endpoint_storage;
244
245static union attrstr_t attr_storage_data[COAP_MAX_ATTRIBUTE_STRINGS];
246static memarray_t attr_storage;
247
248static coap_attr_t resattr_storage_data[COAP_MAX_ATTRIBUTES];
249static memarray_t resattr_storage;
250#endif /* COAP_SERVER_SUPPORT */
251
252static coap_packet_t pkt_storage_data[COAP_MAX_PACKETS];
253static memarray_t pkt_storage;
254
255static coap_queue_t node_storage_data[COAP_MAX_NODES];
256static memarray_t node_storage;
257
258static coap_context_t context_storage_data[COAP_MAX_CONTEXTS];
259static memarray_t context_storage;
260
261static coap_pdu_t pdu_storage_data[COAP_MAX_PDUS];
262static memarray_t pdu_storage;
263
264/* The pdubuf is the storage for holding the (assembled) PDU data in a
265 * coap_pdu_t structure. */
266union pdubuf_t {
267 void *p; /* try to convince the compiler to word-align this structure */
268 char buf[COAP_DEFAULT_MAX_PDU_RX_SIZE];
269};
270
271static union pdubuf_t pdubuf_storage_data[COAP_MAX_PDUS];
272static memarray_t pdubuf_storage;
273
274#if COAP_SERVER_SUPPORT
275static coap_resource_t resource_storage_data[COAP_MAX_RESOURCES];
276static memarray_t resource_storage;
277#endif /* COAP_SERVER_SUPPORT */
278
279#ifdef COAP_WITH_LIBTINYDTLS
280#undef PACKAGE_BUGREPORT
281#undef PACKAGE_URL
282#include <session.h>
283static session_t dtls_storage_data[COAP_MAX_DTLS_SESSIONS];
284static memarray_t dtls_storage;
285#endif /* COAP_WITH_LIBTINYDTLS */
286
287static coap_session_t session_storage_data[COAP_MAX_SESSIONS];
288static memarray_t session_storage;
289
290/* The optbuf_t is the storage for holding optlist nodes. */
291struct optbuf_t {
292 coap_optlist_t optlist;
293 char optbuf[COAP_MAX_OPTION_SIZE];
294};
295static struct optbuf_t option_storage_data[COAP_MAX_OPTIONS];
296static memarray_t option_storage;
297
298#if COAP_SERVER_SUPPORT
299static coap_cache_key_t cache_key_storage_data[COAP_MAX_CACHE_KEYS];
300static memarray_t cache_key_storage;
301
302static coap_cache_entry_t cache_entry_storage_data[COAP_MAX_CACHE_ENTRIES];
303static memarray_t cache_entry_storage;
304#endif /* COAP_SERVER_SUPPORT */
305
306#if COAP_CLIENT_SUPPORT
307static coap_lg_crcv_t cache_lg_crcv_storage_data[COAP_MAX_LG_CRCVS];
308static memarray_t cache_lg_crcv_storage;
309#endif /* COAP_CLIENT_SUPPORT */
310
311#if COAP_SERVER_SUPPORT
312static coap_lg_srcv_t cache_lg_srcv_storage_data[COAP_MAX_LG_SRCVS];
313static memarray_t cache_lg_srcv_storage;
314
315static coap_lg_xmit_t cache_lg_xmit_storage_data[COAP_MAX_LG_XMITS];
316static memarray_t cache_lg_xmit_storage;
317#endif /* COAP_SERVER_SUPPORT */
318
319#define INIT_STORAGE(Storage, Count) \
320 memarray_init(&(Storage ## _storage), (Storage ## _storage_data), sizeof(Storage ## _storage_data[0]), (Count));
321
322#define STORAGE_PTR(Storage) (&(Storage ## _storage))
323
324void
325coap_memory_init(void) {
326 INIT_STORAGE(string, COAP_MAX_STRINGS);
327#if COAP_SERVER_SUPPORT
328 INIT_STORAGE(endpoint, COAP_MAX_ENDPOINTS);
329 INIT_STORAGE(attr, COAP_MAX_ATTRIBUTE_STRINGS);
330#endif /* COAP_SERVER_SUPPORT */
331 INIT_STORAGE(pkt, COAP_MAX_PACKETS);
332 INIT_STORAGE(node, COAP_MAX_NODES);
333 INIT_STORAGE(context, COAP_MAX_CONTEXTS);
334 INIT_STORAGE(pdu, COAP_MAX_PDUS);
335 INIT_STORAGE(pdubuf, COAP_MAX_PDUS);
336#if COAP_SERVER_SUPPORT
337 INIT_STORAGE(resource, COAP_MAX_RESOURCES);
338 INIT_STORAGE(resattr, COAP_MAX_ATTRIBUTES);
339#endif /* COAP_SERVER_SUPPORT */
340#ifdef COAP_WITH_LIBTINYDTLS
341 INIT_STORAGE(dtls, COAP_MAX_DTLS_SESSIONS);
342#endif
343 INIT_STORAGE(session, COAP_MAX_SESSIONS);
344 INIT_STORAGE(option, COAP_MAX_OPTIONS);
345#if COAP_SERVER_SUPPORT
346 INIT_STORAGE(cache_key, COAP_MAX_CACHE_KEYS);
347 INIT_STORAGE(cache_entry, COAP_MAX_CACHE_ENTRIES);
348#endif /* COAP_SERVER_SUPPORT */
349#if COAP_CLIENT_SUPPORT
350 INIT_STORAGE(cache_lg_crcv, COAP_MAX_LG_CRCVS);
351#endif /* COAP_SERVER_SUPPORT */
352#if COAP_SERVER_SUPPORT
353 INIT_STORAGE(cache_lg_srcv, COAP_MAX_LG_SRCVS);
354 INIT_STORAGE(cache_lg_xmit, COAP_MAX_LG_XMITS);
355#endif /* COAP_SERVER_SUPPORT */
356}
357
358static memarray_t *
359get_container(coap_memory_tag_t type) {
360 switch (type) {
361#if COAP_SERVER_SUPPORT
363 /* fall through */
365 return &attr_storage;
366#endif /* COAP_SERVER_SUPPORT */
367 case COAP_PACKET:
368 return &pkt_storage;
369 case COAP_NODE:
370 return &node_storage;
371 case COAP_CONTEXT:
372 return STORAGE_PTR(context);
373#if COAP_SERVER_SUPPORT
374 case COAP_ENDPOINT:
375 return &endpoint_storage;
376#endif /* COAP_SERVER_SUPPORT */
377 case COAP_PDU:
378 return &pdu_storage;
379 case COAP_PDU_BUF:
380 return &pdubuf_storage;
381#if COAP_SERVER_SUPPORT
382 case COAP_RESOURCE:
383 return &resource_storage;
385 return &resattr_storage;
386#endif /* COAP_SERVER_SUPPORT */
387#ifdef COAP_WITH_LIBTINYDTLS
389 return &dtls_storage;
390#endif
391 case COAP_SESSION:
392 return &session_storage;
393 case COAP_OPTLIST:
394 return &option_storage;
395#if COAP_SERVER_SUPPORT
396 case COAP_CACHE_KEY:
397 return &cache_key_storage;
398 case COAP_CACHE_ENTRY:
399 return &cache_entry_storage;
400#endif /* COAP_SERVER_SUPPORT */
401#if COAP_CLIENT_SUPPORT
402 case COAP_LG_CRCV:
403 return &cache_lg_crcv_storage;
404#endif /* COAP_CLIENT_SUPPORT */
405#if COAP_SERVER_SUPPORT
406 case COAP_LG_SRCV:
407 return &cache_lg_srcv_storage;
408 case COAP_LG_XMIT:
409 return &cache_lg_xmit_storage;
410#endif /* COAP_SERVER_SUPPORT */
411 case COAP_STRING:
412 /* fall through */
413 default:
414 return &string_storage;
415 }
416}
417
418void *
419coap_malloc_type(coap_memory_tag_t type, size_t size) {
420 memarray_t *container = get_container(type);
421 void *ptr;
422 assert(container);
423
424 if (size > container->size) {
425 coap_log_warn("coap_malloc_type: Requested memory exceeds maximum object "
426 "size (type %d, size %zu, max %zd)\n",
427 type, size, container->size);
428 return NULL;
429 }
430
431 ptr = memarray_alloc(container);
432 if (!ptr)
433 coap_log_warn("coap_malloc_type: Failure (no free blocks) for type %d\n",
434 type);
435#if COAP_MEMORY_TYPE_TRACK
436 assert(type < COAP_MEM_TAG_LAST);
437 if (ptr) {
438 track_counts[type]++;
439 if (track_counts[type] > peak_counts[type])
440 peak_counts[type] = track_counts[type];
441 } else {
442 fail_counts[type]++;
443 }
444#endif /* COAP_MEMORY_TYPE_TRACK */
445 return ptr;
446}
447
448void
449coap_free_type(coap_memory_tag_t type, void *object) {
450#if COAP_MEMORY_TYPE_TRACK
451 assert(type < COAP_MEM_TAG_LAST);
452 if (object)
453 track_counts[type]--;
454#endif /* COAP_MEMORY_TYPE_TRACK */
455 if (object != NULL)
456 memarray_free(get_container(type), object);
457}
458
459void *
460coap_realloc_type(coap_memory_tag_t type, void *p, size_t size) {
461 memarray_t *container = get_container(type);
462
463 assert(container);
464 /* The fixed container is all we have to work with */
465 if (p) {
466 if (size > container->size) {
467 coap_log_warn("coap_realloc_type: Requested memory exceeds maximum object "
468 "size (type %d, size %zu, max %zd)\n",
469 type, size, container->size);
470 return NULL;
471 }
472 if (size == 0) {
473 coap_free_type(type, p);
474 return NULL;
475 }
476 return p;
477 }
478 return coap_malloc_type(type, size);
479
480}
481#else /* ! RIOT_VERSION && ! MODULE_MEMARRAY */
482
483#if defined(HAVE_MALLOC) || defined(__MINGW32__)
484#include <stdlib.h>
485
486void
487coap_memory_init(void) {
488}
489
490void *
491coap_malloc_type(coap_memory_tag_t type, size_t size) {
492 void *ptr;
493
494 (void)type;
495 ptr = malloc(size);
496#if COAP_MEMORY_TYPE_TRACK
497 assert(type < COAP_MEM_TAG_LAST);
498 if (ptr) {
499 track_counts[type]++;
500 if (track_counts[type] > peak_counts[type])
501 peak_counts[type] = track_counts[type];
502 } else {
503 fail_counts[type]++;
504 }
505#endif /* COAP_MEMORY_TYPE_TRACK */
506 return ptr;
507}
508
509void *
510coap_realloc_type(coap_memory_tag_t type, void *p, size_t size) {
511 void *ptr;
512
513 (void)type;
514 ptr = realloc(p, size);
515#if COAP_MEMORY_TYPE_TRACK
516 if (ptr) {
517 assert(type < COAP_MEM_TAG_LAST);
518 if (!p)
519 track_counts[type]++;
520 if (track_counts[type] > peak_counts[type])
521 peak_counts[type] = track_counts[type];
522 } else {
523 fail_counts[type]++;
524 }
525#endif /* COAP_MEMORY_TYPE_TRACK */
526 return ptr;
527}
528
529void
530coap_free_type(coap_memory_tag_t type, void *p) {
531 (void)type;
532#if COAP_MEMORY_TYPE_TRACK
533 assert(type < COAP_MEM_TAG_LAST);
534 if (p)
535 track_counts[type]--;
536#endif /* COAP_MEMORY_TYPE_TRACK */
537 free(p);
538}
539
540#else /* ! HAVE_MALLOC && !__MINGW32__ */
541
542#ifdef WITH_CONTIKI
543#include "lib/heapmem.h"
544
545void
546coap_memory_init(void) {
547}
548
549void *
550coap_malloc_type(coap_memory_tag_t type, size_t size) {
551 void *ptr = heapmem_alloc(size);
552
553#if COAP_MEMORY_TYPE_TRACK
554 assert(type < COAP_MEM_TAG_LAST);
555 if (ptr) {
556 track_counts[type]++;
557 if (track_counts[type] > peak_counts[type])
558 peak_counts[type] = track_counts[type];
559 } else {
560 fail_counts[type]++;
561 }
562#endif /* COAP_MEMORY_TYPE_TRACK */
563 return ptr;
564}
565
566void *
567coap_realloc_type(coap_memory_tag_t type, void *p, size_t size) {
568 void *ptr = heapmem_realloc(p, size);
569#if COAP_MEMORY_TYPE_TRACK
570 if (ptr) {
571 assert(type < COAP_MEM_TAG_LAST);
572 if (!p)
573 track_counts[type]++;
574 if (track_counts[type] > peak_counts[type])
575 peak_counts[type] = track_counts[type];
576 } else {
577 fail_counts[type]++;
578 }
579#endif /* COAP_MEMORY_TYPE_TRACK */
580 return ptr;
581}
582
583void
584coap_free_type(coap_memory_tag_t type, void *ptr) {
585#if COAP_MEMORY_TYPE_TRACK
586 assert(type < COAP_MEM_TAG_LAST);
587 if (ptr)
588 track_counts[type]--;
589#endif /* COAP_MEMORY_TYPE_TRACK */
590 heapmem_free(ptr);
591}
592
593#endif /* WITH_CONTIKI */
594
595#endif /* ! HAVE_MALLOC */
596
597#endif /* ! RIOT_VERSION */
598
599#ifndef WITH_LWIP
600#define MAKE_CASE(n) case n: name = #n; break
601void
603#if COAP_MEMORY_TYPE_TRACK
604 int i;
605
606 coap_log(level, "* Memory type counts\n");
607 for (i = 0; i < COAP_MEM_TAG_LAST; i++) {
608 const char *name = "?";
609
610
611 switch (i) {
642 default:
643 break;
644 }
645 coap_log(level, "* %-20s in-use %3d peak %3d failed %2d\n",
646 name, track_counts[i], peak_counts[i], fail_counts[i]);
647 }
648#else /* COAP_MEMORY_TYPE_TRACK */
649 (void)level;
650#endif /* COAP_MEMORY_TYPE_TRACK */
651}
652#endif /* !WITH_LWIP */
Library specific build wrapper for coap_internal.h.
#define MAKE_CASE(n)
Definition coap_mem.c:600
void coap_dump_memory_type_counts(coap_log_t level)
Dumps the current usage of malloc'd memory types.
Definition coap_mem.c:602
void coap_memory_init(void)
Initializes libcoap's memory management.
coap_memory_tag_t
Type specifiers for coap_malloc_type().
Definition coap_mem.h:37
@ COAP_DTLS_SESSION
Definition coap_mem.h:49
@ COAP_SESSION
Definition coap_mem.h:50
@ COAP_CACHE_KEY
Definition coap_mem.h:52
@ COAP_DIGEST_CTX
Definition coap_mem.h:57
@ COAP_NODE
Definition coap_mem.h:42
@ COAP_OSCORE_COM
Definition coap_mem.h:60
@ COAP_DTLS_CONTEXT
Definition coap_mem.h:59
@ COAP_OSCORE_EX
Definition coap_mem.h:63
@ COAP_CACHE_ENTRY
Definition coap_mem.h:53
@ COAP_RESOURCE
Definition coap_mem.h:47
@ COAP_RESOURCEATTR
Definition coap_mem.h:48
@ COAP_COSE
Definition coap_mem.h:66
@ COAP_LG_XMIT
Definition coap_mem.h:54
@ COAP_ATTRIBUTE_VALUE
Definition coap_mem.h:40
@ COAP_ENDPOINT
Definition coap_mem.h:44
@ COAP_CONTEXT
Definition coap_mem.h:43
@ COAP_OPTLIST
Definition coap_mem.h:51
@ COAP_PDU
Definition coap_mem.h:45
@ COAP_LG_CRCV
Definition coap_mem.h:55
@ COAP_OSCORE_BUF
Definition coap_mem.h:65
@ COAP_MEM_TAG_LAST
Definition coap_mem.h:67
@ COAP_OSCORE_SEN
Definition coap_mem.h:61
@ COAP_OSCORE_REC
Definition coap_mem.h:62
@ COAP_ATTRIBUTE_NAME
Definition coap_mem.h:39
@ COAP_OSCORE_EP
Definition coap_mem.h:64
@ COAP_LG_SRCV
Definition coap_mem.h:56
@ COAP_PACKET
Definition coap_mem.h:41
@ COAP_SUBSCRIPTION
Definition coap_mem.h:58
@ COAP_STRING
Definition coap_mem.h:38
@ COAP_PDU_BUF
Definition coap_mem.h:46
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.
Defines the application visible session information.
coap_log_t
Logging type.
Definition coap_debug.h:50
#define coap_log_warn(...)
Definition coap_debug.h:102
#define coap_log(level,...)
Logging function.
Definition coap_debug.h:284
struct coap_string_t coap_string_t
CoAP string data definition.
Limits the number of subscribers for each resource that this server support.
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.
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