• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* coap_mem.c -- CoAP memory handling
2  *
3  * Copyright (C) 2014--2015,2019--2023 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 
11 /**
12  * @file coap_mem.c
13  * @brief Memory handling functions
14  */
15 
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 <coap3/coap_session.h>
26 #undef PACKAGE_NAME
27 #undef PACKAGE_STRING
28 #undef PACKAGE_TARNAME
29 #undef PACKAGE_VERSION
30 
31 #include "coap3/coap_session.h"
32 #include "coap3/coap_net.h"
33 #include "coap3/coap_pdu.h"
34 #include "coap3/coap_resource.h"
35 
36 /**
37  * The maximum size of a string on platforms that allocate fixed-size
38  * memory blocks.
39  */
40 #ifndef COAP_MAX_STRING_SIZE
41 #define COAP_MAX_STRING_SIZE     (64U)
42 #endif /* COAP_MAX_STRING_SIZE */
43 
44 /**
45  * The maximum number of strings on platforms that allocate
46  * fixed-size memory blocks.
47  */
48 #ifndef COAP_MAX_STRINGS
49 #define COAP_MAX_STRINGS         (16U)
50 #endif /* COAP_MAX_STRINGS */
51 
52 /**
53  * The maximum number of endpoints on platforms that allocate
54  * fixed-size memory blocks.
55  */
56 #ifndef COAP_MAX_ENDPOINTS
57 #define COAP_MAX_ENDPOINTS          (4U)
58 #endif /* COAP_MAX_ENDPOINTS */
59 
60 /**
61  * The maximum number of resources on platforms that allocate
62  * fixed-size memory blocks.
63  */
64 #ifndef COAP_MAX_RESOURCES
65 #define COAP_MAX_RESOURCES          (8U)
66 #endif /* COAP_MAX_RESOURCES */
67 
68 /**
69  * The maximum number of attributes on platforms that allocate
70  * fixed-size memory blocks.  Default is #COAP_MAX_RESOURCES * 4.
71  */
72 #ifndef COAP_MAX_ATTRIBUTES
73 #define COAP_MAX_ATTRIBUTES             \
74   ((COAP_MAX_RESOURCES) * 4U)
75 #endif /* COAP_MAX_ATTRIBUTE_STRINGS */
76 
77 /**
78  * The maximum number of a strings that are used for attribute names
79  * and values on platforms that allocate fixed-size memory blocks.
80  * Default is #COAP_MAX_ATTRIBUTES, i.e. every attribute can have a
81  * dynamic value.
82  */
83 #ifndef COAP_MAX_ATTRIBUTE_STRINGS
84 #define COAP_MAX_ATTRIBUTE_STRINGS    (COAP_MAX_ATTRIBUTES)
85 #endif /* COAP_MAX_ATTRIBUTE_STRINGS */
86 
87 /**
88  * The maximum size of attribute names or values and values on
89  * platforms that allocate fixed-size memory blocks.
90  */
91 #ifndef COAP_MAX_ATTRIBUTE_SIZE
92 #define COAP_MAX_ATTRIBUTE_SIZE       (16U)
93 #endif /* COAP_MAX_ATTRIBUTE_SIZE */
94 
95 /**
96  * The maximum number of processed packets on platforms that allocate
97  * fixed-size memory blocks.
98  */
99 #ifndef COAP_MAX_PACKETS
100 #define COAP_MAX_PACKETS            (4U)
101 #endif /* COAP_MAX_PACKETS */
102 
103 /**
104  * The maximum number of nodes in retransmission queue on platforms
105  * that allocate fixed-size memory blocks. The default value is
106  * #COAP_MAX_ENDPOINTS * #COAP_MAX_PACKETS.
107  */
108 #ifndef COAP_MAX_NODES
109 #define COAP_MAX_NODES               \
110   ((COAP_MAX_ENDPOINTS) * (COAP_MAX_PACKETS))
111 #endif /* COAP_MAX_NODES */
112 
113 /**
114  * The maximum number of CoAP contexts on platforms that allocate
115  * fixed-size memory blocks. Default is 1.
116  */
117 #ifndef COAP_MAX_CONTEXTS
118 #define COAP_MAX_CONTEXTS           (1U)
119 #endif /* COAP_MAX_CONTEXTS */
120 
121 /**
122  * The maximum number of CoAP PDUs processed in parallel on platforms
123  * that allocate fixed-size memory blocks. Default is
124  * #COAP_MAX_ENDPOINTS * 4.
125  */
126 #ifndef COAP_MAX_PDUS
127 #define COAP_MAX_PDUS               ((COAP_MAX_ENDPOINTS) * 4U)
128 #endif /* COAP_MAX_PDUS */
129 
130 /**
131  * The maximum number of DTLS sessions on platforms that allocate
132  * fixed-size memory blocks.
133  */
134 #ifndef COAP_MAX_DTLS_SESSIONS
135 #define COAP_MAX_DTLS_SESSIONS      (2U)
136 #endif /* COAP_MAX_CONTEXTS */
137 
138 /**
139  * The maximum number of DTLS sessions on platforms that allocate
140  * fixed-size memory blocks. Default is #COAP_MAX_ENDPOINTS.
141  */
142 #ifndef COAP_MAX_SESSIONS
143 #define COAP_MAX_SESSIONS           (COAP_MAX_ENDPOINTS)
144 #endif /* COAP_MAX_CONTEXTS */
145 
146 /**
147  * The maximum number of optlist entries on platforms that allocate
148  * fixed-size memory blocks.
149  */
150 #ifndef COAP_MAX_OPTIONS
151 #define COAP_MAX_OPTIONS            (16U)
152 #endif /* COAP_MAX_CONTEXTS */
153 
154 /**
155  * The maximum size of option values on platforms that allocate
156  * fixed-size memory blocks.
157  */
158 #ifndef COAP_MAX_OPTION_SIZE
159 #define COAP_MAX_OPTION_SIZE        (16U)
160 #endif /* COAP_MAX_OPTION_SIZE */
161 
162 /**
163  * The maximum number of cache-key entries that allocate
164  * fixed-size memory blocks.
165  */
166 #ifndef COAP_MAX_CACHE_KEYS
167 #define COAP_MAX_CACHE_KEYS        (2U)
168 #endif /* COAP_MAX_CACHE_KEYS */
169 
170 /**
171  * The maximum number of cache-entry entries that allocate
172  * fixed-size memory blocks.
173  */
174 #ifndef COAP_MAX_CACHE_ENTRIES
175 #define COAP_MAX_CACHE_ENTRIES        (2U)
176 #endif /* COAP_MAX_CACHE_ENTRIES */
177 
178 /**
179  * The maximum number lg_crcv entries that allocate
180  * fixed-size memory blocks.
181  */
182 #ifndef COAP_MAX_LG_CRCVS
183 #if COAP_CLIENT_SUPPORT
184 #define COAP_MAX_LG_CRCVS        (1U)
185 #else /* ! COAP_CLIENT_SUPPORT */
186 #define COAP_MAX_LG_CRCVS        (0U)
187 #endif /* ! COAP_CLIENT_SUPPORT */
188 #endif /* COAP_MAX_LG_CRCVS */
189 
190 /**
191  * The maximum number lg_srcv entries that allocate
192  * fixed-size memory blocks.
193  */
194 #ifndef COAP_MAX_LG_SRCVS
195 #if COAP_SERVER_SUPPORT
196 #define COAP_MAX_LG_SRCVS        (2U)
197 #else /* ! COAP_SERVER_SUPPORT */
198 #define COAP_MAX_LG_SRCVS        (0U)
199 #endif /* ! COAP_SERVER_SUPPORT */
200 #endif /* COAP_MAX_LG_SRCVS */
201 
202 /**
203  * The maximum number lg_xmit entries that allocate
204  * fixed-size memory blocks.
205  */
206 #ifndef COAP_MAX_LG_XMITS
207 #if COAP_SERVER_SUPPORT
208 #define COAP_MAX_LG_XMITS        (2U)
209 #else /* ! COAP_SERVER_SUPPORT */
210 #define COAP_MAX_LG_XMITS        (1U)
211 #endif /* ! COAP_SERVER_SUPPORT */
212 #endif /* COAP_MAX_LG_XMITS */
213 
214 /* The memstr is the storage for holding coap_string_t structure
215  * together with its contents. */
216 union memstr_t {
217   coap_string_t s;
218   char buf[sizeof(coap_string_t) + COAP_MAX_STRING_SIZE];
219 };
220 
221 /* The attrstr is the storage for holding coap_string_t structures to
222  * serve as attribute names or values. As these are typically short,
223  * they are stored in a different arena than generic strings. */
224 union attrstr_t {
225   coap_string_t s;
226   char buf[sizeof(coap_string_t) + COAP_MAX_ATTRIBUTE_SIZE];
227 };
228 
229 static union memstr_t string_storage_data[COAP_MAX_STRINGS];
230 static memarray_t string_storage;
231 
232 #if COAP_SERVER_SUPPORT
233 static coap_endpoint_t endpoint_storage_data[COAP_MAX_ENDPOINTS];
234 static memarray_t endpoint_storage;
235 
236 static union attrstr_t attr_storage_data[COAP_MAX_ATTRIBUTE_STRINGS];
237 static memarray_t attr_storage;
238 
239 static coap_attr_t resattr_storage_data[COAP_MAX_ATTRIBUTES];
240 static memarray_t resattr_storage;
241 #endif /* COAP_SERVER_SUPPORT */
242 
243 static coap_packet_t pkt_storage_data[COAP_MAX_PACKETS];
244 static memarray_t pkt_storage;
245 
246 static coap_queue_t node_storage_data[COAP_MAX_NODES];
247 static memarray_t node_storage;
248 
249 static coap_context_t context_storage_data[COAP_MAX_CONTEXTS];
250 static memarray_t context_storage;
251 
252 static coap_pdu_t pdu_storage_data[COAP_MAX_PDUS];
253 static memarray_t pdu_storage;
254 
255 /* The pdubuf is the storage for holding the (assembled) PDU data in a
256  * coap_pdu_t structure. */
257 union pdubuf_t {
258   void *p; /* try to convince the compiler to word-align this structure  */
259   char buf[COAP_DEFAULT_MAX_PDU_RX_SIZE];
260 };
261 
262 static union pdubuf_t pdubuf_storage_data[COAP_MAX_PDUS];
263 static memarray_t pdubuf_storage;
264 
265 #if COAP_SERVER_SUPPORT
266 static coap_resource_t resource_storage_data[COAP_MAX_RESOURCES];
267 static memarray_t resource_storage;
268 #endif /* COAP_SERVER_SUPPORT */
269 
270 #ifdef COAP_WITH_LIBTINYDTLS
271 #undef PACKAGE_BUGREPORT
272 #include <session.h>
273 static session_t dtls_storage_data[COAP_MAX_DTLS_SESSIONS];
274 static memarray_t dtls_storage;
275 #endif /* COAP_WITH_LIBTINYDTLS */
276 
277 static coap_session_t session_storage_data[COAP_MAX_SESSIONS];
278 static memarray_t session_storage;
279 
280 /* The optbuf_t is the storage for holding optlist nodes. */
281 struct optbuf_t {
282   coap_optlist_t optlist;
283   char optbuf[COAP_MAX_OPTION_SIZE];
284 };
285 static struct optbuf_t option_storage_data[COAP_MAX_OPTIONS];
286 static memarray_t option_storage;
287 
288 #if COAP_SERVER_SUPPORT
289 static coap_cache_key_t cache_key_storage_data[COAP_MAX_CACHE_KEYS];
290 static memarray_t cache_key_storage;
291 
292 static coap_cache_entry_t cache_entry_storage_data[COAP_MAX_CACHE_ENTRIES];
293 static memarray_t cache_entry_storage;
294 #endif /* COAP_SERVER_SUPPORT */
295 
296 #if COAP_CLIENT_SUPPORT
297 static coap_lg_crcv_t cache_lg_crcv_storage_data[COAP_MAX_LG_CRCVS];
298 static memarray_t cache_lg_crcv_storage;
299 #endif /* COAP_CLIENT_SUPPORT */
300 
301 #if COAP_SERVER_SUPPORT
302 static coap_lg_srcv_t cache_lg_srcv_storage_data[COAP_MAX_LG_SRCVS];
303 static memarray_t cache_lg_srcv_storage;
304 
305 static coap_lg_xmit_t cache_lg_xmit_storage_data[COAP_MAX_LG_XMITS];
306 static memarray_t cache_lg_xmit_storage;
307 #endif /* COAP_SERVER_SUPPORT */
308 
309 #define INIT_STORAGE(Storage, Count)  \
310   memarray_init(&(Storage ## _storage), (Storage ## _storage_data), sizeof(Storage ## _storage_data[0]), (Count));
311 
312 #define STORAGE_PTR(Storage)  (&(Storage ## _storage))
313 
314 void
coap_memory_init(void)315 coap_memory_init(void) {
316   INIT_STORAGE(string, COAP_MAX_STRINGS);
317 #if COAP_SERVER_SUPPORT
318   INIT_STORAGE(endpoint, COAP_MAX_ENDPOINTS);
319   INIT_STORAGE(attr, COAP_MAX_ATTRIBUTE_STRINGS);
320 #endif /* COAP_SERVER_SUPPORT */
321   INIT_STORAGE(pkt, COAP_MAX_PACKETS);
322   INIT_STORAGE(node, COAP_MAX_NODES);
323   INIT_STORAGE(context, COAP_MAX_CONTEXTS);
324   INIT_STORAGE(pdu, COAP_MAX_PDUS);
325   INIT_STORAGE(pdubuf, COAP_MAX_PDUS);
326 #if COAP_SERVER_SUPPORT
327   INIT_STORAGE(resource, COAP_MAX_RESOURCES);
328   INIT_STORAGE(resattr, COAP_MAX_ATTRIBUTES);
329 #endif /* COAP_SERVER_SUPPORT */
330 #ifdef COAP_WITH_LIBTINYDTLS
331   INIT_STORAGE(dtls, COAP_MAX_DTLS_SESSIONS);
332 #endif
333   INIT_STORAGE(session, COAP_MAX_SESSIONS);
334   INIT_STORAGE(option, COAP_MAX_OPTIONS);
335 #if COAP_SERVER_SUPPORT
336   INIT_STORAGE(cache_key, COAP_MAX_CACHE_KEYS);
337   INIT_STORAGE(cache_entry, COAP_MAX_CACHE_ENTRIES);
338 #endif /* COAP_SERVER_SUPPORT */
339 #if COAP_CLIENT_SUPPORT
340   INIT_STORAGE(cache_lg_crcv, COAP_MAX_LG_CRCVS);
341 #endif /* COAP_SERVER_SUPPORT */
342 #if COAP_SERVER_SUPPORT
343   INIT_STORAGE(cache_lg_srcv, COAP_MAX_LG_SRCVS);
344   INIT_STORAGE(cache_lg_xmit, COAP_MAX_LG_XMITS);
345 #endif /* COAP_SERVER_SUPPORT */
346 }
347 
348 static memarray_t *
get_container(coap_memory_tag_t type)349 get_container(coap_memory_tag_t type) {
350   switch (type) {
351 #if COAP_SERVER_SUPPORT
352   case COAP_ATTRIBUTE_NAME:
353   /* fall through */
354   case COAP_ATTRIBUTE_VALUE:
355     return &attr_storage;
356 #endif /* COAP_SERVER_SUPPORT */
357   case COAP_PACKET:
358     return &pkt_storage;
359   case COAP_NODE:
360     return &node_storage;
361   case COAP_CONTEXT:
362     return STORAGE_PTR(context);
363 #if COAP_SERVER_SUPPORT
364   case COAP_ENDPOINT:
365     return &endpoint_storage;
366 #endif /* COAP_SERVER_SUPPORT */
367   case COAP_PDU:
368     return &pdu_storage;
369   case COAP_PDU_BUF:
370     return &pdubuf_storage;
371 #if COAP_SERVER_SUPPORT
372   case COAP_RESOURCE:
373     return &resource_storage;
374   case COAP_RESOURCEATTR:
375     return &resattr_storage;
376 #endif /* COAP_SERVER_SUPPORT */
377 #ifdef COAP_WITH_LIBTINYDTLS
378   case COAP_DTLS_SESSION:
379     return &dtls_storage;
380 #endif
381   case COAP_SESSION:
382     return &session_storage;
383   case COAP_OPTLIST:
384     return &option_storage;
385 #if COAP_SERVER_SUPPORT
386   case COAP_CACHE_KEY:
387     return &cache_key_storage;
388   case COAP_CACHE_ENTRY:
389     return &cache_entry_storage;
390 #endif /* COAP_SERVER_SUPPORT */
391 #if COAP_CLIENT_SUPPORT
392   case COAP_LG_CRCV:
393     return &cache_lg_crcv_storage;
394 #endif /* COAP_CLIENT_SUPPORT */
395 #if COAP_SERVER_SUPPORT
396   case COAP_LG_SRCV:
397     return &cache_lg_srcv_storage;
398   case COAP_LG_XMIT:
399     return &cache_lg_xmit_storage;
400 #endif /* COAP_SERVER_SUPPORT */
401   case COAP_STRING:
402   /* fall through */
403   default:
404     return &string_storage;
405   }
406 }
407 
408 void *
coap_malloc_type(coap_memory_tag_t type,size_t size)409 coap_malloc_type(coap_memory_tag_t type, size_t size) {
410   memarray_t *container = get_container(type);
411   void *ptr;
412   assert(container);
413 
414   if (size > container->size) {
415     coap_log_warn("coap_malloc_type: Requested memory exceeds maximum object "
416                   "size (type %d, size %zu, max %d)\n",
417                   type, size, container->size);
418     return NULL;
419   }
420 
421   ptr = memarray_alloc(container);
422   if (!ptr)
423     coap_log_warn("coap_malloc_type: Failure (no free blocks) for type %d\n",
424                   type);
425   return ptr;
426 }
427 
428 void
coap_free_type(coap_memory_tag_t type,void * object)429 coap_free_type(coap_memory_tag_t type, void *object) {
430   if (object != NULL)
431     memarray_free(get_container(type), object);
432 }
433 
434 void *
coap_realloc_type(coap_memory_tag_t type,void * p,size_t size)435 coap_realloc_type(coap_memory_tag_t type, void *p, size_t size) {
436   memarray_t *container = get_container(type);
437 
438   assert(container);
439   /* The fixed container is all we have to work with */
440   if (p) {
441     if (size > container->size) {
442       coap_log_warn("coap_realloc_type: Requested memory exceeds maximum object "
443                     "size (type %d, size %zu, max %d)\n",
444                     type, size, container->size);
445       return NULL;
446     }
447     if (size == 0) {
448       coap_free_type(type, p);
449       return NULL;
450     }
451     return p;
452   }
453   return coap_malloc_type(type, size);
454 }
455 #else /* ! RIOT_VERSION */
456 
457 #if defined(HAVE_MALLOC) || defined(__MINGW32__)
458 #include <stdlib.h>
459 
460 void
coap_memory_init(void)461 coap_memory_init(void) {
462 }
463 
464 void *
coap_malloc_type(coap_memory_tag_t type,size_t size)465 coap_malloc_type(coap_memory_tag_t type, size_t size) {
466   (void)type;
467   return malloc(size);
468 }
469 
470 void *
coap_realloc_type(coap_memory_tag_t type,void * p,size_t size)471 coap_realloc_type(coap_memory_tag_t type, void *p, size_t size) {
472   (void)type;
473   return realloc(p, size);
474 }
475 
476 void
coap_free_type(coap_memory_tag_t type,void * p)477 coap_free_type(coap_memory_tag_t type, void *p) {
478   (void)type;
479   free(p);
480 }
481 
482 #else /* ! HAVE_MALLOC  && !__MINGW32__ */
483 
484 #ifdef WITH_CONTIKI
485 #include "lib/heapmem.h"
486 
487 void
coap_memory_init(void)488 coap_memory_init(void) {
489 }
490 
491 void *
coap_malloc_type(coap_memory_tag_t type,size_t size)492 coap_malloc_type(coap_memory_tag_t type, size_t size) {
493   return heapmem_alloc(size);
494 }
495 
496 void *
coap_realloc_type(coap_memory_tag_t type,void * p,size_t size)497 coap_realloc_type(coap_memory_tag_t type, void *p, size_t size) {
498   return heapmem_realloc(p, size);
499 }
500 
501 void
coap_free_type(coap_memory_tag_t type,void * ptr)502 coap_free_type(coap_memory_tag_t type, void *ptr) {
503   heapmem_free(ptr);
504 }
505 #endif /* WITH_CONTIKI */
506 
507 #endif /* ! HAVE_MALLOC */
508 
509 #endif /* ! RIOT_VERSION */
510