• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "coap_internal.h"
15 
16 #ifndef WITHOUT_ASYNC
17 
18 /* utlist-style macros for searching pairs in linked lists */
19 #define SEARCH_PAIR(head,out,field1,val1,field2,val2)   \
20   SEARCH_PAIR2(head,out,field1,val1,field2,val2,next)
21 
22 #define SEARCH_PAIR2(head,out,field1,val1,field2,val2,next)             \
23   do {                                                                  \
24     LL_FOREACH2(head,out,next) {                                        \
25       if ((out)->field1 == (val1) && (out)->field2 == (val2)) break;    \
26     }                                                                   \
27 } while(0)
28 
29 coap_async_state_t *
coap_register_async(coap_context_t * context,coap_session_t * session,coap_pdu_t * request,unsigned char flags,void * data)30 coap_register_async(coap_context_t *context, coap_session_t *session,
31                     coap_pdu_t *request, unsigned char flags, void *data) {
32   coap_async_state_t *s;
33   coap_tid_t id = request->tid;
34 
35   SEARCH_PAIR(context->async_state,s,session,session,id,id);
36 
37   if (s != NULL) {
38     /* We must return NULL here as the caller must know that he is
39      * responsible for releasing @p data. */
40     coap_log(LOG_DEBUG,
41          "asynchronous state for transaction %d already registered\n", id);
42     return NULL;
43   }
44 
45   /* store information for handling the asynchronous task */
46   s = (coap_async_state_t *)coap_malloc(sizeof(coap_async_state_t));
47   if (!s) {
48     coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n");
49     return NULL;
50   }
51 
52   memset(s, 0, sizeof(coap_async_state_t));
53 
54   /* set COAP_ASYNC_CONFIRM according to request's type */
55   s->flags = flags & ~COAP_ASYNC_CONFIRM;
56   if (request->type == COAP_MESSAGE_CON)
57     s->flags |= COAP_ASYNC_CONFIRM;
58 
59   s->appdata = data;
60   s->session = coap_session_reference( session );
61   s->id = id;
62 
63   if (request->token_length) {
64     /* A token can be up to 8 bytes */
65     s->tokenlen = (request->token_length > 8) ? 8 : request->token_length;
66     memcpy(s->token, request->token, s->tokenlen);
67   }
68 
69   coap_touch_async(s);
70 
71   LL_PREPEND(context->async_state, s);
72 
73   return s;
74 }
75 
76 coap_async_state_t *
coap_find_async(coap_context_t * context,coap_session_t * session,coap_tid_t id)77 coap_find_async(coap_context_t *context, coap_session_t *session, coap_tid_t id) {
78   coap_async_state_t *tmp;
79   SEARCH_PAIR(context->async_state,tmp,session,session,id,id);
80   return tmp;
81 }
82 
83 int
coap_remove_async(coap_context_t * context,coap_session_t * session,coap_tid_t id,coap_async_state_t ** s)84 coap_remove_async(coap_context_t *context, coap_session_t *session,
85                   coap_tid_t id, coap_async_state_t **s) {
86   coap_async_state_t *tmp = coap_find_async(context, session, id);
87 
88   if (tmp)
89     LL_DELETE(context->async_state,tmp);
90 
91   *s = tmp;
92   return tmp != NULL;
93 }
94 
95 void
coap_free_async(coap_async_state_t * s)96 coap_free_async(coap_async_state_t *s) {
97   if (s) {
98     if (s->session) {
99       coap_session_release(s->session);
100     }
101     if ((s->flags & COAP_ASYNC_RELEASE_DATA) != 0) {
102       coap_free(s->appdata);
103     }
104     coap_free(s);
105   }
106 }
107 
108 #else
109 void does_not_exist(void);        /* make some compilers happy */
110 #endif /* WITHOUT_ASYNC */
111