• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /* async.c -- state management for asynchronous messages
2   *
3   * Copyright (C) 2010,2011,2021 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   * @file async.c
13   * @brief state management for asynchronous messages
14   */
15  
16  #include "coap3/coap_internal.h"
17  
18  #ifndef WITHOUT_ASYNC
19  
20  /* utlist-style macros for searching pairs in linked lists */
21  #define SEARCH_PAIR(head,out,field1,val1,field2,val2,field3,val3)   \
22    SEARCH_PAIR3(head,out,field1,val1,field2,val2,field3,val3,next)
23  
24  #define SEARCH_PAIR3(head,out,field1,val1,field2,val2,field3,val3,next) \
25    do {                                                                  \
26      LL_FOREACH2(head,out,next) {                                        \
27        if ((out)->field1 == (val1) && (out)->field2 == (val2) &&         \
28            ((val2) == 0 || memcmp((out)->field3, (val3), (val2)) == 0)) break; \
29      }                                                                   \
30  } while(0)
31  
32  int
coap_async_is_supported(void)33  coap_async_is_supported(void) {
34    return 1;
35  }
36  
37  coap_async_t *
coap_register_async(coap_session_t * session,const coap_pdu_t * request,coap_tick_t delay)38  coap_register_async(coap_session_t *session,
39                      const coap_pdu_t *request, coap_tick_t delay) {
40    coap_async_t *s;
41    coap_mid_t mid = request->mid;
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      coap_log(LOG_DEBUG,
55           "asynchronous state for mid=0x%x already registered\n", mid);
56      return NULL;
57    }
58  
59    /* store information for handling the asynchronous task */
60    s = (coap_async_t *)coap_malloc(sizeof(coap_async_t));
61    if (!s) {
62      coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n");
63      return NULL;
64    }
65  
66    memset(s, 0, sizeof(coap_async_t));
67  
68    s->pdu = coap_pdu_duplicate(request, session, request->token_length,
69                                request->token, NULL);
70    if (s->pdu == NULL) {
71      coap_free_async(session, s);
72      coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n");
73      return NULL;
74    }
75    s->pdu->mid = mid; /* coap_pdu_duplicate() created one */
76  
77    if (coap_get_data(request, &len, &data)) {
78      coap_add_data(s->pdu, len, data);
79    }
80  
81    s->session = coap_session_reference( session );
82  
83    coap_async_set_delay(s, delay);
84  
85    LL_PREPEND(session->context->async_state, s);
86  
87    return s;
88  }
89  
90  void
coap_async_set_delay(coap_async_t * async,coap_tick_t delay)91  coap_async_set_delay(coap_async_t *async, coap_tick_t delay) {
92    assert(async != NULL);
93  
94    if (delay) {
95      coap_ticks(&async->delay);
96      async->delay += delay;
97    }
98    else
99      async->delay = 0;
100    coap_log(LOG_DEBUG, "   %s: Request for delayed for %u.%03u secs\n",
101             coap_session_str(async->session),
102             (unsigned int)(delay / COAP_TICKS_PER_SECOND),
103             (unsigned int)((delay % COAP_TICKS_PER_SECOND) *
104                 1000 / COAP_TICKS_PER_SECOND));
105  }
106  
107  
108  coap_async_t *
coap_find_async(coap_session_t * session,coap_bin_const_t token)109  coap_find_async(coap_session_t *session, coap_bin_const_t token) {
110    coap_async_t *tmp;
111    SEARCH_PAIR(session->context->async_state, tmp,
112                session, session,
113                pdu->token_length, token.length,
114                pdu->token, token.s);
115    return tmp;
116  }
117  
118  static void
coap_free_async_sub(coap_context_t * context,coap_async_t * s)119  coap_free_async_sub(coap_context_t *context, coap_async_t *s) {
120    if (s) {
121      LL_DELETE(context->async_state,s);
122      if (s->session) {
123        coap_session_release(s->session);
124      }
125      if (s->pdu) {
126        coap_delete_pdu(s->pdu);
127        s->pdu = NULL;
128      }
129      coap_free(s);
130    }
131  }
132  
133  void
coap_free_async(coap_session_t * session,coap_async_t * s)134  coap_free_async(coap_session_t *session, coap_async_t *s) {
135    coap_free_async_sub(session->context, s);
136  }
137  
138  void
coap_delete_all_async(coap_context_t * context)139  coap_delete_all_async(coap_context_t *context) {
140    coap_async_t *astate, *tmp;
141  
142    LL_FOREACH_SAFE(context->async_state, astate, tmp) {
143      coap_free_async_sub(context, astate);
144    }
145    context->async_state = NULL;
146  }
147  
148  void
coap_async_set_app_data(coap_async_t * async,void * app_data)149  coap_async_set_app_data(coap_async_t *async, void *app_data) {
150    async->appdata = app_data;
151  }
152  
153  void *
coap_async_get_app_data(const coap_async_t * async)154  coap_async_get_app_data(const coap_async_t *async) {
155    return async->appdata;
156  }
157  
158  #else
159  
160  int
coap_async_is_supported(void)161  coap_async_is_supported(void) {
162    return 0;
163  }
164  
165  coap_async_t *
coap_register_async(coap_session_t * session,const coap_pdu_t * request,coap_tick_t delay)166  coap_register_async(coap_session_t *session,
167                      const coap_pdu_t *request,
168                      coap_tick_t delay) {
169    (void)session;
170    (void)request;
171    (void)delay;
172    return NULL;
173  }
174  
175  void
coap_async_set_delay(coap_async_t * async,coap_tick_t delay)176  coap_async_set_delay(coap_async_t *async, coap_tick_t delay) {
177    (void)async;
178    (void)delay;
179  }
180  
181  void
coap_free_async(coap_session_t * session,coap_async_t * async)182  coap_free_async(coap_session_t *session, coap_async_t *async) {
183    (void)session;
184    (void)async;
185  }
186  
187  coap_async_t *
coap_find_async(coap_session_t * session,coap_bin_const_t token)188  coap_find_async(coap_session_t *session,
189                  coap_bin_const_t token) {
190    (void)session;
191    (void)token;
192    return NULL;
193  }
194  
195  void
coap_async_set_app_data(coap_async_t * async,void * app_data)196  coap_async_set_app_data(coap_async_t *async, void *app_data) {
197    (void)async;
198    (void)app_data;
199  }
200  
201  void *
coap_async_get_app_data(const coap_async_t * async)202  coap_async_get_app_data(const coap_async_t *async) {
203    (void)async;
204    return NULL;
205  }
206  
207  #endif /* WITHOUT_ASYNC */
208