1 /* async.c -- state management for asynchronous messages
2  *
3  * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
4  *
5  * This file is part of the CoAP library libcoap. Please see
6  * README for terms of use.
7  */
8 
9 /**
10  * @file async.c
11  * @brief state management for asynchronous messages
12  */
13 
14 #ifndef WITHOUT_ASYNC
15 
16 #include "coap_config.h"
17 #include "coap.h"
18 #include "async.h"
19 #include "debug.h"
20 #include "mem.h"
21 #include "utlist.h"
22 
23 coap_async_state_t *
coap_register_async(coap_context_t * context,coap_address_t * peer,coap_pdu_t * request,unsigned char flags,void * data)24 coap_register_async(coap_context_t *context, coap_address_t *peer,
25 		    coap_pdu_t *request, unsigned char flags, void *data) {
26   coap_async_state_t *s;
27   coap_tid_t id;
28 
29   coap_transaction_id(peer, request, &id);
30   LL_SEARCH_SCALAR(context->async_state,s,id,id);
31 
32   if (s != NULL) {
33     /* We must return NULL here as the caller must know that he is
34      * responsible for releasing @p data. */
35     debug("asynchronous state for transaction %d already registered\n", id);
36     return NULL;
37   }
38 
39   /* store information for handling the asynchronous task */
40   s = (coap_async_state_t *)coap_malloc(sizeof(coap_async_state_t) +
41 					request->hdr->token_length);
42   if (!s) {
43     coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n");
44     return NULL;
45   }
46 
47   memset(s, 0, sizeof(coap_async_state_t) + request->hdr->token_length);
48 
49   /* set COAP_ASYNC_CONFIRM according to request's type */
50   s->flags = flags & ~COAP_ASYNC_CONFIRM;
51   if (request->hdr->type == COAP_MESSAGE_CON)
52     s->flags |= COAP_ASYNC_CONFIRM;
53 
54   s->appdata = data;
55 
56   memcpy(&s->peer, peer, sizeof(coap_address_t));
57 
58   if (request->hdr->token_length) {
59     s->tokenlen = request->hdr->token_length;
60     memcpy(s->token, request->hdr->token, request->hdr->token_length);
61   }
62 
63   memcpy(&s->id, &id, sizeof(coap_tid_t));
64 
65   coap_touch_async(s);
66 
67   LL_PREPEND(context->async_state, s);
68 
69   return s;
70 }
71 
72 coap_async_state_t *
coap_find_async(coap_context_t * context,coap_tid_t id)73 coap_find_async(coap_context_t *context, coap_tid_t id) {
74   coap_async_state_t *tmp;
75   LL_SEARCH_SCALAR(context->async_state,tmp,id,id);
76   return tmp;
77 }
78 
79 int
coap_remove_async(coap_context_t * context,coap_tid_t id,coap_async_state_t ** s)80 coap_remove_async(coap_context_t *context, coap_tid_t id,
81 		  coap_async_state_t **s) {
82   coap_async_state_t *tmp = coap_find_async(context, id);
83 
84   if (tmp)
85     LL_DELETE(context->async_state,tmp);
86 
87   *s = tmp;
88   return tmp != NULL;
89 }
90 
91 void
coap_free_async(coap_async_state_t * s)92 coap_free_async(coap_async_state_t *s) {
93   if (s && (s->flags & COAP_ASYNC_RELEASE_DATA) != 0)
94     coap_free(s->appdata);
95   coap_free(s);
96 }
97 
98 #else
99 void does_not_exist();	/* make some compilers happy */
100 #endif /* WITHOUT_ASYNC */
101