libcoap 4.3.5-develop-4fa3dfa
Loading...
Searching...
No Matches
coap_async.c
Go to the documentation of this file.
1/* coap_async.c -- state management for asynchronous messages
2 *
3 * Copyright (C) 2010,2011,2021-2025 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
17
18#if COAP_ASYNC_SUPPORT
19#include <stdio.h>
20
21/* utlist-style macros for searching pairs in linked lists */
22#define SEARCH_PAIR(head,out,field1,val1,field2,val2,field3,val3) \
23 SEARCH_PAIR3(head,out,field1,val1,field2,val2,field3,val3,next)
24
25#define SEARCH_PAIR3(head,out,field1,val1,field2,val2,field3,val3,next) \
26 do { \
27 LL_FOREACH2(head,out,next) { \
28 if ((out)->field1 == (val1) && (out)->field2 == (val2) && \
29 ((val2) == 0 || memcmp((out)->field3, (val3), (val2)) == 0)) break; \
30 } \
31 } while(0)
32
33int
35 return 1;
36}
37
40 const coap_pdu_t *request, coap_tick_t delay) {
41 coap_async_t *async;
42
43 coap_lock_lock(return NULL);
44 async = coap_register_async_lkd(session, request, delay);
46 return async;
47}
48
50coap_register_async_lkd(coap_session_t *session,
51 const coap_pdu_t *request, coap_tick_t delay) {
52 coap_async_t *s;
53 size_t len;
54 const uint8_t *data;
55
57 if (!COAP_PDU_IS_REQUEST(request))
58 return NULL;
59
60 SEARCH_PAIR(session->context->async_state, s,
61 session, session,
62 pdu->actual_token.length, request->actual_token.length,
63 pdu->actual_token.s, request->actual_token.s);
64
65 if (s != NULL) {
66 size_t i;
67 char outbuf[2*8 + 1];
68 size_t outbuflen;
69
70 outbuf[0] = '\000';
71 for (i = 0; i < request->actual_token.length; i++) {
72 /* Output maybe truncated */
73 outbuflen = strlen(outbuf);
74 snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
75 "%02x", request->token[i]);
76 }
77 coap_log_debug("asynchronous state for token '%s' already registered\n", outbuf);
78 return NULL;
79 }
80
81 /* store information for handling the asynchronous task */
83 if (!s) {
84 coap_log_crit("coap_register_async: insufficient memory\n");
85 return NULL;
86 }
87
88 memset(s, 0, sizeof(coap_async_t));
89 LL_PREPEND(session->context->async_state, s);
90
91 /* Note that this generates a new MID */
92 s->pdu = coap_pdu_duplicate_lkd(request, session, request->actual_token.length,
93 request->actual_token.s, NULL);
94 if (s->pdu == NULL) {
95 coap_free_async_lkd(session, s);
96 coap_log_crit("coap_register_async: insufficient memory\n");
97 return NULL;
98 }
99
100 if (coap_get_data(request, &len, &data)) {
101 coap_add_data(s->pdu, len, data);
102 }
103
104 s->session = coap_session_reference_lkd(session);
105
106 coap_async_set_delay_lkd(s, delay);
107
108 return s;
109}
110
111COAP_API void
113 coap_lock_lock(return);
114 coap_async_trigger_lkd(async);
116}
117
118void
119coap_async_trigger_lkd(coap_async_t *async) {
120 assert(async != NULL);
122 coap_ticks(&async->delay);
123
124 coap_log_debug(" %s: Async request triggered\n",
125 coap_session_str(async->session));
126 coap_update_io_timer(async->session->context, 0);
127}
128
129COAP_API void
131 coap_lock_lock(return);
132 coap_async_set_delay_lkd(async, delay);
134}
135
136void
137coap_async_set_delay_lkd(coap_async_t *async, coap_tick_t delay) {
138 coap_tick_t now;
139
141 assert(async != NULL);
142 coap_ticks(&now);
143
144 if (delay) {
145 async->delay = now + delay;
146 coap_update_io_timer(async->session->context, delay);
147 coap_log_debug(" %s: Async request delayed for %u.%03u secs\n",
148 coap_session_str(async->session),
149 (unsigned int)(delay / COAP_TICKS_PER_SECOND),
150 (unsigned int)((delay % COAP_TICKS_PER_SECOND) *
151 1000 / COAP_TICKS_PER_SECOND));
152 } else {
153 async->delay = 0;
154 coap_log_debug(" %s: Async request indefinately delayed\n",
155 coap_session_str(async->session));
156 }
157}
158
161 coap_async_t *tmp;
162
163 coap_lock_lock(return NULL);
164 tmp = coap_find_async_lkd(session, token);
166 return tmp;
167}
168
170coap_find_async_lkd(coap_session_t *session, coap_bin_const_t token) {
171 coap_async_t *tmp;
172
174 SEARCH_PAIR(session->context->async_state, tmp,
175 session, session,
176 pdu->actual_token.length, token.length,
177 pdu->actual_token.s, token.s);
178 return tmp;
179}
180
181static void
182coap_free_async_sub(coap_context_t *context, coap_async_t *async) {
183 if (async) {
184 LL_DELETE(context->async_state,async);
185 if (async->session) {
186 coap_session_release_lkd(async->session);
187 async->session = NULL;
188 }
189 if (async->pdu) {
190 coap_delete_pdu_lkd(async->pdu);
191 async->pdu = NULL;
192 }
193 if (async->app_cb && async->app_data) {
194 coap_lock_callback(async->app_cb(async->app_data));
195 }
197 }
198}
199
200COAP_API void
202 coap_lock_lock(return);
203 coap_free_async_lkd(session, async);
205}
206
207void
208coap_free_async_lkd(coap_session_t *session, coap_async_t *async) {
209 coap_free_async_sub(session->context, async);
210}
211
212void
213coap_delete_all_async(coap_context_t *context) {
214 coap_async_t *astate, *tmp;
215
216 LL_FOREACH_SAFE(context->async_state, astate, tmp) {
217 coap_free_async_sub(context, astate);
218 }
219 context->async_state = NULL;
220}
221
222COAP_API void
223coap_async_set_app_data(coap_async_t *async_entry, void *app_data) {
224 coap_lock_lock(return);
225 coap_async_set_app_data2_lkd(async_entry, app_data, NULL);
227}
228
229COAP_API void *
230coap_async_set_app_data2(coap_async_t *async_entry, void *app_data,
232 void *old_data;
233
234 coap_lock_lock(return NULL);
235 old_data = coap_async_set_app_data2_lkd(async_entry, app_data, callback);
237 return old_data;
238}
239
240void *
241coap_async_set_app_data2_lkd(coap_async_t *async_entry, void *app_data,
243 void *old_data = async_entry->app_data;
244
245 async_entry->app_data = app_data;
246 async_entry->app_cb = app_data ? callback : NULL;
247 return old_data;
248}
249
250void *
252 return async->app_data;
253}
254
255#else /* ! COAP_ASYNC_SUPPORT */
256
257int
259 return 0;
260}
261
264 const coap_pdu_t *request,
265 coap_tick_t delay) {
266 (void)session;
267 (void)request;
268 (void)delay;
269 return NULL;
270}
271
272void
274 (void)async;
275 (void)delay;
276}
277
278void
280 (void)session;
281 (void)async;
282}
283
286 coap_bin_const_t token) {
287 (void)session;
288 (void)token;
289 return NULL;
290}
291
292COAP_API void
293coap_async_set_app_data(coap_async_t *async, void *app_data) {
294 (void)async;
295 (void)app_data;
296}
297
298COAP_API void *
301 (void)async;
302 (void)app_data;
303 (void)callback;
304 return NULL;
305}
306
307void *
309 (void)async;
310 return NULL;
311}
312
313#endif /* ! COAP_ASYNC_SUPPORT */
struct coap_async_t coap_async_t
Async Entry information.
void coap_update_io_timer(coap_context_t *context, coap_tick_t delay)
Update when to continue with I/O processing, unless packets come in in the meantime.
Definition coap_io.c:527
Library specific build wrapper for coap_internal.h.
#define COAP_API
@ COAP_STRING
Definition coap_mem.h:39
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_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:143
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition coap_time.h:158
COAP_API void * coap_async_set_app_data2(coap_async_t *async, void *app_data, coap_app_data_free_callback_t callback)
Stores data with the given async, returning the previously stored value or NULL.
Definition coap_async.c:299
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:279
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:285
void * coap_async_get_app_data(const coap_async_t *async)
Gets the application data pointer held in async.
Definition coap_async.c:308
COAP_API 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:293
COAP_API void coap_async_trigger(coap_async_t *async)
Trigger the registered 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:263
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:273
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
#define coap_lock_callback(func)
Dummy for no thread-safe code.
#define coap_lock_unlock()
Dummy for no thread-safe code.
#define coap_lock_check_locked()
Dummy for no thread-safe code.
#define coap_lock_lock(failed)
Dummy for no thread-safe code.
#define coap_log_debug(...)
Definition coap_debug.h:120
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log_crit(...)
Definition coap_debug.h:90
void coap_delete_pdu_lkd(coap_pdu_t *pdu)
Dispose of an CoAP PDU and free off associated storage.
Definition coap_pdu.c:194
coap_pdu_t * coap_pdu_duplicate_lkd(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:234
#define COAP_PDU_IS_REQUEST(pdu)
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:879
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:848
void coap_session_release_lkd(coap_session_t *session)
Decrement reference counter on a session.
coap_session_t * coap_session_reference_lkd(coap_session_t *session)
Increment reference counter on a session.
void(* coap_app_data_free_callback_t)(void *data)
Callback to free off the app data when the entry is being deleted / freed off.
int coap_async_is_supported(void)
Check whether ASYNC (separate responses) is available.
Definition coap_async.c:258
CoAP binary data definition with const data.
Definition coap_str.h:64
size_t length
length of binary data
Definition coap_str.h:65
const uint8_t * s
read-only binary data
Definition coap_str.h:66
The CoAP stack's global state is stored in a coap_context_t object.
structure for CoAP PDUs
uint8_t * token
first byte of token (or extended length bytes prefix), if any, or options
coap_bin_const_t actual_token
Actual token in pdu.
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
coap_context_t * context
session's context