libcoap  4.3.0
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 
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 
36 #ifndef COAP_MAX_STRING_SIZE
37 #define COAP_MAX_STRING_SIZE (64U)
38 #endif /* COAP_MAX_STRING_SIZE */
39 
44 #ifndef COAP_MAX_STRINGS
45 #define COAP_MAX_STRINGS (16U)
46 #endif /* COAP_MAX_STRINGS */
47 
52 #ifndef COAP_MAX_ENDPOINTS
53 #define COAP_MAX_ENDPOINTS (4U)
54 #endif /* COAP_MAX_ENDPOINTS */
55 
60 #ifndef COAP_MAX_RESOURCES
61 #define COAP_MAX_RESOURCES (8U)
62 #endif /* COAP_MAX_RESOURCES */
63 
68 #ifndef COAP_MAX_ATTRIBUTES
69 #define COAP_MAX_ATTRIBUTES \
70  ((COAP_MAX_RESOURCES) * 4U)
71 #endif /* COAP_MAX_ATTRIBUTE_STRINGS */
72 
79 #ifndef COAP_MAX_ATTRIBUTE_STRINGS
80 #define COAP_MAX_ATTRIBUTE_STRINGS (COAP_MAX_ATTRIBUTES)
81 #endif /* COAP_MAX_ATTRIBUTE_STRINGS */
82 
87 #ifndef COAP_MAX_ATTRIBUTE_SIZE
88 #define COAP_MAX_ATTRIBUTE_SIZE (16U)
89 #endif /* COAP_MAX_ATTRIBUTE_SIZE */
90 
95 #ifndef COAP_MAX_PACKETS
96 #define COAP_MAX_PACKETS (4U)
97 #endif /* COAP_MAX_PACKETS */
98 
104 #ifndef COAP_MAX_NODES
105 #define COAP_MAX_NODES \
106  ((COAP_MAX_ENDPOINTS) * (COAP_MAX_PACKETS))
107 #endif /* COAP_MAX_NODES */
108 
113 #ifndef COAP_MAX_CONTEXTS
114 #define COAP_MAX_CONTEXTS (1U)
115 #endif /* COAP_MAX_CONTEXTS */
116 
122 #ifndef COAP_MAX_PDUS
123 #define COAP_MAX_PDUS ((COAP_MAX_ENDPOINTS) * 4U)
124 #endif /* COAP_MAX_PDUS */
125 
130 #ifndef COAP_MAX_DTLS_SESSIONS
131 #define COAP_MAX_DTLS_SESSIONS (2U)
132 #endif /* COAP_MAX_CONTEXTS */
133 
138 #ifndef COAP_MAX_SESSIONS
139 #define COAP_MAX_SESSIONS (COAP_MAX_ENDPOINTS)
140 #endif /* COAP_MAX_CONTEXTS */
141 
146 #ifndef COAP_MAX_OPTIONS
147 #define COAP_MAX_OPTIONS (16U)
148 #endif /* COAP_MAX_CONTEXTS */
149 
154 #ifndef COAP_MAX_OPTION_SIZE
155 #define COAP_MAX_OPTION_SIZE (16U)
156 #endif /* COAP_MAX_OPTION_SIZE */
157 
162 #ifndef COAP_MAX_CACHE_KEYS
163 #define COAP_MAX_CACHE_KEYS (2U)
164 #endif /* COAP_MAX_CACHE_KEYS */
165 
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 */
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
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 *
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 *
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) {
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)
319  "coap_malloc_type: Failure (no free blocks) for type %d\n",
320  type);
321  return ptr;
322 }
323 
324 void
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
335 coap_memory_init(void) {
336 }
337 
338 void *
339 coap_malloc_type(coap_memory_tag_t type, size_t size) {
340  (void)type;
341  return malloc(size);
342 }
343 
344 void *
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
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 
364 #ifndef COAP_MAX_STRING_SIZE
365 #define COAP_MAX_STRING_SIZE 64
366 #endif /* COAP_MAX_STRING_SIZE */
367 
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 *
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
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 *
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) {
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)
460  "coap_malloc_type: Failure (no free blocks) for type %d\n",
461  type);
462  return ptr;
463 }
464 
465 void
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 */
Pulls together all the internal only header files.
Defines the application visible session information.
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:152
@ LOG_WARNING
Warning.
Definition: coap_debug.h:56
#define COAP_DEFAULT_MAX_PDU_RX_SIZE
struct coap_string_t coap_string_t
CoAP string data definition.
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_memory_init(void)
Initializes libcoap's memory management.
coap_memory_tag_t
Type specifiers for coap_malloc_type().
Definition: mem.h:31
@ COAP_SESSION
Definition: mem.h:46
@ COAP_CACHE_KEY
Definition: mem.h:48
@ COAP_NODE
Definition: mem.h:36
@ COAP_CACHE_ENTRY
Definition: mem.h:49
@ COAP_RESOURCE
Definition: mem.h:41
@ COAP_RESOURCEATTR
Definition: mem.h:42
@ COAP_LG_XMIT
Definition: mem.h:50
@ COAP_ATTRIBUTE_VALUE
Definition: mem.h:34
@ COAP_ENDPOINT
Definition: mem.h:38
@ COAP_CONTEXT
Definition: mem.h:37
@ COAP_OPTLIST
Definition: mem.h:47
@ COAP_PDU
Definition: mem.h:39
@ COAP_LG_CRCV
Definition: mem.h:51
@ COAP_ATTRIBUTE_NAME
Definition: mem.h:33
@ COAP_LG_SRCV
Definition: mem.h:52
@ COAP_PACKET
Definition: mem.h:35
@ COAP_STRING
Definition: mem.h:32
@ COAP_PDU_BUF
Definition: mem.h:40
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_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
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: option.h:327
structure for CoAP PDUs token, if any, follows the fixed size header, then options until payload mark...
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: str.h:32