Loading...
Searching...
No Matches
coap_async.c
Go to the documentation of this file.
/* coap_async.c -- state management for asynchronous messages
*
* Copyright (C) 2010,2011,2021-2023 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 COAP_ASYNC_SUPPORT
#include <stdio.h>
/* utlist-style macros for searching pairs in linked lists */
#define SEARCH_PAIR(head,out,field1,val1,field2,val2,field3,val3) \
SEARCH_PAIR3(head,out,field1,val1,field2,val2,field3,val3,next)
#define SEARCH_PAIR3(head,out,field1,val1,field2,val2,field3,val3,next) \
do { \
LL_FOREACH2(head,out,next) { \
if ((out)->field1 == (val1) && (out)->field2 == (val2) && \
((val2) == 0 || memcmp((out)->field3, (val3), (val2)) == 0)) break; \
} \
} while(0)
int
coap_async_is_supported(void) {
return 1;
}
coap_async_t *
coap_register_async(coap_session_t *session,
const coap_pdu_t *request, coap_tick_t delay) {
coap_async_t *s;
size_t len;
const uint8_t *data;
if (!COAP_PDU_IS_REQUEST(request))
return NULL;
SEARCH_PAIR(session->context->async_state, s,
session, session,
pdu->actual_token.length, request->actual_token.length,
pdu->actual_token.s, request->actual_token.s);
if (s != NULL) {
size_t i;
char outbuf[2*8 + 1];
size_t outbuflen;
outbuf[0] = '\000';
for (i = 0; i < request->actual_token.length; i++) {
/* Output maybe truncated */
outbuflen = strlen(outbuf);
snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
"%02x", request->token[i]);
}
coap_log_debug("asynchronous state for token '%s' already registered\n", outbuf);
return NULL;
}
/* store information for handling the asynchronous task */
s = (coap_async_t *)coap_malloc_type(COAP_STRING, sizeof(coap_async_t));
if (!s) {
coap_log_crit("coap_register_async: insufficient memory\n");
return NULL;
}
memset(s, 0, sizeof(coap_async_t));
LL_PREPEND(session->context->async_state, s);
/* Note that this generates a new MID */
s->pdu = coap_pdu_duplicate(request, session, request->actual_token.length,
request->actual_token.s, NULL);
if (s->pdu == NULL) {
coap_free_async(session, s);
coap_log_crit("coap_register_async: insufficient memory\n");
return NULL;
}
if (coap_get_data(request, &len, &data)) {
coap_add_data(s->pdu, len, data);
}
s->session = coap_session_reference(session);
coap_async_set_delay(s, delay);
return s;
}
void
coap_async_trigger(coap_async_t *async) {
assert(async != NULL);
coap_ticks(&async->delay);
coap_log_debug(" %s: Async request triggered\n",
coap_session_str(async->session));
#ifdef COAP_EPOLL_SUPPORT
coap_update_epoll_timer(async->session->context, 0);
#endif /* COAP_EPOLL_SUPPORT */
}
void
coap_async_set_delay(coap_async_t *async, coap_tick_t delay) {
coap_tick_t now;
assert(async != NULL);
coap_ticks(&now);
if (delay) {
async->delay = now + delay;
#ifdef COAP_EPOLL_SUPPORT
coap_update_epoll_timer(async->session->context, delay);
#endif /* COAP_EPOLL_SUPPORT */
coap_log_debug(" %s: Async request delayed for %u.%03u secs\n",
coap_session_str(async->session),
(unsigned int)(delay / COAP_TICKS_PER_SECOND),
(unsigned int)((delay % COAP_TICKS_PER_SECOND) *
1000 / COAP_TICKS_PER_SECOND));
} else {
async->delay = 0;
coap_log_debug(" %s: Async request indefinately delayed\n",
coap_session_str(async->session));
}
}
coap_async_t *
coap_find_async(coap_session_t *session, coap_bin_const_t token) {
coap_async_t *tmp;
SEARCH_PAIR(session->context->async_state, tmp,
session, session,
pdu->actual_token.length, token.length,
pdu->actual_token.s, token.s);
return tmp;
}
static void
coap_free_async_sub(coap_context_t *context, coap_async_t *s) {
if (s) {
LL_DELETE(context->async_state,s);
if (s->session) {
coap_session_release(s->session);
}
if (s->pdu) {
coap_delete_pdu(s->pdu);
s->pdu = NULL;
}
coap_free_type(COAP_STRING, s);
}
}
void
coap_free_async(coap_session_t *session, coap_async_t *s) {
coap_free_async_sub(session->context, s);
}
void
coap_delete_all_async(coap_context_t *context) {
coap_async_t *astate, *tmp;
LL_FOREACH_SAFE(context->async_state, astate, tmp) {
coap_free_async_sub(context, astate);
}
context->async_state = NULL;
}
void
coap_async_set_app_data(coap_async_t *async, void *app_data) {
async->appdata = app_data;
}
void *
coap_async_get_app_data(const coap_async_t *async) {
return async->appdata;
}
#else /* ! COAP_ASYNC_SUPPORT */
int
coap_async_is_supported(void) {
return 0;
}
coap_async_t *
coap_register_async(coap_session_t *session,
const coap_pdu_t *request,
coap_tick_t delay) {
(void)session;
(void)request;
(void)delay;
return NULL;
}
void
coap_async_set_delay(coap_async_t *async, coap_tick_t delay) {
(void)async;
(void)delay;
}
void
coap_free_async(coap_session_t *session, coap_async_t *async) {
(void)session;
(void)async;
}
coap_async_t *
coap_find_async(coap_session_t *session,
coap_bin_const_t token) {
(void)session;
(void)token;
return NULL;
}
void
coap_async_set_app_data(coap_async_t *async, void *app_data) {
(void)async;
(void)app_data;
}
void *
coap_async_get_app_data(const coap_async_t *async) {
(void)async;
return NULL;
}
#endif /* ! COAP_ASYNC_SUPPORT */
coap_async_t
struct coap_async_t coap_async_t
Async Entry information.
Definition coap_forward_decls.h:43
coap_internal.h
Pulls together all the internal only header files.
coap_update_epoll_timer
void coap_update_epoll_timer(coap_context_t *context, coap_tick_t delay)
Update the epoll timer fd as to when it is to trigger.
COAP_STRING
@ COAP_STRING
Definition coap_mem.h:38
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_free_type
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
coap_tick_t
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:144
COAP_TICKS_PER_SECOND
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition coap_time.h:159
coap_free_async
void coap_free_async(coap_session_t *session, coap_async_t *async)
Releases the memory that was allocated by coap_register_async() for the object async.
Definition coap_async.c:211
coap_async_trigger
void coap_async_trigger(coap_async_t *async)
Trigger the registered async.
coap_register_async
coap_async_t * coap_register_async(coap_session_t *session, const coap_pdu_t *request, coap_tick_t delay)
Allocates a new coap_async_t object and fills its fields according to the given request.
Definition coap_async.c:195
coap_async_set_delay
void coap_async_set_delay(coap_async_t *async, coap_tick_t delay)
Update the delay timeout, so changing when the registered async triggers.
Definition coap_async.c:205
coap_async_get_app_data
void * coap_async_get_app_data(const coap_async_t *async)
Gets the application data pointer held in async.
Definition coap_async.c:231
coap_find_async
coap_async_t * coap_find_async(coap_session_t *session, coap_bin_const_t token)
Retrieves the object identified by token from the list of asynchronous transactions that are register...
Definition coap_async.c:217
coap_async_set_app_data
void coap_async_set_app_data(coap_async_t *async, void *app_data)
Set the application data pointer held in async.
Definition coap_async.c:225
coap_async_is_supported
int coap_async_is_supported(void)
Returns 1 if libcoap was built with separate messages enabled, 0 otherwise.
Definition coap_async.c:190
coap_ticks
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
coap_log_debug
#define coap_log_debug(...)
Definition coap_debug.h:120
coap_session_str
const char * coap_session_str(const coap_session_t *session)
Get session description.
Definition coap_session.c:1882
coap_log_crit
#define coap_log_crit(...)
Definition coap_debug.h:90
COAP_PDU_IS_REQUEST
#define COAP_PDU_IS_REQUEST(pdu)
Definition coap_pdu_internal.h:90
coap_delete_pdu
void coap_delete_pdu(coap_pdu_t *pdu)
Dispose of an CoAP PDU and frees associated storage.
Definition coap_pdu.c:163
coap_get_data
int coap_get_data(const coap_pdu_t *pdu, size_t *len, const uint8_t **data)
Retrieves the length and data pointer of specified PDU.
Definition coap_pdu.c:797
coap_pdu_duplicate
coap_pdu_t * coap_pdu_duplicate(const coap_pdu_t *old_pdu, coap_session_t *session, size_t token_length, const uint8_t *token, coap_opt_filter_t *drop_options)
Duplicate an existing PDU.
Definition coap_pdu.c:179
coap_add_data
int coap_add_data(coap_pdu_t *pdu, size_t len, const uint8_t *data)
Adds given data to the pdu that is passed as first parameter.
Definition coap_pdu.c:766
coap_session_release
void coap_session_release(coap_session_t *session)
Decrement reference counter on a session.
Definition coap_session.c:354
coap_session_reference
coap_session_t * coap_session_reference(coap_session_t *session)
Increment reference counter on a session.
Definition coap_session.c:348
coap_bin_const_t
CoAP binary data definition with const data.
Definition coap_str.h:64
coap_bin_const_t::length
size_t length
length of binary data
Definition coap_str.h:65
coap_bin_const_t::s
const uint8_t * s
read-only binary data
Definition coap_str.h:66
coap_context_t
The CoAP stack's global state is stored in a coap_context_t object.
Definition coap_net_internal.h:49
coap_pdu_t
structure for CoAP PDUs
Definition coap_pdu_internal.h:119
coap_pdu_t::token
uint8_t * token
first byte of token (or extended length bytes prefix), if any, or options
Definition coap_pdu_internal.h:139
coap_pdu_t::actual_token
coap_bin_const_t actual_token
Actual token in pdu.
Definition coap_pdu_internal.h:132
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:68
coap_session_t::context
coap_context_t * context
session's context
Definition coap_session_internal.h:86