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/utlist.h>
25 #include "oic_malloc.h"
28 #ifdef HAVE_SYS_TIME_H
31 #ifdef HAVE_ARDUINO_TIME_H
34 #include <coap/coap_time.h>
37 #include "cainterface.h"
40 #define TAG "OIC_RI_CLIENTCB"
42 struct ClientCB *cbList = NULL;
43 static OCMulticastNode * mcPresenceNodes = NULL;
46 AddClientCB (ClientCB** clientCB, OCCallbackData* cbData,
47 CAToken_t token, uint8_t tokenLength,
48 OCDoHandle *handle, OCMethod method,
49 OCDevAddr *devAddr, char * requestUri,
50 char * resourceTypeName, uint32_t ttl)
52 if (!clientCB || !cbData || !handle || tokenLength > CA_MAX_TOKEN_LEN)
54 return OC_STACK_INVALID_PARAM;
57 ClientCB *cbNode = NULL;
60 if (method == OC_REST_PRESENCE)
61 { // Retrieve the presence callback structure for this specific requestUri.
62 cbNode = GetClientCB(NULL, 0, NULL, requestUri);
65 if (!cbNode)// If it does not already exist, create new node.
66 #endif // WITH_PRESENCE
68 cbNode = (ClientCB*) OICMalloc(sizeof(ClientCB));
76 OIC_LOG(INFO, TAG, "Adding client callback with token");
77 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
78 cbNode->callBack = cbData->cb;
79 cbNode->context = cbData->context;
80 cbNode->deleteCallback = cbData->cd;
81 //Note: token memory is allocated in the caller OCDoResource
82 //but freed in DeleteClientCB
83 cbNode->token = token;
84 cbNode->tokenLength = tokenLength;
85 cbNode->handle = *handle;
86 cbNode->method = method;
87 cbNode->sequenceNumber = 0;
89 cbNode->presence = NULL;
90 cbNode->filterResourceType = NULL;
91 #endif // WITH_PRESENCE
93 if (method == OC_REST_PRESENCE ||
94 method == OC_REST_OBSERVE ||
95 method == OC_REST_OBSERVE_ALL)
103 cbNode->requestUri = requestUri; // I own it now
104 cbNode->devAddr = devAddr; // I own it now
105 OIC_LOG_V(INFO, TAG, "Added Callback for uri : %s", requestUri);
106 LL_APPEND(cbList, cbNode);
113 // Ensure that the handle the SDK hands back up to the application layer for the
114 // OCDoResource call matches the found ClientCB Node.
119 cbData->cd(cbData->context);
126 *handle = cbNode->handle;
129 if (method == OC_REST_PRESENCE && resourceTypeName)
131 // Amend the found or created node by adding a new resourceType to it.
132 return InsertResourceTypeFilter(cbNode,(char *)resourceTypeName);
133 // I own resourceTypName now.
137 OICFree(resourceTypeName);
140 OICFree(resourceTypeName);
146 return OC_STACK_NO_MEMORY;
149 void DeleteClientCB(ClientCB * cbNode)
153 LL_DELETE(cbList, cbNode);
154 OIC_LOG (INFO, TAG, "Deleting token");
155 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)cbNode->token, cbNode->tokenLength);
156 CADestroyToken (cbNode->token);
157 OICFree(cbNode->devAddr);
158 OICFree(cbNode->handle);
159 if (cbNode->requestUri)
161 OIC_LOG_V (INFO, TAG, "Deleting callback with uri %s", cbNode->requestUri);
162 OICFree(cbNode->requestUri);
164 if (cbNode->deleteCallback)
166 cbNode->deleteCallback(cbNode->context);
170 if (cbNode->presence)
172 OICFree(cbNode->presence->timeOut);
173 OICFree(cbNode->presence);
175 if (cbNode->method == OC_REST_PRESENCE)
177 OCResourceType * pointer = cbNode->filterResourceType;
178 OCResourceType * next = NULL;
181 next = pointer->next;
182 OICFree(pointer->resourcetypename);
187 #endif // WITH_PRESENCE
194 * This function checks if the node is past its time to live and
195 * deletes it if timed-out. Calling this function with a presence or observe
196 * callback with ttl set to 0 will not delete anything as presence nodes have
197 * their own mechanisms for timeouts. A null argument will cause the function to
200 static void CheckAndDeleteTimedOutCB(ClientCB* cbNode)
206 if (cbNode->TTL == 0)
213 if (cbNode->TTL < now)
215 OIC_LOG(INFO, TAG, "Deleting timed-out callback");
216 DeleteClientCB(cbNode);
220 ClientCB* GetClientCB(const CAToken_t token, uint8_t tokenLength,
221 OCDoHandle handle, const char * requestUri)
223 ClientCB* out = NULL;
225 if (token && tokenLength <= CA_MAX_TOKEN_LEN && tokenLength > 0)
227 OIC_LOG (INFO, TAG, "Looking for token");
228 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
229 OIC_LOG(INFO, TAG, "\tFound in callback list");
230 LL_FOREACH(cbList, out)
232 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->token, tokenLength);
234 if (memcmp(out->token, token, tokenLength) == 0)
238 CheckAndDeleteTimedOutCB(out);
243 LL_FOREACH(cbList, out)
245 if (out->handle == handle)
249 CheckAndDeleteTimedOutCB(out);
254 OIC_LOG_V(INFO, TAG, "Looking for uri %s", requestUri);
255 LL_FOREACH(cbList, out)
257 OIC_LOG_V(INFO, TAG, "\tFound %s", out->requestUri);
258 if (out->requestUri && strcmp(out->requestUri, requestUri ) == 0)
262 CheckAndDeleteTimedOutCB(out);
265 OIC_LOG(INFO, TAG, "Callback Not found !!");
270 OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, char * resourceTypeName)
272 OCResourceType * newResourceType = NULL;
273 if (cbNode && resourceTypeName)
275 // Form a new resourceType member.
276 newResourceType = (OCResourceType *) OICMalloc(sizeof(OCResourceType));
277 if (!newResourceType)
279 return OC_STACK_NO_MEMORY;
282 newResourceType->next = NULL;
283 newResourceType->resourcetypename = resourceTypeName;
285 LL_APPEND(cbNode->filterResourceType, newResourceType);
288 return OC_STACK_ERROR;
290 #endif // WITH_PRESENCE
292 void DeleteClientCBList()
296 LL_FOREACH_SAFE(cbList, out, tmp)
303 void FindAndDeleteClientCB(ClientCB * cbNode)
308 LL_FOREACH(cbList, tmp)
319 OCStackResult AddMCPresenceNode(OCMulticastNode** outnode, char* uri, uint32_t nonce)
323 return OC_STACK_INVALID_PARAM;
326 OCMulticastNode *node = (OCMulticastNode*) OICMalloc(sizeof(*node));
331 LL_APPEND(mcPresenceNodes, node);
336 return OC_STACK_NO_MEMORY;
339 OCMulticastNode* GetMCPresenceNode(const char * uri)
343 OCMulticastNode* out = NULL;
344 LL_FOREACH(mcPresenceNodes, out)
346 if (out->uri && strcmp(out->uri, uri) == 0)
352 OIC_LOG(INFO, TAG, "MulticastNode Not found !!");