1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include "iotivity_config.h"
22 #include "occlientcb.h"
23 #include <coap/coap.h>
26 #include "oic_malloc.h"
29 #ifdef HAVE_SYS_TIME_H
32 #ifdef HAVE_ARDUINO_TIME_H
37 #include "cainterface.h"
40 #define TAG "OIC_RI_CLIENTCB"
42 struct ClientCB *cbList = NULL;
45 AddClientCB(ClientCB** clientCB, OCCallbackData* cbData,
47 CAToken_t token, uint8_t tokenLength,
48 CAHeaderOption_t *options, uint8_t numOptions,
49 CAPayload_t payload, size_t payloadSize,
50 CAPayloadFormat_t payloadFormat,
51 OCDoHandle *handle, OCMethod method,
52 OCDevAddr *devAddr, char *requestUri,
53 char *resourceTypeName, uint32_t ttl)
55 if (!clientCB || !cbData || !handle || tokenLength > CA_MAX_TOKEN_LEN)
57 return OC_STACK_INVALID_PARAM;
60 OIC_TRACE_BEGIN(%s:AddClientCB, TAG);
62 ClientCB *cbNode = NULL;
65 if (method == OC_REST_PRESENCE)
66 { // Retrieve the presence callback structure for this specific requestUri.
67 cbNode = GetClientCB(NULL, 0, NULL, requestUri);
70 if (!cbNode)// If it does not already exist, create new node.
71 #endif // WITH_PRESENCE
73 cbNode = (ClientCB*) OICMalloc(sizeof(ClientCB));
81 OIC_LOG(INFO, TAG, "Adding client callback with token");
82 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
83 OIC_TRACE_BUFFER("OIC_RI_CLIENTCB:AddClientCB:token:",
84 (const uint8_t *)token, tokenLength);
85 cbNode->callBack = cbData->cb;
86 cbNode->context = cbData->context;
87 cbNode->deleteCallback = cbData->cd;
88 if (!options || !numOptions)
90 OIC_LOG (INFO, TAG, "No options present");
91 cbNode->options = NULL;
92 cbNode->numOptions = 0;
96 cbNode->options = (CAHeaderOption_t *) OICCalloc(numOptions,
97 sizeof(CAHeaderOption_t));
100 OIC_LOG(ERROR, TAG, "Out of memory");
103 return OC_STACK_NO_MEMORY;
105 memcpy(cbNode->options, options,
106 sizeof(CAHeaderOption_t) * numOptions);
108 cbNode->numOptions = numOptions;
110 if (!payload || !payloadSize)
112 OIC_LOG (INFO, TAG, "No payload present");
113 cbNode->payload = NULL;
114 cbNode->payloadSize = 0;
118 cbNode->payload = (CAPayload_t) OICCalloc(1, payloadSize);
119 if (!cbNode->payload)
121 OIC_LOG(ERROR, TAG, "Out of memory");
124 OICFree(cbNode->options);
128 return OC_STACK_NO_MEMORY;
130 memcpy(cbNode->payload, payload, payloadSize);
131 cbNode->payloadSize = payloadSize;
133 cbNode->payloadFormat = payloadFormat;
135 //Note: token memory is allocated in the caller OCDoResource
136 //but freed in DeleteClientCB
137 cbNode->token = token;
138 cbNode->tokenLength = tokenLength;
139 cbNode->handle = *handle;
140 cbNode->method = method;
141 cbNode->sequenceNumber = 0;
143 cbNode->presence = NULL;
144 cbNode->filterResourceType = NULL;
145 #endif // WITH_PRESENCE
147 if (method == OC_REST_PRESENCE ||
148 method == OC_REST_OBSERVE ||
149 method == OC_REST_OBSERVE_ALL)
157 cbNode->requestUri = requestUri; // I own it now
158 cbNode->devAddr = devAddr; // I own it now
159 OIC_LOG_V(INFO, TAG, "Added Callback for uri : %s", requestUri);
160 OIC_TRACE_MARK(%s:AddClientCB:uri:%s, TAG, requestUri);
161 LL_APPEND(cbList, cbNode);
168 // Ensure that the handle the SDK hands back up to the application layer for the
169 // OCDoResource call matches the found ClientCB Node.
174 cbData->cd(cbData->context);
177 CADestroyToken(token);
181 *handle = cbNode->handle;
184 if (method == OC_REST_PRESENCE && resourceTypeName)
187 // Amend the found or created node by adding a new resourceType to it.
188 return InsertResourceTypeFilter(cbNode,(char *)resourceTypeName);
189 // I own resourceTypName now.
193 OICFree(resourceTypeName);
196 OICFree(resourceTypeName);
204 return OC_STACK_NO_MEMORY;
207 void DeleteClientCB(ClientCB * cbNode)
209 OIC_TRACE_BEGIN(%s:DeleteClientCB, TAG);
212 LL_DELETE(cbList, cbNode);
213 OIC_LOG (INFO, TAG, "Deleting token");
214 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)cbNode->token, cbNode->tokenLength);
215 OIC_TRACE_BUFFER("OIC_RI_CLIENTCB:DeleteClientCB:token:",
216 (const uint8_t *)cbNode->token, cbNode->tokenLength);
217 CADestroyToken (cbNode->token);
220 OICFree(cbNode->options);
224 OICFree(cbNode->payload);
226 OICFree(cbNode->devAddr);
227 OICFree(cbNode->handle);
228 if (cbNode->requestUri)
230 OIC_LOG_V (INFO, TAG, "Deleting callback with uri %s", cbNode->requestUri);
231 OIC_TRACE_MARK(%s:DeleteClientCB:uri:%s, TAG, cbNode->requestUri);
232 OICFree(cbNode->requestUri);
234 if (cbNode->deleteCallback)
236 cbNode->deleteCallback(cbNode->context);
240 if (cbNode->presence)
242 OICFree(cbNode->presence->timeOut);
243 OICFree(cbNode->presence);
245 if (cbNode->method == OC_REST_PRESENCE)
247 OCResourceType * pointer = cbNode->filterResourceType;
248 OCResourceType * next = NULL;
251 next = pointer->next;
252 OICFree(pointer->resourcetypename);
257 #endif // WITH_PRESENCE
265 * This function checks if the node is past its time to live and
266 * deletes it if timed-out. Calling this function with a presence or observe
267 * callback with ttl set to 0 will not delete anything as presence nodes have
268 * their own mechanisms for timeouts. A null argument will cause the function to
271 static void CheckAndDeleteTimedOutCB(ClientCB* cbNode)
277 if (cbNode->TTL == 0)
284 if (cbNode->TTL < now)
286 OIC_LOG(INFO, TAG, "Deleting timed-out callback");
287 DeleteClientCB(cbNode);
291 ClientCB* GetClientCB(const CAToken_t token, uint8_t tokenLength,
292 OCDoHandle handle, const char * requestUri)
294 ClientCB* out = NULL;
296 if (token && tokenLength <= CA_MAX_TOKEN_LEN && tokenLength > 0)
298 OIC_LOG (INFO, TAG, "Looking for token");
299 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
300 LL_FOREACH(cbList, out)
302 /* de-annotate below line if want to see all token in cbList */
303 //OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->token, tokenLength);
304 if (memcmp(out->token, token, tokenLength) == 0)
306 OIC_LOG(INFO, TAG, "Found in callback list");
309 CheckAndDeleteTimedOutCB(out);
314 OIC_LOG (INFO, TAG, "Looking for handle");
315 LL_FOREACH(cbList, out)
317 if (out->handle == handle)
319 OIC_LOG(INFO, TAG, "Found in callback list");
322 CheckAndDeleteTimedOutCB(out);
327 OIC_LOG_V(INFO, TAG, "Looking for uri %s", requestUri);
328 LL_FOREACH(cbList, out)
330 /* de-annotate below line if want to see all uri in cbList */
331 //OIC_LOG_V(INFO, TAG, "%s", out->requestUri);
332 if (out->requestUri && strcmp(out->requestUri, requestUri ) == 0)
334 OIC_LOG(INFO, TAG, "Found in callback list");
337 CheckAndDeleteTimedOutCB(out);
340 OIC_LOG(INFO, TAG, "Callback Not found !!");
345 OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, char * resourceTypeName)
347 OCResourceType * newResourceType = NULL;
348 if (cbNode && resourceTypeName)
350 // Form a new resourceType member.
351 newResourceType = (OCResourceType *) OICMalloc(sizeof(OCResourceType));
352 if (!newResourceType)
354 return OC_STACK_NO_MEMORY;
357 newResourceType->next = NULL;
358 newResourceType->resourcetypename = resourceTypeName;
360 LL_APPEND(cbNode->filterResourceType, newResourceType);
363 return OC_STACK_ERROR;
365 #endif // WITH_PRESENCE
367 void DeleteClientCBList()
371 LL_FOREACH_SAFE(cbList, out, tmp)
378 void FindAndDeleteClientCB(ClientCB * cbNode)
383 LL_FOREACH(cbList, tmp)