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>
25 #include "oic_malloc.h"
28 #ifdef HAVE_SYS_TIME_H
31 #ifdef HAVE_ARDUINO_TIME_H
36 #include "cainterface.h"
39 #define TAG "OIC_RI_CLIENTCB"
41 struct ClientCB *cbList = NULL;
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)
50 if (!clientCB || !cbData || !handle || tokenLength > CA_MAX_TOKEN_LEN)
52 return OC_STACK_INVALID_PARAM;
55 ClientCB *cbNode = NULL;
58 if (method == OC_REST_PRESENCE)
59 { // Retrieve the presence callback structure for this specific requestUri.
60 cbNode = GetClientCB(NULL, 0, NULL, requestUri);
63 if (!cbNode)// If it does not already exist, create new node.
64 #endif // WITH_PRESENCE
66 cbNode = (ClientCB*) OICMalloc(sizeof(ClientCB));
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;
87 cbNode->presence = NULL;
88 cbNode->filterResourceType = NULL;
89 #endif // WITH_PRESENCE
91 if (method == OC_REST_PRESENCE ||
92 method == OC_REST_OBSERVE ||
93 method == OC_REST_OBSERVE_ALL)
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);
111 // Ensure that the handle the SDK hands back up to the application layer for the
112 // OCDoResource call matches the found ClientCB Node.
117 cbData->cd(cbData->context);
124 *handle = cbNode->handle;
127 if (method == OC_REST_PRESENCE && resourceTypeName)
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.
135 OICFree(resourceTypeName);
138 OICFree(resourceTypeName);
144 return OC_STACK_NO_MEMORY;
147 void DeleteClientCB(ClientCB * cbNode)
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)
159 OIC_LOG_V (INFO, TAG, "Deleting callback with uri %s", cbNode->requestUri);
160 OICFree(cbNode->requestUri);
162 if (cbNode->deleteCallback)
164 cbNode->deleteCallback(cbNode->context);
168 if (cbNode->presence)
170 OICFree(cbNode->presence->timeOut);
171 OICFree(cbNode->presence);
173 if (cbNode->method == OC_REST_PRESENCE)
175 OCResourceType * pointer = cbNode->filterResourceType;
176 OCResourceType * next = NULL;
179 next = pointer->next;
180 OICFree(pointer->resourcetypename);
185 #endif // WITH_PRESENCE
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
198 static void CheckAndDeleteTimedOutCB(ClientCB* cbNode)
204 if (cbNode->TTL == 0)
211 if (cbNode->TTL < now)
213 OIC_LOG(INFO, TAG, "Deleting timed-out callback");
214 DeleteClientCB(cbNode);
218 ClientCB* GetClientCB(const CAToken_t token, uint8_t tokenLength,
219 OCDoHandle handle, const char * requestUri)
221 ClientCB* out = NULL;
223 if (token && tokenLength <= CA_MAX_TOKEN_LEN && tokenLength > 0)
225 OIC_LOG (INFO, TAG, "Looking for token");
226 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
227 LL_FOREACH(cbList, out)
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)
233 OIC_LOG(INFO, TAG, "Found in callback list");
236 CheckAndDeleteTimedOutCB(out);
241 OIC_LOG (INFO, TAG, "Looking for handle");
242 LL_FOREACH(cbList, out)
244 if (out->handle == handle)
246 OIC_LOG(INFO, TAG, "Found in callback list");
249 CheckAndDeleteTimedOutCB(out);
254 OIC_LOG_V(INFO, TAG, "Looking for uri %s", requestUri);
255 LL_FOREACH(cbList, out)
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)
261 OIC_LOG(INFO, TAG, "Found in callback list");
264 CheckAndDeleteTimedOutCB(out);
267 OIC_LOG(INFO, TAG, "Callback Not found !!");
272 OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, char * resourceTypeName)
274 OCResourceType * newResourceType = NULL;
275 if (cbNode && resourceTypeName)
277 // Form a new resourceType member.
278 newResourceType = (OCResourceType *) OICMalloc(sizeof(OCResourceType));
279 if (!newResourceType)
281 return OC_STACK_NO_MEMORY;
284 newResourceType->next = NULL;
285 newResourceType->resourcetypename = resourceTypeName;
287 LL_APPEND(cbNode->filterResourceType, newResourceType);
290 return OC_STACK_ERROR;
292 #endif // WITH_PRESENCE
294 void DeleteClientCBList()
298 LL_FOREACH_SAFE(cbList, out, tmp)
305 void FindAndDeleteClientCB(ClientCB * cbNode)
310 LL_FOREACH(cbList, tmp)