mem.c
Go to the documentation of this file.
/* mem.c -- CoAP memory handling
*
* Copyright (C) 2014--2015,2019--2020 Olaf Bergmann <bergmann@tzi.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*
* This file is part of the CoAP library libcoap. Please see
* README for terms of use.
*/
#include "coap3/coap_internal.h"
#if defined(RIOT_VERSION) && defined(MODULE_MEMARRAY)
#include <memarray.h>
#undef PACKAGE_NAME
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
#undef PACKAGE_VERSION
#include <session.h>
#undef PACKAGE_NAME
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
#undef PACKAGE_VERSION
#include "coap_session.h"
#include "net.h"
#include "pdu.h"
#include "resource.h"
#ifndef COAP_MAX_STRING_SIZE
#define COAP_MAX_STRING_SIZE (64U)
#endif /* COAP_MAX_STRING_SIZE */
#ifndef COAP_MAX_STRINGS
#define COAP_MAX_STRINGS (16U)
#endif /* COAP_MAX_STRINGS */
#ifndef COAP_MAX_ENDPOINTS
#define COAP_MAX_ENDPOINTS (4U)
#endif /* COAP_MAX_ENDPOINTS */
#ifndef COAP_MAX_RESOURCES
#define COAP_MAX_RESOURCES (8U)
#endif /* COAP_MAX_RESOURCES */
#ifndef COAP_MAX_ATTRIBUTES
#define COAP_MAX_ATTRIBUTES \
((COAP_MAX_RESOURCES) * 4U)
#endif /* COAP_MAX_ATTRIBUTE_STRINGS */
#ifndef COAP_MAX_ATTRIBUTE_STRINGS
#define COAP_MAX_ATTRIBUTE_STRINGS (COAP_MAX_ATTRIBUTES)
#endif /* COAP_MAX_ATTRIBUTE_STRINGS */
#ifndef COAP_MAX_ATTRIBUTE_SIZE
#define COAP_MAX_ATTRIBUTE_SIZE (16U)
#endif /* COAP_MAX_ATTRIBUTE_SIZE */
#ifndef COAP_MAX_PACKETS
#define COAP_MAX_PACKETS (4U)
#endif /* COAP_MAX_PACKETS */
#ifndef COAP_MAX_NODES
#define COAP_MAX_NODES \
((COAP_MAX_ENDPOINTS) * (COAP_MAX_PACKETS))
#endif /* COAP_MAX_NODES */
#ifndef COAP_MAX_CONTEXTS
#define COAP_MAX_CONTEXTS (1U)
#endif /* COAP_MAX_CONTEXTS */
#ifndef COAP_MAX_PDUS
#define COAP_MAX_PDUS ((COAP_MAX_ENDPOINTS) * 4U)
#endif /* COAP_MAX_PDUS */
#ifndef COAP_MAX_DTLS_SESSIONS
#define COAP_MAX_DTLS_SESSIONS (2U)
#endif /* COAP_MAX_CONTEXTS */
#ifndef COAP_MAX_SESSIONS
#define COAP_MAX_SESSIONS (COAP_MAX_ENDPOINTS)
#endif /* COAP_MAX_CONTEXTS */
#ifndef COAP_MAX_OPTIONS
#define COAP_MAX_OPTIONS (16U)
#endif /* COAP_MAX_CONTEXTS */
#ifndef COAP_MAX_OPTION_SIZE
#define COAP_MAX_OPTION_SIZE (16U)
#endif /* COAP_MAX_OPTION_SIZE */
#ifndef COAP_MAX_CACHE_KEYS
#define COAP_MAX_CACHE_KEYS (2U)
#endif /* COAP_MAX_CACHE_KEYS */
#ifndef COAP_MAX_CACHE_ENTRIES
#define COAP_MAX_CACHE_ENTRIES (2U)
#endif /* COAP_MAX_CACHE_ENTRIES */
/* The memstr is the storage for holding coap_string_t structure
* together with its contents. */
union memstr_t {
coap_string_t s;
char buf[sizeof(coap_string_t) + COAP_MAX_STRING_SIZE];
};
/* The attrstr is the storage for holding coap_string_t structures to
* serve as attribute names or values. As these are typically short,
* they are stored in a different arena than generic strings. */
union attrstr_t {
coap_string_t s;
char buf[sizeof(coap_string_t) + COAP_MAX_ATTRIBUTE_SIZE];
};
static union memstr_t string_storage_data[COAP_MAX_STRINGS];
static memarray_t string_storage;
static coap_endpoint_t endpoint_storage_data[COAP_MAX_ENDPOINTS];
static memarray_t endpoint_storage;
static union attrstr_t attr_storage_data[COAP_MAX_ATTRIBUTE_STRINGS];
static memarray_t attr_storage;
static coap_attr_t resattr_storage_data[COAP_MAX_ATTRIBUTES];
static memarray_t resattr_storage;
static coap_packet_t pkt_storage_data[COAP_MAX_PACKETS];
static memarray_t pkt_storage;
static coap_queue_t node_storage_data[COAP_MAX_NODES];
static memarray_t node_storage;
static coap_context_t context_storage_data[COAP_MAX_CONTEXTS];
static memarray_t context_storage;
static coap_pdu_t pdu_storage_data[COAP_MAX_PDUS];
static memarray_t pdu_storage;
/* The pdubuf is the storage for holding the (assembled) PDU data in a
* coap_pdu_t structure. */
union pdubuf_t {
void *p; /* try to convince the compiler to word-align this structure */
char buf[COAP_DEFAULT_MAX_PDU_RX_SIZE];
};
static union pdubuf_t pdubuf_storage_data[COAP_MAX_PDUS];
static memarray_t pdubuf_storage;
static coap_resource_t resource_storage_data[COAP_MAX_RESOURCES];
static memarray_t resource_storage;
#ifdef HAVE_LIBTINYDTLS
static session_t dtls_storage_data[COAP_MAX_DTLS_SESSIONS];
static memarray_t dtls_storage;
#endif /* HAVE_LIBTINYDTLS */
static coap_session_t session_storage_data[COAP_MAX_SESSIONS];
static memarray_t session_storage;
/* The optbuf_t is the storage for holding optlist nodes. */
struct optbuf_t {
coap_optlist_t optlist;
char optbuf[COAP_MAX_OPTION_SIZE];
};
static struct optbuf_t option_storage_data[COAP_MAX_OPTIONS];
static memarray_t option_storage;
static coap_cache_key_t cache_key_storage_data[COAP_MAX_CACHE_KEYS];
static memarray_t cache_key_storage;
static coap_cache_entry_t cache_entry_storage_data[COAP_MAX_CACHE_ENTRIES];
static memarray_t cache_entry_storage;
#define INIT_STORAGE(Storage, Count) \
memarray_init(&(Storage ## _storage), (Storage ## _storage_data), sizeof(Storage ## _storage_data[0]), (Count));
#define STORAGE_PTR(Storage) (&(Storage ## _storage))
void
coap_memory_init(void) {
INIT_STORAGE(string, COAP_MAX_STRINGS);
INIT_STORAGE(endpoint, COAP_MAX_ENDPOINTS);
INIT_STORAGE(attr, COAP_MAX_ATTRIBUTE_STRINGS);
INIT_STORAGE(pkt, COAP_MAX_PACKETS);
INIT_STORAGE(node, COAP_MAX_NODES);
INIT_STORAGE(context, COAP_MAX_CONTEXTS);
INIT_STORAGE(pdu, COAP_MAX_PDUS);
INIT_STORAGE(pdubuf, COAP_MAX_PDUS);
INIT_STORAGE(resource, COAP_MAX_RESOURCES);
INIT_STORAGE(resattr, COAP_MAX_ATTRIBUTES);
#ifdef HAVE_LIBTINYDTLS
INIT_STORAGE(dtls, COAP_MAX_DTLS_SESSIONS);
#endif
INIT_STORAGE(session, COAP_MAX_SESSIONS);
INIT_STORAGE(option, COAP_MAX_OPTIONS);
INIT_STORAGE(cache_key, COAP_MAX_CACHE_KEYS);
INIT_STORAGE(cache_entry, COAP_MAX_CACHE_ENTRIES);
}
static memarray_t *
get_container(coap_memory_tag_t type) {
switch(type) {
case COAP_ATTRIBUTE_NAME:
/* fall through */
case COAP_ATTRIBUTE_VALUE: return &attr_storage;
case COAP_PACKET: return &pkt_storage;
case COAP_NODE: return &node_storage;
case COAP_CONTEXT: return STORAGE_PTR(context);
case COAP_ENDPOINT: return &endpoint_storage;
case COAP_PDU: return &pdu_storage;
case COAP_PDU_BUF: return &pdubuf_storage;
case COAP_RESOURCE: return &resource_storage;
case COAP_RESOURCEATTR: return &resattr_storage;
#ifdef HAVE_LIBTINYDTLS
case COAP_DTLS_SESSION: return &dtls_storage;
#endif
case COAP_SESSION: return &session_storage;
case COAP_OPTLIST: return &option_storage;
case COAP_CACHE_KEY: return &cache_key_storage;
case COAP_CACHE_ENTRY: return &cache_key_entry;
case COAP_STRING:
/* fall through */
default:
return &string_storage;
}
}
void *
coap_malloc_type(coap_memory_tag_t type, size_t size) {
memarray_t *container = get_container(type);
void *ptr;
assert(container);
if (size > container->size) {
coap_log(LOG_WARNING,
"coap_malloc_type: Requested memory exceeds maximum object "
"size (type %d, size %zu, max %d)\n",
type, size, container->size);
return NULL;
}
ptr = memarray_alloc(container);
if (!ptr)
coap_log(LOG_WARNING,
"coap_malloc_type: Failure (no free blocks) for type %d\n",
type);
return ptr;
}
void
coap_free_type(coap_memory_tag_t type, void *object) {
if (object != NULL)
memarray_free(get_container(type), object);
}
#else /* ! RIOT_VERSION */
#ifdef HAVE_MALLOC
#include <stdlib.h>
void
coap_memory_init(void) {
}
void *
coap_malloc_type(coap_memory_tag_t type, size_t size) {
(void)type;
return malloc(size);
}
void *
coap_realloc_type(coap_memory_tag_t type, void* p, size_t size) {
(void)type;
return realloc(p, size);
}
void
coap_free_type(coap_memory_tag_t type, void *p) {
(void)type;
free(p);
}
#else /* ! HAVE_MALLOC */
#ifdef WITH_CONTIKI
#ifndef COAP_MAX_STRING_SIZE
#define COAP_MAX_STRING_SIZE 64
#endif /* COAP_MAX_STRING_SIZE */
#ifndef COAP_MAX_STRINGS
#define COAP_MAX_STRINGS 10
#endif /* COAP_MAX_STRINGS */
struct coap_stringbuf_t {
char data[COAP_MAX_STRING_SIZE];
};
#define COAP_MAX_PACKET_SIZE (sizeof(coap_packet_t) + COAP_RXBUFFER_SIZE)
#ifndef COAP_MAX_PACKETS
#define COAP_MAX_PACKETS 2
#endif /* COAP_MAX_PACKETS */
typedef union {
coap_pdu_t packet; /* try to convince the compiler to word-align this structure */
char buf[COAP_MAX_PACKET_SIZE];
} coap_packetbuf_t;
MEMB(string_storage, struct coap_stringbuf_t, COAP_MAX_STRINGS);
MEMB(packet_storage, coap_packetbuf_t, COAP_MAX_PACKETS);
MEMB(session_storage, coap_session_t, COAP_MAX_SESSIONS);
MEMB(node_storage, coap_queue_t, COAP_PDU_MAXCNT);
MEMB(pdu_storage, coap_pdu_t, COAP_PDU_MAXCNT);
MEMB(pdu_buf_storage, coap_packetbuf_t, COAP_PDU_MAXCNT);
MEMB(resource_storage, coap_resource_t, COAP_MAX_RESOURCES);
MEMB(attribute_storage, coap_attr_t, COAP_MAX_ATTRIBUTES);
MEMB(cache_key_storage, coap_cache_key_t, COAP_MAX_CACHE_KEYS);
MEMB(cache_entry_storage, coap_cache_entry_t, COAP_MAX_CACHE_ENTRIES);
MEMB(lg_xmit_storage, coap_lg_xmit_t, COAP_MAX_LG_XMIT);
MEMB(lg_crcv_storage, coap_lg_crcv_t, COAP_MAX_LG_CRCV);
MEMB(lg_srcv_storage, coap_lg_srcv_t, COAP_MAX_LG_SRCV);
static struct memb *
get_container(coap_memory_tag_t type) {
switch(type) {
case COAP_PACKET: return &packet_storage;
case COAP_NODE: return &node_storage;
case COAP_SESSION: return &session_storage;
case COAP_PDU: return &pdu_storage;
case COAP_PDU_BUF: return &pdu_buf_storage;
case COAP_RESOURCE: return &resource_storage;
case COAP_RESOURCEATTR: return &attribute_storage;
case COAP_CACHE_KEY: return &cache_key_storage;
case COAP_CACHE_ENTRY: return &cache_entry_storage;
case COAP_LG_XMIT: return &lg_xmit_storage;
case COAP_LG_CRCV: return &lg_crcv_storage;
case COAP_LG_SRCV: return &lg_srcv_storage;
default:
return &string_storage;
}
}
void
coap_memory_init(void) {
memb_init(&string_storage);
memb_init(&packet_storage);
memb_init(&node_storage);
memb_init(&session_storage);
memb_init(&pdu_storage);
memb_init(&pdu_buf_storage);
memb_init(&resource_storage);
memb_init(&attribute_storage);
memb_init(&cache_key_storage);
memb_init(&cache_entry_storage);
memb_init(&lg_xmit_storage);
memb_init(&lg_crcv_storage);
memb_init(&lg_srcv_storage);
}
void *
coap_malloc_type(coap_memory_tag_t type, size_t size) {
struct memb *container = get_container(type);
void *ptr;
assert(container);
if (size > container->size) {
coap_log(LOG_WARNING,
"coap_malloc_type: Requested memory exceeds maximum object "
"size (type %d, size %d, max %d)\n",
type, (int)size, container->size);
return NULL;
}
ptr = memb_alloc(container);
if (!ptr)
coap_log(LOG_WARNING,
"coap_malloc_type: Failure (no free blocks) for type %d\n",
type);
return ptr;
}
void
coap_free_type(coap_memory_tag_t type, void *object) {
memb_free(get_container(type), object);
}
#endif /* WITH_CONTIKI */
#endif /* ! HAVE_MALLOC */
#endif /* ! RIOT_VERSION */
coap_internal.h
Pulls together all the internal only header files.
coap_session.h
Defines the application visible session information.
coap_log
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:152
LOG_WARNING
@ LOG_WARNING
Warning.
Definition: coap_debug.h:56
COAP_DEFAULT_MAX_PDU_RX_SIZE
#define COAP_DEFAULT_MAX_PDU_RX_SIZE
Definition: coap_pdu_internal.h:60
coap_string_t
struct coap_string_t coap_string_t
CoAP string data definition.
coap_malloc_type
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.
coap_memory_init
void coap_memory_init(void)
Initializes libcoap's memory management.
coap_memory_tag_t
coap_memory_tag_t
Type specifiers for coap_malloc_type().
Definition: mem.h:31
COAP_SESSION
@ COAP_SESSION
Definition: mem.h:46
COAP_CACHE_KEY
@ COAP_CACHE_KEY
Definition: mem.h:48
COAP_NODE
@ COAP_NODE
Definition: mem.h:36
COAP_CACHE_ENTRY
@ COAP_CACHE_ENTRY
Definition: mem.h:49
COAP_RESOURCE
@ COAP_RESOURCE
Definition: mem.h:41
COAP_RESOURCEATTR
@ COAP_RESOURCEATTR
Definition: mem.h:42
COAP_LG_XMIT
@ COAP_LG_XMIT
Definition: mem.h:50
COAP_ATTRIBUTE_VALUE
@ COAP_ATTRIBUTE_VALUE
Definition: mem.h:34
COAP_ENDPOINT
@ COAP_ENDPOINT
Definition: mem.h:38
COAP_CONTEXT
@ COAP_CONTEXT
Definition: mem.h:37
COAP_OPTLIST
@ COAP_OPTLIST
Definition: mem.h:47
COAP_PDU
@ COAP_PDU
Definition: mem.h:39
COAP_LG_CRCV
@ COAP_LG_CRCV
Definition: mem.h:51
COAP_ATTRIBUTE_NAME
@ COAP_ATTRIBUTE_NAME
Definition: mem.h:33
COAP_LG_SRCV
@ COAP_LG_SRCV
Definition: mem.h:52
COAP_PACKET
@ COAP_PACKET
Definition: mem.h:35
COAP_STRING
@ COAP_STRING
Definition: mem.h:32
COAP_PDU_BUF
@ COAP_PDU_BUF
Definition: mem.h:40
coap_realloc_type
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...
coap_free_type
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
net.h
pdu.h
Pre-defined constants that reflect defaults for CoAP.
resource.h
Generic resource handling.
coap_attr_t
Abstraction of attribute associated with a resource.
Definition: coap_resource_internal.h:31
coap_cache_entry_t
Definition: coap_cache_internal.h:38
coap_cache_key_t
Definition: coap_cache_internal.h:34
coap_context_t
The CoAP stack's global state is stored in a coap_context_t object.
Definition: coap_net_internal.h:45
coap_endpoint_t
Abstraction of virtual endpoint that can be attached to coap_context_t.
Definition: coap_session_internal.h:136
coap_lg_crcv_t
Structure to hold large body (many blocks) client receive information.
Definition: coap_block_internal.h:99
coap_lg_srcv_t
Structure to hold large body (many blocks) server receive information.
Definition: coap_block_internal.h:127
coap_lg_xmit_t
Structure to hold large body (many blocks) transmission information.
Definition: coap_block_internal.h:77
coap_optlist_t
Representation of chained list of CoAP options to install.
Definition: option.h:327
coap_packet_t
Definition: coap_io_internal.h:160
coap_pdu_t
structure for CoAP PDUs token, if any, follows the fixed size header, then options until payload mark...
Definition: coap_pdu_internal.h:94
coap_queue_t
Queue entry.
Definition: coap_net_internal.h:31
coap_resource_t
Abstraction of resource that can be attached to coap_context_t.
Definition: coap_resource_internal.h:42
coap_session_t
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
Definition: coap_session_internal.h:48
coap_string_t
CoAP string data definition.
Definition: str.h:32