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