libcoap  4.3.1
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-2022 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 
16 #include "coap3/coap_internal.h"
17 
18 #ifndef WITHOUT_ASYNC
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 
33 int
35  return 1;
36 }
37 
40  const coap_pdu_t *request, coap_tick_t delay) {
41  coap_async_t *s;
42  size_t len;
43  const uint8_t *data;
44 
45  if (!COAP_PDU_IS_REQUEST(request))
46  return NULL;
47 
48  SEARCH_PAIR(session->context->async_state, s,
49  session, session,
50  pdu->token_length, request->token_length,
51  pdu->token, request->token);
52 
53  if (s != NULL) {
54  size_t i;
55  char outbuf[2*8 + 1];
56  size_t outbuflen;
57 
58  outbuf[0] = '\000';
59  for (i = 0; i < request->token_length; i++) {
60  outbuflen = strlen(outbuf);
61  snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen,
62  "%02x", request->token[i]);
63  }
65  "asynchronous state for token '%s' already registered\n", outbuf);
66  return NULL;
67  }
68 
69  /* store information for handling the asynchronous task */
70  s = (coap_async_t *)coap_malloc(sizeof(coap_async_t));
71  if (!s) {
72  coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n");
73  return NULL;
74  }
75 
76  memset(s, 0, sizeof(coap_async_t));
77 
78  /* Note that this generates a new MID */
79  s->pdu = coap_pdu_duplicate(request, session, request->token_length,
80  request->token, NULL);
81  if (s->pdu == NULL) {
82  coap_free_async(session, s);
83  coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n");
84  return NULL;
85  }
86 
87  if (coap_get_data(request, &len, &data)) {
88  coap_add_data(s->pdu, len, data);
89  }
90 
91  s->session = coap_session_reference( session );
92 
93  coap_async_set_delay(s, delay);
94 
95  LL_PREPEND(session->context->async_state, s);
96 
97  return s;
98 }
99 
100 void
102  assert(async != NULL);
103  coap_ticks(&async->delay);
104 
105  coap_log(LOG_DEBUG, " %s: Async request triggered\n",
106  coap_session_str(async->session));
107 #ifdef COAP_EPOLL_SUPPORT
109 #endif /* COAP_EPOLL_SUPPORT */
110 }
111 
112 
113 void
115  coap_tick_t now;
116 
117  assert(async != NULL);
118  coap_ticks(&now);
119 
120  if (delay) {
121  async->delay = now + delay;
122 #ifdef COAP_EPOLL_SUPPORT
123  coap_update_epoll_timer(async->session->context, delay);
124 #endif /* COAP_EPOLL_SUPPORT */
125  coap_log(LOG_DEBUG, " %s: Async request delayed for %u.%03u secs\n",
126  coap_session_str(async->session),
127  (unsigned int)(delay / COAP_TICKS_PER_SECOND),
128  (unsigned int)((delay % COAP_TICKS_PER_SECOND) *
129  1000 / COAP_TICKS_PER_SECOND));
130  }
131  else {
132  async->delay = 0;
133  coap_log(LOG_DEBUG, " %s: Async request indefinately delayed\n",
134  coap_session_str(async->session));
135  }
136 }
137 
138 coap_async_t *
140  coap_async_t *tmp;
141  SEARCH_PAIR(session->context->async_state, tmp,
142  session, session,
143  pdu->token_length, token.length,
144  pdu->token, token.s);
145  return tmp;
146 }
147 
148 static void
150  if (s) {
151  LL_DELETE(context->async_state,s);
152  if (s->session) {
154  }
155  if (s->pdu) {
156  coap_delete_pdu(s->pdu);
157  s->pdu = NULL;
158  }
159  coap_free(s);
160  }
161 }
162 
163 void
165  coap_free_async_sub(session->context, s);
166 }
167 
168 void
170  coap_async_t *astate, *tmp;
171 
172  LL_FOREACH_SAFE(context->async_state, astate, tmp) {
173  coap_free_async_sub(context, astate);
174  }
175  context->async_state = NULL;
176 }
177 
178 void
179 coap_async_set_app_data(coap_async_t *async, void *app_data) {
180  async->appdata = app_data;
181 }
182 
183 void *
185  return async->appdata;
186 }
187 
188 #else /* WITHOUT_ASYNC */
189 
190 int
192  return 0;
193 }
194 
195 coap_async_t *
197  const coap_pdu_t *request,
198  coap_tick_t delay) {
199  (void)session;
200  (void)request;
201  (void)delay;
202  return NULL;
203 }
204 
205 void
207  (void)async;
208  (void)delay;
209 }
210 
211 void
212 coap_free_async(coap_session_t *session, coap_async_t *async) {
213  (void)session;
214  (void)async;
215 }
216 
217 coap_async_t *
219  coap_bin_const_t token) {
220  (void)session;
221  (void)token;
222  return NULL;
223 }
224 
225 void
226 coap_async_set_app_data(coap_async_t *async, void *app_data) {
227  (void)async;
228  (void)app_data;
229 }
230 
231 void *
233  (void)async;
234  return NULL;
235 }
236 
237 #endif /* WITHOUT_ASYNC */
#define SEARCH_PAIR(head, out, field1, val1, field2, val2, field3, val3)
Definition: coap_async.c:22
static void coap_free_async_sub(coap_context_t *context, coap_async_t *s)
Definition: coap_async.c:149
Pulls together all the internal only header files.
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.
void coap_ticks(coap_tick_t *t)
Sets t to the internal time with COAP_TICKS_PER_SECOND resolution.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:127
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition: coap_time.h:142
void coap_delete_all_async(coap_context_t *context)
Removes and frees off all of the async entries for the given context.
Definition: coap_async.c:169
void coap_free_async(coap_session_t *session, coap_async_t *s)
Releases the memory that was allocated by coap_register_async() for the object async.
Definition: coap_async.c:164
void coap_async_trigger(coap_async_t *async)
Trigger the registered async.
Definition: coap_async.c:101
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:39
void * coap_async_get_app_data(const coap_async_t *async)
Gets the application data pointer held in async.
Definition: coap_async.c:184
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:114
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:179
int coap_async_is_supported(void)
Returns 1 if libcoap was built with separate messages enabled, 0 otherwise.
Definition: coap_async.c:34
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:139
#define LOG_DEBUG
Definition: coap_debug.h:81
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define LOG_CRIT
Definition: coap_debug.h:66
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:165
#define COAP_PDU_IS_REQUEST(pdu)
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: pdu.c:167
void coap_delete_pdu(coap_pdu_t *pdu)
Dispose of an CoAP PDU and frees associated storage.
Definition: pdu.c:154
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: pdu.c:713
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: pdu.c:682
coap_session_t * coap_session_reference(coap_session_t *session)
Increment reference counter on a session.
Definition: coap_session.c:126
void coap_session_release(coap_session_t *session)
Decrement reference counter on a session.
Definition: coap_session.c:132
COAP_STATIC_INLINE void * coap_malloc(size_t size)
Wrapper function to coap_malloc_type() for backwards compatibility.
Definition: mem.h:103
COAP_STATIC_INLINE void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
Definition: mem.h:110
coap_session_t * session
transaction session
coap_pdu_t * pdu
copy of request pdu
coap_tick_t delay
When to delay to before triggering the response 0 indicates never trigger.
CoAP binary data definition with const data.
Definition: str.h:64
size_t length
length of binary data
Definition: str.h:65
const uint8_t * s
read-only binary data
Definition: str.h:66
The CoAP stack's global state is stored in a coap_context_t object.
coap_async_t * async_state
list of asynchronous message ids
structure for CoAP PDUs
uint8_t * token
first byte of token, if any, or options
uint8_t token_length
length of Token
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