annotate OIC_LOG_BUFFER when looking for client callback and observer
[platform/upstream/iotivity.git] / resource / csdk / stack / src / occlientcb.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "iotivity_config.h"
22 #include "occlientcb.h"
23 #include <coap/coap.h>
24 #include "logger.h"
25 #include "oic_malloc.h"
26 #include <string.h>
27
28 #ifdef HAVE_SYS_TIME_H
29 #include <sys/time.h>
30 #endif
31 #ifdef HAVE_ARDUINO_TIME_H
32 #include "Time.h"
33 #endif
34
35 #include "cacommon.h"
36 #include "cainterface.h"
37
38 /// Module Name
39 #define TAG "OIC_RI_CLIENTCB"
40
41 struct ClientCB *cbList = NULL;
42
43 OCStackResult
44 AddClientCB (ClientCB** clientCB, OCCallbackData* cbData,
45              CAToken_t token, uint8_t tokenLength,
46              OCDoHandle *handle, OCMethod method,
47              OCDevAddr *devAddr, char * requestUri,
48              char * resourceTypeName, uint32_t ttl)
49 {
50     if (!clientCB || !cbData || !handle || tokenLength > CA_MAX_TOKEN_LEN)
51     {
52         return OC_STACK_INVALID_PARAM;
53     }
54
55     ClientCB *cbNode = NULL;
56
57 #ifdef WITH_PRESENCE
58     if (method == OC_REST_PRESENCE)
59     {   // Retrieve the presence callback structure for this specific requestUri.
60         cbNode = GetClientCB(NULL, 0, NULL, requestUri);
61     }
62
63     if (!cbNode)// If it does not already exist, create new node.
64 #endif // WITH_PRESENCE
65     {
66         cbNode = (ClientCB*) OICMalloc(sizeof(ClientCB));
67         if (!cbNode)
68         {
69             *clientCB = NULL;
70             goto exit;
71         }
72         else
73         {
74             OIC_LOG(INFO, TAG, "Adding client callback with token");
75             OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
76             cbNode->callBack = cbData->cb;
77             cbNode->context = cbData->context;
78             cbNode->deleteCallback = cbData->cd;
79             //Note: token memory is allocated in the caller OCDoResource
80             //but freed in DeleteClientCB
81             cbNode->token = token;
82             cbNode->tokenLength = tokenLength;
83             cbNode->handle = *handle;
84             cbNode->method = method;
85             cbNode->sequenceNumber = 0;
86 #ifdef WITH_PRESENCE
87             cbNode->presence = NULL;
88             cbNode->filterResourceType = NULL;
89 #endif // WITH_PRESENCE
90
91             if (method == OC_REST_PRESENCE ||
92                 method == OC_REST_OBSERVE  ||
93                 method == OC_REST_OBSERVE_ALL)
94             {
95                 cbNode->TTL = 0;
96             }
97             else
98             {
99                 cbNode->TTL = ttl;
100             }
101             cbNode->requestUri = requestUri;    // I own it now
102             cbNode->devAddr = devAddr;          // I own it now
103             OIC_LOG_V(INFO, TAG, "Added Callback for uri : %s", requestUri);
104             LL_APPEND(cbList, cbNode);
105             *clientCB = cbNode;
106         }
107     }
108 #ifdef WITH_PRESENCE
109     else
110     {
111         // Ensure that the handle the SDK hands back up to the application layer for the
112         // OCDoResource call matches the found ClientCB Node.
113         *clientCB = cbNode;
114
115         if (cbData->cd)
116         {
117             cbData->cd(cbData->context);
118         }
119
120         OICFree(token);
121         OICFree(*handle);
122         OICFree(requestUri);
123         OICFree(devAddr);
124         *handle = cbNode->handle;
125     }
126
127     if (method == OC_REST_PRESENCE && resourceTypeName)
128     {
129         // Amend the found or created node by adding a new resourceType to it.
130         return InsertResourceTypeFilter(cbNode,(char *)resourceTypeName);
131         // I own resourceTypName now.
132     }
133     else
134     {
135         OICFree(resourceTypeName);
136     }
137 #else
138     OICFree(resourceTypeName);
139 #endif
140
141     return OC_STACK_OK;
142
143 exit:
144     return OC_STACK_NO_MEMORY;
145 }
146
147 void DeleteClientCB(ClientCB * cbNode)
148 {
149     if (cbNode)
150     {
151         LL_DELETE(cbList, cbNode);
152         OIC_LOG (INFO, TAG, "Deleting token");
153         OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)cbNode->token, cbNode->tokenLength);
154         CADestroyToken (cbNode->token);
155         OICFree(cbNode->devAddr);
156         OICFree(cbNode->handle);
157         if (cbNode->requestUri)
158         {
159             OIC_LOG_V (INFO, TAG, "Deleting callback with uri %s", cbNode->requestUri);
160             OICFree(cbNode->requestUri);
161         }
162         if (cbNode->deleteCallback)
163         {
164             cbNode->deleteCallback(cbNode->context);
165         }
166
167 #ifdef WITH_PRESENCE
168         if (cbNode->presence)
169         {
170             OICFree(cbNode->presence->timeOut);
171             OICFree(cbNode->presence);
172         }
173         if (cbNode->method == OC_REST_PRESENCE)
174         {
175             OCResourceType * pointer = cbNode->filterResourceType;
176             OCResourceType * next = NULL;
177             while(pointer)
178             {
179                 next = pointer->next;
180                 OICFree(pointer->resourcetypename);
181                 OICFree(pointer);
182                 pointer = next;
183             }
184         }
185 #endif // WITH_PRESENCE
186         OICFree(cbNode);
187         cbNode = NULL;
188     }
189 }
190
191 /*
192  * This function checks if the node is past its time to live and
193  * deletes it if timed-out. Calling this function with a  presence or observe
194  * callback with ttl set to 0 will not delete anything as presence nodes have
195  * their own mechanisms for timeouts. A null argument will cause the function to
196  * silently return.
197  */
198 static void CheckAndDeleteTimedOutCB(ClientCB* cbNode)
199 {
200     if (!cbNode)
201     {
202         return;
203     }
204     if (cbNode->TTL == 0)
205     {
206         return;
207     }
208     coap_tick_t now;
209     coap_ticks(&now);
210
211     if (cbNode->TTL < now)
212     {
213         OIC_LOG(INFO, TAG, "Deleting timed-out callback");
214         DeleteClientCB(cbNode);
215     }
216 }
217
218 ClientCB* GetClientCB(const CAToken_t token, uint8_t tokenLength,
219                       OCDoHandle handle, const char * requestUri)
220 {
221     ClientCB* out = NULL;
222
223     if (token && tokenLength <= CA_MAX_TOKEN_LEN && tokenLength > 0)
224     {
225         OIC_LOG (INFO, TAG,  "Looking for token");
226         OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
227         LL_FOREACH(cbList, out)
228         {
229             /* de-annotate below line if want to see all token in cbList */
230             //OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->token, tokenLength);
231             if (memcmp(out->token, token, tokenLength) == 0)
232             {
233                 OIC_LOG(INFO, TAG, "Found in callback list");
234                 return out;
235             }
236             CheckAndDeleteTimedOutCB(out);
237         }
238     }
239     else if (handle)
240     {
241         OIC_LOG (INFO, TAG,  "Looking for handle");
242         LL_FOREACH(cbList, out)
243         {
244             if (out->handle == handle)
245             {
246                 OIC_LOG(INFO, TAG, "Found in callback list");
247                 return out;
248             }
249             CheckAndDeleteTimedOutCB(out);
250         }
251     }
252     else if (requestUri)
253     {
254         OIC_LOG_V(INFO, TAG, "Looking for uri %s", requestUri);
255         LL_FOREACH(cbList, out)
256         {
257             /* de-annotate below line if want to see all uri in cbList */
258             //OIC_LOG_V(INFO, TAG, "%s", out->requestUri);
259             if (out->requestUri && strcmp(out->requestUri, requestUri ) == 0)
260             {
261                 OIC_LOG(INFO, TAG, "Found in callback list");
262                 return out;
263             }
264             CheckAndDeleteTimedOutCB(out);
265         }
266     }
267     OIC_LOG(INFO, TAG, "Callback Not found !!");
268     return NULL;
269 }
270
271 #ifdef WITH_PRESENCE
272 OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, char * resourceTypeName)
273 {
274     OCResourceType * newResourceType = NULL;
275     if (cbNode && resourceTypeName)
276     {
277         // Form a new resourceType member.
278         newResourceType = (OCResourceType *) OICMalloc(sizeof(OCResourceType));
279         if (!newResourceType)
280         {
281             return OC_STACK_NO_MEMORY;
282         }
283
284         newResourceType->next = NULL;
285         newResourceType->resourcetypename = resourceTypeName;
286
287         LL_APPEND(cbNode->filterResourceType, newResourceType);
288         return OC_STACK_OK;
289     }
290     return OC_STACK_ERROR;
291 }
292 #endif // WITH_PRESENCE
293
294 void DeleteClientCBList()
295 {
296     ClientCB* out;
297     ClientCB* tmp;
298     LL_FOREACH_SAFE(cbList, out, tmp)
299     {
300         DeleteClientCB(out);
301     }
302     cbList = NULL;
303 }
304
305 void FindAndDeleteClientCB(ClientCB * cbNode)
306 {
307     ClientCB* tmp;
308     if (cbNode)
309     {
310         LL_FOREACH(cbList, tmp)
311         {
312             if (cbNode == tmp)
313             {
314                 DeleteClientCB(tmp);
315                 break;
316             }
317         }
318     }
319 }