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"
25 #include "oic_malloc.h"
28 #ifdef HAVE_SYS_TIME_H
31 #ifdef HAVE_ARDUINO_TIME_H
36 #include "cainterface.h"
37 #include <coap/coap.h>
40 #define TAG "OIC_RI_CLIENTCB"
42 struct ClientCB *cbList = NULL;
45 AddClientCB (ClientCB** clientCB, OCCallbackData* cbData,
46 CAToken_t token, uint8_t tokenLength,
47 OCDoHandle *handle, OCMethod method,
48 OCDevAddr *devAddr, char * requestUri,
49 char * resourceTypeName, uint32_t ttl)
51 if (!clientCB || !cbData || !handle || tokenLength > CA_MAX_TOKEN_LEN)
53 return OC_STACK_INVALID_PARAM;
56 OIC_TRACE_BEGIN(%s:AddClientCB, TAG);
58 ClientCB *cbNode = NULL;
61 if (method == OC_REST_PRESENCE)
62 { // Retrieve the presence callback structure for this specific requestUri.
63 cbNode = GetClientCB(NULL, 0, NULL, requestUri);
66 if (!cbNode)// If it does not already exist, create new node.
67 #endif // WITH_PRESENCE
69 cbNode = (ClientCB*) OICMalloc(sizeof(ClientCB));
77 OIC_LOG(INFO, TAG, "Adding client callback with token");
78 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
79 OIC_TRACE_BUFFER("OIC_RI_CLIENTCB:AddClientCB:token",
80 (const uint8_t *) token, tokenLength);
81 cbNode->callBack = cbData->cb;
82 cbNode->context = cbData->context;
83 cbNode->deleteCallback = cbData->cd;
84 //Note: token memory is allocated in the caller OCDoResource
85 //but freed in DeleteClientCB
86 cbNode->token = token;
87 cbNode->tokenLength = tokenLength;
88 cbNode->handle = *handle;
89 cbNode->method = method;
90 cbNode->sequenceNumber = 0;
92 cbNode->presence = NULL;
93 cbNode->filterResourceType = NULL;
94 #endif // WITH_PRESENCE
98 method == OC_REST_PRESENCE ||
100 method == OC_REST_OBSERVE ||
101 method == OC_REST_OBSERVE_ALL)
109 cbNode->requestUri = requestUri; // I own it now
110 cbNode->devAddr = devAddr; // I own it now
111 OIC_LOG_V(INFO, TAG, "Added Callback for uri : %s", requestUri);
112 OIC_TRACE_MARK(%s:AddClientCB:uri:%s, TAG, requestUri);
113 LL_APPEND(cbList, cbNode);
120 // Ensure that the handle the SDK hands back up to the application layer for the
121 // OCDoResource call matches the found ClientCB Node.
126 cbData->cd(cbData->context);
133 *handle = cbNode->handle;
136 if (method == OC_REST_PRESENCE && resourceTypeName)
139 // Amend the found or created node by adding a new resourceType to it.
140 return InsertResourceTypeFilter(cbNode,(char *)resourceTypeName);
141 // I own resourceTypName now.
145 OICFree(resourceTypeName);
148 OICFree(resourceTypeName);
156 return OC_STACK_NO_MEMORY;
159 void DeleteClientCB(ClientCB * cbNode)
161 OIC_TRACE_BEGIN(%s:DeleteClientCB, TAG);
164 LL_DELETE(cbList, cbNode);
165 OIC_LOG (INFO, TAG, "Deleting token");
166 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)cbNode->token, cbNode->tokenLength);
167 OIC_TRACE_BUFFER("OIC_RI_CLIENTCB:DeleteClientCB:token",
168 (const uint8_t *)cbNode->token, cbNode->tokenLength);
169 CADestroyToken (cbNode->token);
170 OICFree(cbNode->devAddr);
171 OICFree(cbNode->handle);
172 if (cbNode->requestUri)
174 OIC_LOG_V (INFO, TAG, "Deleting callback with uri %s", cbNode->requestUri);
175 OIC_TRACE_MARK(%s:DeleteClientCB:uri:%s, TAG, cbNode->requestUri);
176 OICFree(cbNode->requestUri);
178 if (cbNode->deleteCallback)
180 cbNode->deleteCallback(cbNode->context);
184 if (cbNode->presence)
186 OICFree(cbNode->presence->timeOut);
187 OICFree(cbNode->presence);
189 if (cbNode->method == OC_REST_PRESENCE)
191 OCResourceType * pointer = cbNode->filterResourceType;
192 OCResourceType * next = NULL;
195 next = pointer->next;
196 OICFree(pointer->resourcetypename);
201 #endif // WITH_PRESENCE
209 * This function checks if the node is past its time to live and
210 * deletes it if timed-out. Calling this function with a presence or observe
211 * callback with ttl set to 0 will not delete anything as presence nodes have
212 * their own mechanisms for timeouts. A null argument will cause the function to
215 static void CheckAndDeleteTimedOutCB(ClientCB* cbNode)
221 if (cbNode->TTL == 0)
228 if (cbNode->TTL < now)
230 OIC_LOG(INFO, TAG, "Deleting timed-out callback");
231 DeleteClientCB(cbNode);
235 ClientCB* GetClientCB(const CAToken_t token, uint8_t tokenLength,
236 OCDoHandle handle, const char * requestUri)
238 ClientCB* out = NULL;
240 if (token && tokenLength <= CA_MAX_TOKEN_LEN && tokenLength > 0)
242 OIC_LOG (INFO, TAG, "Looking for token");
243 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
244 LL_FOREACH(cbList, out)
246 /* de-annotate below line if want to see all token in cbList */
247 //OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->token, tokenLength);
248 if (memcmp(out->token, token, tokenLength) == 0)
250 OIC_LOG(INFO, TAG, "Found in callback list");
253 CheckAndDeleteTimedOutCB(out);
258 OIC_LOG (INFO, TAG, "Looking for handle");
259 LL_FOREACH(cbList, out)
261 if (out->handle == handle)
263 OIC_LOG(INFO, TAG, "Found in callback list");
266 CheckAndDeleteTimedOutCB(out);
271 OIC_LOG_V(INFO, TAG, "Looking for uri %s", requestUri);
272 LL_FOREACH(cbList, out)
274 /* de-annotate below line if want to see all uri in cbList */
275 //OIC_LOG_V(INFO, TAG, "%s", out->requestUri);
276 if (out->requestUri && strcmp(out->requestUri, requestUri ) == 0)
278 OIC_LOG(INFO, TAG, "Found in callback list");
281 CheckAndDeleteTimedOutCB(out);
284 OIC_LOG(INFO, TAG, "Callback Not found !!");
289 OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, char * resourceTypeName)
291 OCResourceType * newResourceType = NULL;
292 if (cbNode && resourceTypeName)
294 // Form a new resourceType member.
295 newResourceType = (OCResourceType *) OICMalloc(sizeof(OCResourceType));
296 if (!newResourceType)
298 return OC_STACK_NO_MEMORY;
301 newResourceType->next = NULL;
302 newResourceType->resourcetypename = resourceTypeName;
304 LL_APPEND(cbNode->filterResourceType, newResourceType);
307 return OC_STACK_ERROR;
309 #endif // WITH_PRESENCE
311 void DeleteClientCBList()
315 LL_FOREACH_SAFE(cbList, out, tmp)
322 void FindAndDeleteClientCB(ClientCB * cbNode)
327 LL_FOREACH(cbList, tmp)