3324da5ad29dc22b64444255f6cd1ecee2aeddd9
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocstack.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
22 //-----------------------------------------------------------------------------
23 // Includes
24 //-----------------------------------------------------------------------------
25 #include "ocstack.h"
26 #include "ocstackinternal.h"
27 #include "ocresourcehandler.h"
28 #include "occlientcb.h"
29 #include "ocobserve.h"
30 #include "ocrandom.h"
31 #include "debug.h"
32 #include "occoap.h"
33 #include "ocmalloc.h"
34 #include "ocserverrequest.h"
35
36 #ifdef CA_INT
37     #include "cacommon.h"
38     #include "cainterface.h"
39 #endif
40
41 //-----------------------------------------------------------------------------
42 // Typedefs
43 //-----------------------------------------------------------------------------
44 typedef enum {
45     OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED
46 } OCStackState;
47
48 #ifdef WITH_PRESENCE
49 typedef enum {
50     OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED
51 } OCPresenceState;
52 #endif
53
54 //-----------------------------------------------------------------------------
55 // Private variables
56 //-----------------------------------------------------------------------------
57 static OCStackState stackState = OC_STACK_UNINITIALIZED;
58
59 OCResource *headResource = NULL;
60 #ifdef WITH_PRESENCE
61 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
62 static PresenceResource presenceResource;
63 uint8_t PresenceTimeOutSize = 0;
64 uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
65 #endif
66
67 OCMode myStackMode;
68 OCDeviceEntityHandler defaultDeviceHandler;
69
70 //-----------------------------------------------------------------------------
71 // Macros
72 //-----------------------------------------------------------------------------
73 #define TAG  PCF("OCStack")
74 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
75             {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
76 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
77              TAG, PCF(#arg " is NULL")); return (retVal); } }
78 #define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
79     goto exit;} }
80
81 //TODO: we should allow the server to define this
82 #define MAX_OBSERVE_AGE (0x2FFFFUL)
83
84 //-----------------------------------------------------------------------------
85 // Externs
86 //-----------------------------------------------------------------------------
87 extern void DeinitOCSecurityInfo();
88
89 //-----------------------------------------------------------------------------
90 // Internal API function
91 //-----------------------------------------------------------------------------
92
93 // This internal function is called to update the stack with the status of
94 // observers and communication failures
95 OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
96 {
97     OCStackResult result = OC_STACK_ERROR;
98     ResourceObserver * observer = NULL;
99     OCEntityHandlerRequest ehRequest = {0};
100
101     switch(status)
102     {
103     case OC_OBSERVER_NOT_INTERESTED:
104         OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
105         observer = GetObserverUsingToken (token);
106         if(observer)
107         {
108             result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
109                     OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
110                     NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
111             if(result != OC_STACK_OK)
112             {
113                 return result;
114             }
115             observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
116         }
117         //observer is not observing anymore
118         result = DeleteObserverUsingToken (token);
119         if(result == OC_STACK_OK)
120         {
121             OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
122         }
123         else
124         {
125             result = OC_STACK_OK;
126             OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
127         }
128         break;
129     case OC_OBSERVER_STILL_INTERESTED:
130         //observer is still interested
131         OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
132                 notifications, reset the failedCount"));
133         observer = GetObserverUsingToken(token);
134         if(observer)
135         {
136             observer->forceHighQos = 0;
137             observer->failedCommCount = 0;
138             result = OC_STACK_OK;
139         }
140         else
141         {
142             result = OC_STACK_OBSERVER_NOT_FOUND;
143         }
144         break;
145     case OC_OBSERVER_FAILED_COMM:
146         //observer is not reachable
147         OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
148         observer = GetObserverUsingToken(token);
149         if(observer)
150         {
151             if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
152             {
153                 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
154                         OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
155                         NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
156                 if(result != OC_STACK_OK)
157                 {
158                     return OC_STACK_ERROR;
159                 }
160                 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
161                 //observer is unreachable
162                 result = DeleteObserverUsingToken (token);
163                 if(result == OC_STACK_OK)
164                 {
165                     OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
166                 }
167                 else
168                 {
169                     result = OC_STACK_OK;
170                     OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
171                 }
172             }
173             else
174             {
175                 observer->failedCommCount++;
176                 result = OC_STACK_CONTINUE;
177             }
178             observer->forceHighQos = 1;
179             OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
180         }
181         break;
182     default:
183         OC_LOG(ERROR, TAG, PCF("Unknown status"));
184         result = OC_STACK_ERROR;
185         break;
186         }
187     return result;
188 }
189
190 #ifdef CA_INT
191 OCStackResult CAToOCStackResult(CAResponseResult_t caCode)
192 {
193     OCStackResult ret = OC_STACK_ERROR;
194
195     switch(caCode)
196     {
197         case CA_SUCCESS:
198             ret = OC_STACK_OK;
199             break;
200         case CA_CREATED:
201             ret = OC_STACK_RESOURCE_CREATED;
202             break;
203         case CA_DELETED:
204             ret = OC_STACK_RESOURCE_DELETED;
205             break;
206         case CA_BAD_REQ:
207             ret = OC_STACK_INVALID_QUERY;
208             break;
209         case CA_BAD_OPT:
210             ret = OC_STACK_INVALID_OPTION;
211             break;
212         case CA_NOT_FOUND:
213             ret = OC_STACK_NO_RESOURCE;
214             break;
215         default:
216             break;
217     }
218     return ret;
219 }
220
221 //This function will be called back by CA layer when a response is received
222 void HandleCAResponses(const CARemoteEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
223 {
224     OC_LOG(INFO, TAG, PCF("Enter HandleCAResponses"));
225     printf ("Received payload: %s\n", (char *)responseInfo->info.payload);
226     OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
227     ClientCB *cbNode = GetClientCB((CAToken_t *)&responseInfo->info.token, NULL, NULL);
228     if (cbNode)
229     {
230         OC_LOG(INFO, TAG, PCF("Calling into application address space"));
231         OCClientResponse response;
232         struct sockaddr_in sa;
233
234         inet_pton(AF_INET, endPoint->addressInfo.IP.ipAddress, &(sa.sin_addr));
235         sa.sin_port = htons(endPoint->addressInfo.IP.port);
236         static OCDevAddr address;
237         memcpy((void*)&address.addr, &(sa), sizeof(sa));
238         response.addr = &address;
239         response.result = CAToOCStackResult(responseInfo->result);
240         response.resJSONPayload = (unsigned char*)responseInfo->info.payload;
241         response.numRcvdVendorSpecificHeaderOptions = 0;
242         if(responseInfo->info.numOptions > 0)
243         {
244             //First option alwas with option ID COAP_OPTION_OBSERVE if it is availbale
245             if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
246             {
247                 memcpy (&(response.sequenceNumber),
248                 &(responseInfo->info.options[0].optionData), 4);
249             }
250             else
251             {
252                memcpy (&(response.rcvdVendorSpecificHeaderOptions[0]),
253                  &(responseInfo->info.options[0]), sizeof(OCHeaderOption));
254             }
255             for (uint8_t i = 1; i < responseInfo->info.numOptions; i++)
256             {
257                 memcpy (&(response.rcvdVendorSpecificHeaderOptions[i]),
258                  &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
259             }
260             response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
261         }
262         result = cbNode->callBack(cbNode->context,
263                 cbNode->handle, &response);
264         if (result == OC_STACK_DELETE_TRANSACTION)
265         {
266             FindAndDeleteClientCB(cbNode);
267         }
268     }
269     OC_LOG_V(INFO, TAG, PCF("Received payload: %s\n"), (char*)responseInfo->info.payload);
270     OC_LOG(INFO, TAG, PCF("Exit HandleCAResponses"));
271 }
272
273 //This function will be called back by CA layer when a request is received
274 void HandleCARequests(const CARemoteEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
275 {
276     CAInfo_t responseData;
277     CAResponseInfo_t responseInfo;
278     OCStackResult requestResult = OC_STACK_ERROR;
279
280     OC_LOG(INFO, TAG, PCF("Enter HandleCARequests"));
281
282 #if 1
283     if(myStackMode == OC_CLIENT)
284     {
285         //TODO: should the client be responding to requests?
286         return;
287     }
288
289     OCServerProtocolRequest serverRequest;
290
291     memset (&serverRequest, 0, sizeof(OCServerProtocolRequest));
292     // copy URI of resource
293     memcpy (&(serverRequest.resourceUrl), endPoint->resourceUri, strlen(endPoint->resourceUri));
294     //copy query
295     // TODO-CA: Is the query part of header option?
296     //copy request payload
297     if (requestInfo->info.payload)
298     {
299         serverRequest.reqTotalSize = strlen(requestInfo->info.payload) + 1;
300         memcpy (&(serverRequest.reqJSONPayload), requestInfo->info.payload,
301                 strlen(requestInfo->info.payload));
302     }
303     else
304     {
305         serverRequest.reqTotalSize = 1;
306     }
307
308     switch (requestInfo->method)
309     {
310         case CA_GET:
311             {
312                 serverRequest.method = OC_REST_GET;
313                 break;
314             }
315         case CA_PUT:
316             {
317                 serverRequest.method = OC_REST_PUT;
318                 break;
319             }
320         case CA_POST:
321             {
322                 serverRequest.method = OC_REST_POST;
323                 break;
324             }
325         case CA_DELETE:
326             {
327                 serverRequest.method = OC_REST_DELETE;
328                 break;
329             }
330         default:
331             {
332                 OC_LOG(ERROR, TAG, PCF("Received CA method %d not supported"));
333                 return;
334             }
335     }
336
337     // copy token
338     OC_LOG_V(INFO, TAG, "HandleCARequests: CA token length = %d", strlen(requestInfo->info.token));
339     OC_LOG_BUFFER(INFO, TAG, requestInfo->info.token, strlen(requestInfo->info.token));
340     // TODO-CA: For CA integration currently copying CAToken to OCCoapToken:
341     // Need to remove OCCoapToken
342     memcpy (&(serverRequest.requestToken.token), requestInfo->info.token,
343             strlen(requestInfo->info.token));
344     serverRequest.requestToken.tokenLength = strlen(requestInfo->info.token);
345     serverRequest.observationOption = OC_OBSERVE_NO_OPTION;
346     if (requestInfo->info.type == CA_MSG_CONFIRM)
347     {
348         serverRequest.qos = OC_HIGH_QOS;
349     }
350     else if (requestInfo->info.type == CA_MSG_NONCONFIRM)
351     {
352         serverRequest.qos = OC_LOW_QOS;
353     }
354     else if (requestInfo->info.type == CA_MSG_ACKNOWLEDGE)
355     {
356         // TODO-CA: Need to handle this
357     }
358     else if (requestInfo->info.type == CA_MSG_RESET)
359     {
360         // TODO-CA: Need to handle this
361     }
362     // CA does not need the following 3 fields
363     serverRequest.coapID = 0;
364     serverRequest.delayedResNeeded = 0;
365     serverRequest.secured = 0;
366
367     // copy the address
368     serverRequest.addressInfo      = endPoint->addressInfo;
369     serverRequest.connectivityType = endPoint->connectivityType;
370     if (requestInfo->info.token)
371     {
372         strncpy(serverRequest.token, requestInfo->info.token, sizeof(serverRequest.token) - 1);
373     }
374 #if 0
375     struct sockaddr_in sa;
376     inet_pton(AF_INET, endPoint->addressInfo.IP.ipAddress, &(sa.sin_addr));
377     sa.sin_port = htons(endPoint->addressInfo.IP.port);
378     memcpy((void*)&serverRequest.requesterAddr, &(sa), sizeof(sa));
379 #endif
380     // copy vendor specific header options
381     // TODO-CA: CA is including non-vendor header options as well, like observe.
382     // Need to filter those out
383     if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
384     {
385         // TODO-CA: Need to send an error indicating the num of options is incorrect
386         return;
387     }
388     serverRequest.numRcvdVendorSpecificHeaderOptions = requestInfo->info.numOptions;
389     if (serverRequest.numRcvdVendorSpecificHeaderOptions)
390     {
391         memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
392             sizeof(CAHeaderOption_t)*requestInfo->info.numOptions);
393     }
394
395     requestResult = HandleStackRequests (&serverRequest);
396 #endif
397
398 #if 0
399     // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
400     memset(&responseData, 0, sizeof(CAInfo_t));
401     responseData.token = (requestInfo != NULL) ? requestInfo->info.token : "";
402
403     // TODO : I guess we need to allocate memeory?
404     responseData.payload = "{\"oc\":[{\"href\":\"/a/led\",\"sid\":\"\",\"prop\":{\"rt\":[\"core.led\"],\"if\":[\"oc.mi.def\"],\"obs\":1}}]}";
405
406     //responseInfo = (CAResponseInfo*) malloc(sizeof(CAResponseInfo));
407     memset(&responseInfo, 0, sizeof(CAResponseInfo_t));
408     responseInfo.result = 200;
409     responseInfo.info = responseData;
410
411     // send request (connectivityType from remoteEndpoint of request Info)
412     OC_LOG(INFO, TAG, PCF("CASendResponse in HandleCARequests"));
413     //TODO-CA: CASendResponse returns the result (we need to check if the
414     // result is ok)
415     CAResult_t caResult = CASendResponse(endPoint, &responseInfo);
416     if(caResult != CA_STATUS_OK)
417     {
418         OC_LOG(ERROR, TAG, PCF("CASendResponse error"));
419     }
420 #endif
421
422     OC_LOG(INFO, TAG, PCF("Exit HandleCARequests"));
423 }
424
425 #endif // CA_INT
426
427 //This function will be called back by occoap layer when a request is received
428 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
429 {
430     OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
431
432     OCStackResult result = OC_STACK_ERROR;
433     ResourceHandling resHandling;
434     OCResource *resource;
435
436     OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
437     if(!request)
438     {
439         OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
440 #ifdef CA_INT
441         result = AddServerCARequest(&request, protocolRequest->coapID,
442                 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
443                 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
444                 protocolRequest->observationOption, protocolRequest->qos,
445                 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
446                 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
447                 &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
448                 protocolRequest->reqTotalSize,
449                 &protocolRequest->addressInfo, protocolRequest->connectivityType, protocolRequest->token);
450 #else
451         result = AddServerRequest(&request, protocolRequest->coapID,
452                 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
453                 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
454                 protocolRequest->observationOption, protocolRequest->qos,
455                 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
456                 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
457                 &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
458                 protocolRequest->reqTotalSize);
459 #endif
460         if (OC_STACK_OK != result)
461         {
462             OC_LOG(ERROR, TAG, PCF("Error adding server request"));
463             return result;
464         }
465         VERIFY_NON_NULL(request, ERROR, OC_STACK_NO_MEMORY);
466
467         if(!protocolRequest->reqMorePacket)
468         {
469             request->requestComplete = 1;
470         }
471     }
472     else
473     {
474         OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request"));
475     }
476
477     if(request->requestComplete)
478     {
479         OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
480         result = DetermineResourceHandling (request, &resHandling, &resource);
481         if (result == OC_STACK_OK)
482         {
483             result = ProcessRequest(resHandling, resource, request);
484         }
485         else
486         {
487             result = OC_STACK_ERROR;
488         }
489     }
490     else
491     {
492         OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
493         result = OC_STACK_CONTINUE;
494     }
495     return result;
496 }
497
498 //This function will be called back by occoap layer when a response is received
499 OCStackResult HandleStackResponses(OCResponse * response)
500 {
501     OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)"));
502     OCStackResult result = OC_STACK_OK;
503     OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
504     uint8_t isObserveNotification = 0;
505     ClientCB * cbNode = NULL;
506     #ifdef WITH_PRESENCE
507     uint8_t isPresenceNotification = 0;
508     uint8_t isMulticastPresence = 0;
509     char * resourceTypeName = NULL;
510     uint32_t lowerBound = 0;
511     uint32_t higherBound = 0;
512     char * tok = NULL;
513     unsigned char * bufRes = response->bufRes;
514     #endif // WITH_PRESENCE
515
516     cbNode = response->cbNode;
517     if(!cbNode)
518     {
519         cbNode = GetClientCB(response->rcvdToken, NULL, NULL);
520     }
521
522     if(response->clientResponse->sequenceNumber >= OC_OFFSET_SEQUENCE_NUMBER)
523     {
524         isObserveNotification = 1;
525         OC_LOG(INFO, TAG, PCF("Received an observe notification"));
526     }
527
528     OC_LOG_V(DEBUG, TAG, "The sequenceNumber/NONCE of this response %u",
529             response->clientResponse->sequenceNumber);
530     OC_LOG_V(DEBUG, TAG, "The maxAge/TTL of this response %u", response->maxAge);
531     OC_LOG_V(DEBUG, TAG, "The response received is %s", bufRes);
532
533 #ifdef WITH_PRESENCE
534     if(!strcmp((char *)response->rcvdUri, (char *)OC_PRESENCE_URI)){
535         isPresenceNotification = 1;
536         if(!bufRes)
537         {
538             result = OC_STACK_INVALID_PARAM;
539             goto exit;
540         }
541         tok = strtok((char *)bufRes, "[:]}");
542         bufRes[strlen((char *)bufRes)] = ':';
543         tok = strtok(NULL, "[:]}");
544         bufRes[strlen((char *)bufRes)] = ':';
545         response->clientResponse->sequenceNumber = (uint32_t )atoi(tok);
546         OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", response->clientResponse->sequenceNumber);
547         tok = strtok(NULL, "[:]}");
548         response->maxAge = (uint32_t )atoi(tok);
549         OC_LOG_V(DEBUG, TAG, "The received TTL is %u", response->maxAge);
550         tok = strtok(NULL, "[:]}");
551         if(tok)
552         {
553             resourceTypeName = (char *)OCMalloc(strlen(tok));
554             if(!resourceTypeName)
555             {
556                 goto exit;
557             }
558             bufRes[strlen((char *)bufRes)] = ':';
559             strcpy(resourceTypeName, tok);
560             OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
561                     resourceTypeName);
562         }
563         bufRes[strlen((char *)bufRes)] = ']';
564     }
565
566     // Check if the application subcribed for presence
567     if(!cbNode)
568     {
569         cbNode = GetClientCB(NULL, NULL, response->fullUri);
570     }
571
572     // Check if application subscribed for multicast presence
573     if(!cbNode)
574     {
575         snprintf((char *)response->fullUri, MAX_URI_LENGTH, "%s%s",
576                 OC_MULTICAST_IP, response->rcvdUri);
577         cbNode = GetClientCB(NULL, NULL, response->fullUri);
578         if(cbNode)
579         {
580             isMulticastPresence = 1;
581             isPresenceNotification = 0;
582         }
583     }
584
585     if(cbNode && isPresenceNotification)
586     {
587         OC_LOG(INFO, TAG, PCF("Received a presence notification"));
588         if(!cbNode->presence)
589         {
590             cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
591             VERIFY_NON_NULL_V(cbNode->presence);
592             cbNode->presence->timeOut = NULL;
593             cbNode->presence->timeOut = (uint32_t *)
594                     OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
595             if(!(cbNode->presence->timeOut)){
596                 OCFree(cbNode->presence);
597                 result = OC_STACK_NO_MEMORY;
598             }
599         }
600         if(response->maxAge == 0)
601         {
602             OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
603             response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
604             if(cbNode->presence)
605             {
606                 OCFree(cbNode->presence->timeOut);
607                 OCFree(cbNode->presence);
608                 cbNode->presence = NULL;
609             }
610         }
611         else
612         {
613             OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %d", GetTime(0));
614             cbNode->presence->TTL = response->maxAge;
615             for(int index = 0; index < PresenceTimeOutSize; index++)
616             {
617                 lowerBound = GetTime(((float)(PresenceTimeOut[index])
618                         /(float)100)*(float)cbNode->presence->TTL);
619                 higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
620                         /(float)100)*(float)cbNode->presence->TTL);
621                 cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
622                 OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout  %d", lowerBound);
623                 OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
624                 OC_LOG_V(DEBUG, TAG, "----------------timeOut entry  %d",
625                         cbNode->presence->timeOut[index]);
626             }
627             cbNode->presence->TTLlevel = 0;
628             OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
629             if(cbNode->sequenceNumber == response->clientResponse->sequenceNumber)
630             {
631                 OC_LOG(INFO, TAG, PCF("===============No presence change"));
632                 goto exit;
633             }
634             OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
635             cbNode->sequenceNumber = response->clientResponse->sequenceNumber;;
636         }
637
638         // Ensure that a filter is actually applied.
639         if(resourceTypeName && cbNode->filterResourceType)
640         {
641             if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
642             {
643                 goto exit;
644             }
645         }
646     }
647     else if(cbNode && isMulticastPresence)
648     {
649         // Check if the same nonce for a given host
650         OCMulticastNode* mcNode = NULL;
651         mcNode = GetMCPresenceNode(response->fullUri);
652
653         if(response->maxAge == 0)
654         {
655             OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
656             response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
657             if(cbNode->presence)
658             {
659                 OCFree(cbNode->presence->timeOut);
660                 OCFree(cbNode->presence);
661                 cbNode->presence = NULL;
662             }
663         }
664         else if(mcNode != NULL)
665         {
666             if(mcNode->nonce == response->clientResponse->sequenceNumber)
667             {
668                 OC_LOG(INFO, TAG, PCF("===============No presence change (Multicast)"));
669                 result = OC_STACK_NO_MEMORY;
670                 goto exit;
671             }
672             mcNode->nonce = response->clientResponse->sequenceNumber;
673         }
674         else
675         {
676             uint32_t uriLen = strlen((char*)response->fullUri);
677             unsigned char* uri = (unsigned char *) OCMalloc(uriLen + 1);
678             if(uri)
679             {
680                 memcpy(uri, response->fullUri, (uriLen + 1));
681             }
682             else
683             {
684                 OC_LOG(INFO, TAG,
685                     PCF("===============No Memory for URI to store in the presence node"));
686                 result = OC_STACK_NO_MEMORY;
687                 goto exit;
688             }
689             result = AddMCPresenceNode(&mcNode, (unsigned char*) uri,
690                     response->clientResponse->sequenceNumber);
691             if(result == OC_STACK_NO_MEMORY)
692             {
693                 OC_LOG(INFO, TAG,
694                     PCF("===============No Memory for Multicast Presence Node"));
695                 result = OC_STACK_NO_MEMORY;
696                 goto exit;
697             }
698         }
699
700         // Ensure that a filter is actually applied.
701         if(resourceTypeName && cbNode->filterResourceType)
702         {
703             if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
704             {
705                 goto exit;
706             }
707         }
708     }
709
710     else if(!cbNode && isPresenceNotification)
711     {
712     OC_LOG(INFO, TAG, PCF("Received a presence notification, but I do not have callback \
713                  ------------ ignoring"));
714     }
715     #endif // WITH_PRESENCE
716
717     if(cbNode)
718     {
719         if(isObserveNotification)
720         {
721             OC_LOG(INFO, TAG, PCF("Received an observe notification"));
722             //TODO: check the standard for methods to detect wrap around condition
723             if(cbNode->method == OC_REST_OBSERVE &&
724                     (response->clientResponse->sequenceNumber <= cbNode->sequenceNumber ||
725                             (response->clientResponse->sequenceNumber > cbNode->sequenceNumber &&
726                                     response->clientResponse->sequenceNumber ==
727                                             MAX_SEQUENCE_NUMBER)))
728             {
729                 OC_LOG_V(DEBUG, TAG, "Observe notification came out of order. \
730                         Ignoring Incoming:%d  Against Current:%d.",
731                         response->clientResponse->sequenceNumber, cbNode->sequenceNumber);
732                 goto exit;
733             }
734             if(response->clientResponse->sequenceNumber > cbNode->sequenceNumber){
735                 cbNode->sequenceNumber = response->clientResponse->sequenceNumber;
736             }
737         }
738
739         response->clientResponse->resJSONPayload = bufRes;
740
741         cbResult = cbNode->callBack(cbNode->context, cbNode->handle, response->clientResponse);
742
743         if (cbResult == OC_STACK_DELETE_TRANSACTION ||
744                 response->clientResponse->result == OC_STACK_COMM_ERROR ||
745                 (response->clientResponse->result == OC_STACK_RESOURCE_DELETED &&
746                         !isPresenceNotification && !isMulticastPresence))
747         {
748             FindAndDeleteClientCB(cbNode);
749         }
750     }
751     else
752     {
753         result = OC_STACK_ERROR;
754     }
755
756     exit:
757     #ifdef WITH_PRESENCE
758     OCFree(resourceTypeName);
759     #endif
760     return result;
761 }
762
763 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
764 {
765     size_t index = 0;
766     unsigned char *itr, *coap;
767     uint8_t dotCount = 0;
768
769     ipAddr[index] = 0;
770     *port = 0;
771     /* search for scheme */
772     itr = ipAddrStr;
773     if (!isdigit((unsigned char) *ipAddrStr))
774     {
775         coap = (unsigned char *) OC_COAP_SCHEME;
776         while (*coap && tolower(*itr) == *coap)
777         {
778             coap++;
779             itr++;
780         }
781     }
782     ipAddrStr = itr;
783
784     while (*ipAddrStr) {
785         if (isdigit((unsigned char) *ipAddrStr))
786         {
787             ipAddr[index] *= 10;
788             ipAddr[index] += *ipAddrStr - '0';
789         }
790         else if ((unsigned char) *ipAddrStr == '.')
791         {
792             index++;
793             dotCount++;
794             ipAddr[index] = 0;
795         }
796         else
797         {
798             break;
799         }
800         ipAddrStr++;
801     }
802     if(*ipAddrStr == ':')
803     {
804         ipAddrStr++;
805         while (*ipAddrStr){
806             if (isdigit((unsigned char) *ipAddrStr))
807             {
808                 *port *= 10;
809                 *port += *ipAddrStr - '0';
810             }
811             else
812             {
813                 break;
814             }
815             ipAddrStr++;
816         }
817     }
818
819
820     if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
821             && dotCount == 3)
822     {
823         return 1;
824     }
825     else
826     {
827         return 0;
828     }
829 }
830
831 //-----------------------------------------------------------------------------
832 // Private internal function prototypes
833 //-----------------------------------------------------------------------------
834
835 static OCDoHandle GenerateInvocationHandle();
836 static OCStackResult initResources();
837 static void insertResource(OCResource *resource);
838 static OCResource *findResource(OCResource *resource);
839 static void insertResourceType(OCResource *resource,
840         OCResourceType *resourceType);
841 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
842         uint8_t index);
843 static void insertResourceInterface(OCResource *resource,
844         OCResourceInterface *resourceInterface);
845 static OCResourceInterface *findResourceInterfaceAtIndex(
846         OCResourceHandle handle, uint8_t index);
847 static void deleteResourceType(OCResourceType *resourceType);
848 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
849 static void deleteResourceElements(OCResource *resource);
850 static int deleteResource(OCResource *resource);
851 static void deleteAllResources();
852 static void incrementSequenceNumber(OCResource * resPtr);
853 static OCStackResult verifyUriQueryLength(const char * inputUri,
854         uint16_t uriLen);
855 static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
856 OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI);
857
858 //-----------------------------------------------------------------------------
859 // Public APIs
860 //-----------------------------------------------------------------------------
861
862 /**
863  * Initialize the OC Stack.  Must be called prior to starting the stack.
864  *
865  * @param ipAddr
866  *     IP Address of host device
867  * @param port
868  *     Port of host device
869  * @param mode
870  *     Host device is client, server, or client-server
871  *
872  * @return
873  *     OC_STACK_OK    - no errors
874  *     OC_STACK_ERROR - stack init error
875  */
876 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
877 {
878     OCStackResult result = OC_STACK_ERROR;
879     OC_LOG(INFO, TAG, PCF("Entering OCInit"));
880
881     if (ipAddr)
882     {
883         OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
884     }
885 #ifdef CA_INT
886     CAInitialize();
887     //It is ok to select network to CA_WIFI for now
888     CAResult_t caResult = CASelectNetwork(CA_WIFI);
889     if(caResult == CA_STATUS_OK)
890     {
891         OC_LOG(INFO, TAG, PCF("CASelectNetwork to WIFI"));
892         caResult = CARegisterHandler(HandleCARequests, HandleCAResponses);
893         if(caResult == CA_STATUS_OK)
894         {
895             OC_LOG(INFO, TAG, PCF("CARegisterHandler..."));
896             stackState = OC_STACK_INITIALIZED;
897             result = OC_STACK_OK;
898             switch (mode)
899             {
900                 case OC_CLIENT:
901                     caResult = CAStartDiscoveryServer();
902                     OC_LOG(INFO, TAG, PCF("Client mode: CAStartDiscoveryServer"));
903                     break;
904                 case OC_SERVER:
905                     caResult = CAStartListeningServer();
906                     OC_LOG(INFO, TAG, PCF("Server mode: CAStartListeningServer"));
907                     break;
908                 case OC_CLIENT_SERVER:
909                     caResult = CAStartListeningServer();
910                     if(caResult == CA_STATUS_OK)
911                     {
912                         caResult = CAStartDiscoveryServer();
913                     }
914                     OC_LOG(INFO, TAG, PCF("Client-server mode"));
915                     break;
916                 default:
917                     OC_LOG(ERROR, TAG, PCF("Invalid mode"));
918                     return OC_STACK_ERROR;
919                     break;
920             }
921
922         }
923         if (caResult == CA_STATUS_OK)
924         {
925             result = OC_STACK_OK;
926         }
927         else
928         {
929             result = OC_STACK_ERROR;
930         }
931     }
932 #else
933     switch (mode)
934     {
935     case OC_CLIENT:
936         OC_LOG(INFO, TAG, PCF("Client mode"));
937         break;
938     case OC_SERVER:
939         OC_LOG(INFO, TAG, PCF("Server mode"));
940         break;
941     case OC_CLIENT_SERVER:
942         OC_LOG(INFO, TAG, PCF("Client-server mode"));
943         break;
944     default:
945         OC_LOG(ERROR, TAG, PCF("Invalid mode"));
946         return OC_STACK_ERROR;
947         break;
948     }
949
950     // Make call to OCCoAP layer
951     result = OCInitCoAP(ipAddr, (uint16_t) port, myStackMode);
952 #endif //CA_INT
953
954     myStackMode = mode;
955     defaultDeviceHandler = NULL;
956
957 #ifdef WITH_PRESENCE
958     PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
959 #endif // WITH_PRESENCE
960
961     if (result == OC_STACK_OK)
962     {
963         stackState = OC_STACK_INITIALIZED;
964     }
965     // Initialize resource
966     if(result == OC_STACK_OK && myStackMode != OC_CLIENT)
967     {
968         result = initResources();
969     }
970     if(result != OC_STACK_OK)
971     {
972         OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
973     }
974     return result;
975 }
976
977 /**
978  * Stop the OC stack.  Use for a controlled shutdown.
979  * @return
980  *     OC_STACK_OK    - no errors
981  *     OC_STACK_ERROR - stack not initialized
982  */
983 OCStackResult OCStop()
984 {
985     OCStackResult result = OC_STACK_ERROR;
986
987     OC_LOG(INFO, TAG, PCF("Entering OCStop"));
988
989     if (stackState != OC_STACK_INITIALIZED)
990     {
991         OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
992         return OC_STACK_ERROR;
993     }
994
995     #ifdef WITH_PRESENCE
996     // Ensure that the TTL associated with ANY and ALL presence notifications originating from
997     // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
998     presenceResource.presenceTTL = 0;
999     #endif // WITH_PRESENCE
1000
1001     // Free memory dynamically allocated for resources
1002     deleteAllResources();
1003
1004     // Make call to OCCoAP layer
1005     if (OCStopCoAP() == OC_STACK_OK)
1006     {
1007         // Remove all observers
1008         DeleteObserverList();
1009         // Remove all the client callbacks
1010         DeleteClientCBList();
1011         stackState = OC_STACK_UNINITIALIZED;
1012         result = OC_STACK_OK;
1013     } else {
1014         result = OC_STACK_ERROR;
1015     }
1016
1017     // Deinit security blob
1018     DeinitOCSecurityInfo();
1019
1020     if (result != OC_STACK_OK) {
1021         OC_LOG(ERROR, TAG, PCF("Stack stop error"));
1022     }
1023
1024     return result;
1025 }
1026
1027 /**
1028  * Verify the lengths of the URI and the query separately
1029  *
1030  * @param inputUri       - Input URI and query.
1031  * @param uriLen         - The length of the initial URI with query.
1032  *
1033  * Note: The '?' that appears after the URI is not considered as
1034  * a part of the query.
1035  */
1036 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
1037 {
1038     char *query;
1039
1040     query = strchr (inputUri, '?');
1041
1042     if (query != NULL)
1043     {
1044         if((query - inputUri) > MAX_URI_LENGTH)
1045         {
1046             return OC_STACK_INVALID_URI;
1047         }
1048
1049         if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
1050         {
1051             return OC_STACK_INVALID_QUERY;
1052         }
1053     }
1054     else if(uriLen > MAX_URI_LENGTH)
1055     {
1056         return OC_STACK_INVALID_URI;
1057     }
1058     return OC_STACK_OK;
1059 }
1060
1061 /**
1062  * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
1063  *
1064  * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
1065  * @param method             - @ref OCMethod to perform on the resource
1066  * @param requiredUri        - URI of the resource to interact with
1067  * @param referenceUri       - URI of the reference resource
1068  * @param request            - JSON encoded request
1069  * @param qos                - quality of service
1070  * @param cbData             - struct that contains asynchronous callback function that is invoked
1071  *                             by the stack when discovery or resource interaction is complete
1072  * @param options            - The address of an array containing the vendor specific header
1073  *                             header options to be sent with the request
1074  * @param numOptions         - Number of vendor specific header options to be included
1075  *
1076  * @return
1077  *     OC_STACK_OK               - no errors
1078  *     OC_STACK_INVALID_CALLBACK - invalid callback function pointer
1079  *     OC_STACK_INVALID_METHOD   - invalid resource method
1080  *     OC_STACK_INVALID_URI      - invalid required or reference URI
1081  */
1082
1083 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
1084                            const char *referenceUri, const char *request,
1085                            OCQualityOfService qos, OCCallbackData *cbData,
1086                            OCHeaderOption * options, uint8_t numOptions)
1087 {
1088     OCStackResult result = OC_STACK_ERROR;
1089     OCCoAPToken token;
1090     ClientCB *clientCB = NULL;
1091     unsigned char * requestUri = NULL;
1092     unsigned char * resourceType = NULL;
1093     char * newUri = (char *)requiredUri;
1094     (void) referenceUri;
1095 #ifdef CA_INT
1096     CARemoteEndpoint_t* endpoint = NULL;
1097     CAResult_t caResult;
1098     CAToken_t caToken = NULL;
1099     CAInfo_t requestData;
1100     CARequestInfo_t requestInfo;
1101     // To track if memory is allocated for additional header options
1102     uint8_t hdrOptionMemAlloc = 0;
1103 #endif // CA_INT
1104
1105     OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
1106
1107     // Validate input parameters
1108     VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
1109     VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
1110
1111     TODO ("Need to form the final query by concatenating require and reference URI's");
1112     VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
1113
1114     uint16_t uriLen = strlen(requiredUri);
1115
1116     // ToDo: We should also check if the requiredUri has a mutlicast address, then qos has to be OC_Low_QOS
1117     switch (method)
1118     {
1119         case OC_REST_GET:
1120         case OC_REST_PUT:
1121         case OC_REST_POST:
1122         case OC_REST_DELETE:
1123         case OC_REST_OBSERVE:
1124         case OC_REST_OBSERVE_ALL:
1125         case OC_REST_CANCEL_OBSERVE:
1126             break;
1127         #ifdef WITH_PRESENCE
1128         case OC_REST_PRESENCE:
1129             break;
1130         #endif
1131         default:
1132             result = OC_STACK_INVALID_METHOD;
1133             goto exit;
1134     }
1135
1136     if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK)
1137     {
1138         goto exit;
1139     }
1140
1141     if((request) && (strlen(request) > MAX_REQUEST_LENGTH))
1142     {
1143         result = OC_STACK_INVALID_PARAM;
1144         goto exit;
1145     }
1146
1147 #ifdef WITH_PRESENCE
1148     if(method == OC_REST_PRESENCE)
1149     {
1150         result = getResourceType(requiredUri, &resourceType, &newUri);
1151         if(resourceType) {
1152             OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
1153         }
1154         else
1155         {
1156             OC_LOG(DEBUG, TAG, PCF("Got Resource Type is NULL."));
1157         }
1158         if(result != OC_STACK_OK)
1159         {
1160             goto exit;
1161         }
1162     }
1163 #endif // WITH_PRESENCE
1164
1165     requestUri = (unsigned char *) OCMalloc(uriLen + 1);
1166     if(requestUri)
1167     {
1168         memcpy(requestUri, newUri, (uriLen + 1));
1169     }
1170     else
1171     {
1172         result = OC_STACK_NO_MEMORY;
1173         goto exit;
1174     }
1175
1176     *handle = GenerateInvocationHandle();
1177     if(!*handle)
1178     {
1179         result = OC_STACK_NO_MEMORY;
1180         goto exit;
1181     }
1182
1183 #ifdef CA_INT
1184     memset(&requestData, 0, sizeof(CAInfo_t));
1185     memset(&requestInfo, 0, sizeof(CARequestInfo_t));
1186     switch (method)
1187     {
1188         case OC_REST_GET:
1189         case OC_REST_OBSERVE:
1190         case OC_REST_OBSERVE_ALL:
1191         case OC_REST_CANCEL_OBSERVE:
1192             {
1193                 requestInfo.method = CA_GET;
1194                 break;
1195             }
1196         case OC_REST_PUT:
1197             {
1198                 requestInfo.method = CA_PUT;
1199                 break;
1200             }
1201         case OC_REST_POST:
1202             {
1203                 requestInfo.method = CA_POST;
1204                 break;
1205             }
1206         case OC_REST_DELETE:
1207             {
1208                 requestInfo.method = CA_DELETE;
1209                 break;
1210             }
1211         #ifdef WITH_PRESENCE
1212         case OC_REST_PRESENCE:
1213             //TODO-CA: What should be the CA method?
1214             break;
1215         #endif
1216         default:
1217             result = OC_STACK_INVALID_METHOD;
1218             goto exit;
1219     }
1220
1221     // TODO-CA: Handle multi-cast scenario
1222     // Create remote end point
1223     caResult = CACreateRemoteEndpoint(newUri, CA_WIFI, &endpoint);
1224     // TODO-CA: Connectivity type should be passed to API
1225     endpoint->connectivityType = CA_WIFI;
1226     if (caResult != CA_STATUS_OK)
1227     {
1228         OC_LOG(ERROR, TAG, PCF("CACreateRemoteEndpoint error"));
1229         goto exit;
1230     }
1231
1232     // create token
1233     caResult = CAGenerateToken(&caToken);
1234
1235     if (caResult != CA_STATUS_OK)
1236     {
1237         OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
1238         caToken = NULL;
1239         goto exit;
1240     }
1241
1242     // TODO-CA: Map QoS to the right CA msg type
1243     requestData.type = CA_MSG_NONCONFIRM;
1244     requestData.token = caToken;
1245     requestData.options = (CAHeaderOption_t*)options;
1246     requestData.numOptions = numOptions;
1247     requestData.payload = (char *)request;
1248
1249     requestInfo.info = requestData;
1250
1251     // send request
1252     caResult = CASendRequest(endpoint, &requestInfo);
1253     if (caResult != CA_STATUS_OK)
1254     {
1255         OC_LOG(ERROR, TAG, PCF("CASendRequest"));
1256         goto exit;
1257     }
1258
1259     if((result = AddClientCB(&clientCB, cbData, &caToken, handle, method,
1260                              requestUri, resourceType)) != OC_STACK_OK)
1261     {
1262         result = OC_STACK_NO_MEMORY;
1263         goto exit;
1264     }
1265
1266 #else // CA_INT
1267
1268     // Generate token which will be used by OCStack to match responses received
1269     // with the request
1270     OCGenerateCoAPToken(&token);
1271
1272     if((result = AddClientCB(&clientCB, cbData, &token, handle, method, requestUri, resourceType))
1273             != OC_STACK_OK)
1274     {
1275         result = OC_STACK_NO_MEMORY;
1276         goto exit;
1277     }
1278
1279 #ifdef WITH_PRESENCE
1280     if(method == OC_REST_PRESENCE)
1281     {
1282         // Replacing method type with GET because "presence" is a stack layer only implementation.
1283         method = OC_REST_GET;
1284     }
1285 #endif
1286
1287     // Make call to OCCoAP layer
1288     result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
1289 #endif // CA_INT
1290
1291 exit:
1292     if(newUri != requiredUri)
1293     {
1294         OCFree(newUri);
1295     }
1296     if (result != OC_STACK_OK)
1297     {
1298         OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
1299         FindAndDeleteClientCB(clientCB);
1300     }
1301 #ifdef CA_INT
1302     CADestroyRemoteEndpoint(endpoint);
1303     if (hdrOptionMemAlloc)
1304     {
1305         OCFree(requestData.options);
1306     }
1307     //TODO-CA: CADestroyToken here
1308 #endif // CA_INT
1309     return result;
1310 }
1311
1312 /**
1313  * Cancel a request associated with a specific @ref OCDoResource invocation.
1314  *
1315  * @param handle - Used to identify a specific OCDoResource invocation.
1316  * @param qos    - used to specify Quality of Service (read below for more info)
1317  * @param options- used to specify vendor specific header options when sending
1318  *                 explicit observe cancellation
1319  * @param numOptions- Number of header options to be included
1320  *
1321  * @return
1322  *     OC_STACK_OK               - No errors; Success
1323  *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
1324  */
1325 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
1326         uint8_t numOptions) {
1327     /*
1328      * This ftn is implemented one of two ways in the case of observation:
1329      *
1330      * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
1331      *      Remove the callback associated on client side.
1332      *      When the next notification comes in from server,
1333      *      reply with RESET message to server.
1334      *      Keep in mind that the server will react to RESET only
1335      *      if the last notification was sent ans CON
1336      *
1337      * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
1338      *      and it is associated with an observe request
1339      *      (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
1340      *      Send CON Observe request to server with
1341      *      observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
1342      *      Remove the callback associated on client side.
1343      */
1344     OCStackResult ret = OC_STACK_OK;
1345
1346     if(!handle) {
1347         return OC_STACK_INVALID_PARAM;
1348     }
1349
1350     OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
1351
1352     ClientCB *clientCB = GetClientCB(NULL, handle, NULL);
1353
1354     if(clientCB) {
1355         switch (clientCB->method)
1356         {
1357             case OC_REST_OBSERVE:
1358             case OC_REST_OBSERVE_ALL:
1359                 if(qos == OC_HIGH_QOS)
1360                 {
1361                     ret = OCDoCoAPResource(OC_REST_CANCEL_OBSERVE, qos,
1362                             &(clientCB->token), (const char *) clientCB->requestUri, NULL, options,
1363                             numOptions);
1364                 }
1365                 else
1366                 {
1367                     FindAndDeleteClientCB(clientCB);
1368                 }
1369                 break;
1370             #ifdef WITH_PRESENCE
1371             case OC_REST_PRESENCE:
1372                 FindAndDeleteClientCB(clientCB);
1373                 break;
1374             #endif
1375             default:
1376                 return OC_STACK_INVALID_METHOD;
1377         }
1378     }
1379     return ret;
1380 }
1381 #ifdef WITH_PRESENCE
1382 OCStackResult OCProcessPresence()
1383 {
1384     OCStackResult result = OC_STACK_OK;
1385     uint8_t ipAddr[4] = { 0 };
1386     uint16_t port = 0;
1387
1388     OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
1389     ClientCB* cbNode = NULL;
1390     OCDevAddr dst;
1391     OCClientResponse clientResponse;
1392     OCResponse * response = NULL;
1393
1394     LL_FOREACH(cbList, cbNode) {
1395         if(OC_REST_PRESENCE == cbNode->method)
1396         {
1397             if(cbNode->presence)
1398             {
1399                 uint32_t now = GetTime(0);
1400                 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
1401                 OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
1402
1403
1404                 if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
1405                 {
1406                     goto exit;
1407                 }
1408
1409                 if(cbNode->presence->TTLlevel < PresenceTimeOutSize){
1410                     OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d",
1411                             cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
1412                 }
1413
1414                 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
1415                 {
1416                     OC_LOG(DEBUG, TAG, PCF("----------------No more timeout ticks"));
1417                     if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
1418                     {
1419                         OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
1420                                 &dst);
1421                         result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_TIMEOUT,
1422                                 (OCDevAddr *) &dst, 0, NULL);
1423                         if(result != OC_STACK_OK)
1424                         {
1425                             goto exit;
1426                         }
1427                         result = FormOCResponse(&response, cbNode, 0, NULL, NULL,
1428                                 &cbNode->token, &clientResponse, NULL);
1429                         if(result != OC_STACK_OK)
1430                         {
1431                             goto exit;
1432                         }
1433
1434                         // Increment the TTLLevel (going to a next state), so we don't keep
1435                         // sending presence notification to client.
1436                         cbNode->presence->TTLlevel++;
1437                         OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
1438                                                 cbNode->presence->TTLlevel);
1439                     }
1440                     else
1441                     {
1442                         result = OC_STACK_INVALID_IP;
1443                         goto exit;
1444                     }
1445                     HandleStackResponses(response);
1446                 }
1447                 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
1448                 {
1449                     OC_LOG(DEBUG, TAG, PCF("time to test server presence =========="));
1450                     OCCoAPToken token;
1451                     OCGenerateCoAPToken(&token);
1452                     result = OCDoCoAPResource(OC_REST_GET, OC_LOW_QOS,
1453                             &token, (const char *)cbNode->requestUri, NULL, NULL, 0);
1454                     if(result != OC_STACK_OK)
1455                     {
1456                         goto exit;
1457                     }
1458                     cbNode->presence->TTLlevel++;
1459                     OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d", cbNode->presence->TTLlevel);
1460                 }
1461             }
1462         }
1463     }
1464 exit:
1465     if (result != OC_STACK_OK)
1466     {
1467         OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
1468     }
1469     return result;
1470 }
1471 #endif
1472
1473 /**
1474  * Called in main loop of OC client or server.  Allows low-level processing of
1475  * stack services.
1476  *
1477  * @return
1478  *     OC_STACK_OK    - no errors
1479  *     OC_STACK_ERROR - stack process error
1480  */
1481 OCStackResult OCProcess() {
1482
1483     OC_LOG(INFO, TAG, PCF("Entering OCProcess"));
1484     #ifdef WITH_PRESENCE
1485     OCProcessPresence();
1486     #endif
1487 #ifdef CA_INT
1488     CAHandleRequestResponse();
1489 #else
1490     OCProcessCoAP();
1491 #endif // CA_INT
1492
1493     return OC_STACK_OK;
1494 }
1495
1496 #ifdef WITH_PRESENCE
1497 /**
1498  * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out
1499  * presence notifications to clients via multicast. Once this API has been called with a success,
1500  * clients may query for this server's presence and this server's stack will respond via multicast.
1501  *
1502  * Server can call this function when it comes online for the first time, or when it comes back
1503  * online from offline mode, or when it re enters network.
1504  *
1505  * @param ttl - Time To Live in seconds
1506  * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
1507  *
1508  * @return
1509  *     OC_STACK_OK      - No errors; Success
1510  */
1511 OCStackResult OCStartPresence(const uint32_t ttl)
1512 {
1513     OCChangeResourceProperty(
1514             &(((OCResource *)presenceResource.handle)->resourceProperties),
1515             OC_ACTIVE, 1);
1516
1517     if(ttl > 0)
1518     {
1519         presenceResource.presenceTTL = ttl;
1520     }
1521
1522     if(OC_PRESENCE_UNINITIALIZED == presenceState)
1523     {
1524         OCDevAddr multiCastAddr;
1525         OCCoAPToken token;
1526
1527         presenceState = OC_PRESENCE_INITIALIZED;
1528         OCGenerateCoAPToken(&token);
1529         OCBuildIPv4Address(224, 0, 1, 187, 5683, &multiCastAddr);
1530         //add the presence observer
1531         AddObserver(OC_PRESENCE_URI, NULL, 0, &token, &multiCastAddr,
1532             (OCResource *)presenceResource.handle, OC_LOW_QOS);
1533     }
1534
1535     // Each time OCStartPresence is called
1536     // a different random 32-bit integer number is used
1537     ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1538
1539     return SendPresenceNotification(NULL);
1540 }
1541
1542 /**
1543  * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out
1544  * presence notifications to clients via multicast. Once this API has been called with a success,
1545  * this server's stack will not respond to clients querying for this server's presence.
1546  *
1547  * Server can call this function when it is terminating, going offline, or when going
1548  * away from network.
1549  *
1550  * @return
1551  *     OC_STACK_OK      - No errors; Success
1552  */
1553 OCStackResult OCStopPresence()
1554 {
1555     OCStackResult result = OC_STACK_ERROR;
1556     //make resource inactive
1557     result = OCChangeResourceProperty(
1558             &(((OCResource *) presenceResource.handle)->resourceProperties),
1559             OC_ACTIVE, 0);
1560     result = SendPresenceNotification(NULL);
1561
1562     return result;
1563 }
1564 #endif
1565
1566
1567 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler)
1568 {
1569     defaultDeviceHandler = entityHandler;
1570
1571     return OC_STACK_OK;
1572 }
1573
1574 /**
1575  * Create a resource
1576  *
1577  * @param handle - pointer to handle to newly created resource.  Set by ocstack.  Used to refer to resource
1578  * @param resourceTypeName - name of resource type.  Example: "core.led"
1579  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
1580  * @param uri - URI of the resource.  Example:  "/a/led"
1581  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1582  *                        NULL for default entity handler
1583  * @param resourceProperties - properties supported by resource.  Example: OC_DISCOVERABLE|OC_OBSERVABLE
1584  *
1585  * @return
1586  *     OC_STACK_OK    - no errors
1587  *     OC_STACK_ERROR - stack process error
1588  */
1589 OCStackResult OCCreateResource(OCResourceHandle *handle,
1590         const char *resourceTypeName,
1591         const char *resourceInterfaceName,
1592         const char *uri, OCEntityHandler entityHandler,
1593         uint8_t resourceProperties) {
1594
1595     OCResource *pointer = NULL;
1596     char *str = NULL;
1597     size_t size;
1598     OCStackResult result = OC_STACK_ERROR;
1599
1600     OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
1601
1602     if(myStackMode == OC_CLIENT)
1603     {
1604         return result;
1605     }
1606     // Validate parameters
1607     // Is it presented during resource discovery?
1608     if (!handle || !resourceTypeName || !uri) {
1609         OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
1610         return OC_STACK_INVALID_PARAM;
1611     }
1612
1613     if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0) {
1614         resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
1615     }
1616
1617     // Make sure resourceProperties bitmask has allowed properties specified
1618     if (resourceProperties
1619             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE)) {
1620         OC_LOG(ERROR, TAG, PCF("Invalid property"));
1621         return OC_STACK_INVALID_PARAM;
1622     }
1623
1624     // If the headResource is NULL, then no resources have been created...
1625     pointer = headResource;
1626     if (pointer) {
1627         // At least one resources is in the resource list, so we need to search for
1628         // repeated URLs, which are not allowed.  If a repeat is found, exit with an error
1629         while (pointer) {
1630             if (strcmp(uri, pointer->uri) == 0) {
1631                 OC_LOG(ERROR, TAG, PCF("URI already in use"));
1632                 return OC_STACK_INVALID_PARAM;
1633             }
1634             pointer = pointer->next;
1635         }
1636     }
1637     // Create the pointer and insert it into the resource list
1638     pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
1639     if (!pointer) {
1640         goto exit;
1641     }
1642     pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
1643
1644     insertResource(pointer);
1645
1646     // Set the uri
1647     size = strlen(uri) + 1;
1648     str = (char *) OCMalloc(size);
1649     if (!str) {
1650         goto exit;
1651     }
1652     strncpy(str, uri, size);
1653     pointer->uri = str;
1654
1655     // Set properties.  Set OC_ACTIVE
1656     pointer->resourceProperties = (OCResourceProperty) (resourceProperties
1657             | OC_ACTIVE);
1658
1659     // Add the resourcetype to the resource
1660     result = BindResourceTypeToResource(pointer, resourceTypeName);
1661     if (result != OC_STACK_OK) {
1662         OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
1663         goto exit;
1664     }
1665
1666     // Add the resourceinterface to the resource
1667     result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
1668     if (result != OC_STACK_OK) {
1669         OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
1670         goto exit;
1671     }
1672
1673     // If an entity handler has been passed, attach it to the newly created
1674     // resource.  Otherwise, set the default entity handler.
1675     if (entityHandler)
1676     {
1677         pointer->entityHandler = entityHandler;
1678     }
1679     else
1680     {
1681         pointer->entityHandler = defaultResourceEHandler;
1682     }
1683
1684     *handle = pointer;
1685     result = OC_STACK_OK;
1686
1687     #ifdef WITH_PRESENCE
1688     if(presenceResource.handle)
1689     {
1690         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1691         SendPresenceNotification(pointer->rsrcType);
1692     }
1693     #endif
1694 exit:
1695     if (result != OC_STACK_OK)
1696     {
1697         // Deep delete of resource and other dynamic elements that it contains
1698         deleteResource(pointer);
1699         OCFree(str);
1700     }
1701     return result;
1702 }
1703
1704
1705
1706 /**
1707  * Create a resource. with host ip address for remote resource
1708  *
1709  * @param handle - pointer to handle to newly created resource.  Set by ocstack.
1710  *                 Used to refer to resource
1711  * @param resourceTypeName - name of resource type.  Example: "core.led"
1712  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
1713  * @param host - HOST address of the remote resource.  Example:  "coap://xxx.xxx.xxx.xxx:xxxxx"
1714  * @param uri - URI of the resource.  Example:  "/a/led"
1715  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1716  *                        NULL for default entity handler
1717  * @param resourceProperties - properties supported by resource.
1718  *                             Example: OC_DISCOVERABLE|OC_OBSERVABLE
1719  *
1720  * @return
1721  *     OC_STACK_OK    - no errors
1722  *     OC_STACK_ERROR - stack process error
1723  */
1724
1725 OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle,
1726         const char *resourceTypeName,
1727         const char *resourceInterfaceName,
1728         const char *host,
1729         const char *uri,
1730         OCEntityHandler entityHandler,
1731         uint8_t resourceProperties)
1732 {
1733     char *str = NULL;
1734     size_t size;
1735     OCStackResult result = OC_STACK_ERROR;
1736
1737     result = OCCreateResource(handle, resourceTypeName, resourceInterfaceName,
1738                                 uri, entityHandler, resourceProperties);
1739
1740     if (result != OC_STACK_ERROR)
1741     {
1742         // Set the uri
1743         size = strlen(host) + 1;
1744         str = (char *) OCMalloc(size);
1745         if (!str)
1746         {
1747             return OC_STACK_ERROR;
1748         }
1749         strncpy(str, host, size);
1750         ((OCResource *) *handle)->host = str;
1751     }
1752
1753     return result;
1754 }
1755
1756 /**
1757  * Add a resource to a collection resource.
1758  *
1759  * @param collectionHandle - handle to the collection resource
1760  * @param resourceHandle - handle to resource to be added to the collection resource
1761  *
1762  * @return
1763  *     OC_STACK_OK    - no errors
1764  *     OC_STACK_ERROR - stack process error
1765  *     OC_STACK_INVALID_PARAM - invalid collectionhandle
1766  */
1767 OCStackResult OCBindResource(
1768         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
1769     OCResource *resource;
1770     uint8_t i;
1771
1772     OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
1773
1774     // Validate parameters
1775     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
1776     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
1777     // Container cannot contain itself
1778     if (collectionHandle == resourceHandle) {
1779         OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
1780         return OC_STACK_INVALID_PARAM;
1781     }
1782
1783     // Use the handle to find the resource in the resource linked list
1784     resource = findResource((OCResource *) collectionHandle);
1785     if (!resource) {
1786         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
1787         return OC_STACK_INVALID_PARAM;
1788     }
1789
1790     // Look for an open slot to add add the child resource.
1791     // If found, add it and return success
1792     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
1793         if (!resource->rsrcResources[i]) {
1794             resource->rsrcResources[i] = (OCResource *) resourceHandle;
1795             OC_LOG(INFO, TAG, PCF("resource bound"));
1796             return OC_STACK_OK;
1797         }
1798     }
1799
1800     #ifdef WITH_PRESENCE
1801     if(presenceResource.handle)
1802     {
1803         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1804         SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
1805     }
1806     #endif
1807
1808     // Unable to add resourceHandle, so return error
1809     return OC_STACK_ERROR;
1810 }
1811
1812 /**
1813  * Remove a resource from a collection resource.
1814  *
1815  * @param collectionHandle - handle to the collection resource
1816  * @param resourceHandle - handle to resource to be added to the collection resource
1817  *
1818  * @return
1819  *     OC_STACK_OK    - no errors
1820  *     OC_STACK_ERROR - stack process error
1821  *     OC_STACK_INVALID_PARAM - invalid collectionHandle
1822  */
1823 OCStackResult OCUnBindResource(
1824         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
1825     OCResource *resource;
1826     uint8_t i;
1827
1828     OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
1829
1830     // Validate parameters
1831     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
1832     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
1833     // Container cannot contain itself
1834     if (collectionHandle == resourceHandle) {
1835         OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
1836         return OC_STACK_INVALID_PARAM;
1837     }
1838
1839     // Use the handle to find the resource in the resource linked list
1840     resource = findResource((OCResource *) collectionHandle);
1841     if (!resource) {
1842         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
1843         return OC_STACK_INVALID_PARAM;
1844     }
1845
1846     // Look for an open slot to add add the child resource.
1847     // If found, add it and return success
1848     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
1849         if (resourceHandle == resource->rsrcResources[i]) {
1850             resource->rsrcResources[i] = (OCResource *) NULL;
1851             OC_LOG(INFO, TAG, PCF("resource unbound"));
1852             return OC_STACK_OK;
1853         }
1854     }
1855
1856     OC_LOG(INFO, TAG, PCF("resource not found in collection"));
1857
1858     #ifdef WITH_PRESENCE
1859     if(presenceResource.handle)
1860     {
1861         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1862         SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
1863     }
1864     #endif
1865
1866     // Unable to add resourceHandle, so return error
1867     return OC_STACK_ERROR;
1868 }
1869
1870 OCStackResult BindResourceTypeToResource(OCResource* resource,
1871                                             const char *resourceTypeName)
1872 {
1873     OCResourceType *pointer = NULL;
1874     char *str = NULL;
1875     size_t size;
1876     OCStackResult result = OC_STACK_ERROR;
1877
1878     OC_LOG(INFO, TAG, PCF("Entering BindResourceTypeToResource"));
1879
1880     // Validate parameters
1881     VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
1882     // TODO:  Does resource attribute resentation really have to be maintained in stack?
1883     // Is it presented during resource discovery?
1884
1885     TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
1886
1887     // Create the resourcetype and insert it into the resource list
1888     pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
1889     if (!pointer) {
1890         goto exit;
1891     }
1892
1893     // Set the resourceTypeName
1894     size = strlen(resourceTypeName) + 1;
1895     str = (char *) OCMalloc(size);
1896     if (!str) {
1897         goto exit;
1898     }
1899     strncpy(str, resourceTypeName, size);
1900     pointer->resourcetypename = str;
1901
1902     insertResourceType(resource, pointer);
1903     result = OC_STACK_OK;
1904
1905     exit: if (result != OC_STACK_OK) {
1906         OCFree(pointer);
1907         OCFree(str);
1908     }
1909
1910     return result;
1911 }
1912
1913 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
1914         const char *resourceInterfaceName)
1915 {
1916     OCResourceInterface *pointer = NULL;
1917     char *str = NULL;
1918     size_t size;
1919     OCStackResult result = OC_STACK_ERROR;
1920
1921     OC_LOG(INFO, TAG, PCF("Entering BindResourceInterfaceToResource"));
1922
1923     // Validate parameters
1924     VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
1925
1926     TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
1927
1928     // Create the resourceinterface and insert it into the resource list
1929     pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
1930     if (!pointer) {
1931         goto exit;
1932     }
1933
1934     // Set the resourceinterface name
1935     size = strlen(resourceInterfaceName) + 1;
1936     str = (char *) OCMalloc(size);
1937     if (!str) {
1938         goto exit;
1939     }
1940     strncpy(str, resourceInterfaceName, size);
1941     pointer->name = str;
1942
1943     // Bind the resourceinterface to the resource
1944     insertResourceInterface(resource, pointer);
1945
1946     result = OC_STACK_OK;
1947
1948     exit: if (result != OC_STACK_OK) {
1949         OCFree(pointer);
1950         OCFree(str);
1951     }
1952
1953     return result;
1954 }
1955
1956 /**
1957  * Bind a resourcetype to a resource.
1958  *
1959  * @param handle - handle to the resource
1960  * @param resourceTypeName - name of resource type.  Example: "core.led"
1961  *
1962  * @return
1963  *     OC_STACK_OK    - no errors
1964  *     OC_STACK_ERROR - stack process error
1965  */
1966 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
1967         const char *resourceTypeName) {
1968
1969     OCStackResult result = OC_STACK_ERROR;
1970     OCResource *resource;
1971
1972     // Make sure resource exists
1973     resource = findResource((OCResource *) handle);
1974     if (!resource) {
1975         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1976         return OC_STACK_ERROR;
1977     }
1978
1979     // call internal function
1980     result = BindResourceTypeToResource(resource, resourceTypeName);
1981
1982     #ifdef WITH_PRESENCE
1983     if(presenceResource.handle)
1984     {
1985         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1986         SendPresenceNotification(resource->rsrcType);
1987     }
1988     #endif
1989
1990     return result;
1991 }
1992
1993 /**
1994  * Bind a resourceinterface to a resource.
1995  *
1996  * @param handle - handle to the resource
1997  * @param resourceInterfaceName - name of resource interface.  Example: "oc.mi.b"
1998  *
1999  * @return
2000  *     OC_STACK_OK    - no errors
2001  *     OC_STACK_ERROR - stack process error
2002  */
2003
2004 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
2005         const char *resourceInterfaceName) {
2006
2007     OCStackResult result = OC_STACK_ERROR;
2008     OCResource *resource;
2009
2010     // Make sure resource exists
2011     resource = findResource((OCResource *) handle);
2012     if (!resource) {
2013         OC_LOG(ERROR, TAG, PCF("Resource not found"));
2014         return OC_STACK_ERROR;
2015     }
2016
2017     // call internal function
2018     result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
2019
2020     #ifdef WITH_PRESENCE
2021     if(presenceResource.handle)
2022     {
2023         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2024         SendPresenceNotification(resource->rsrcType);
2025     }
2026     #endif
2027
2028     return result;
2029 }
2030
2031 /**
2032  * Get the number of resources that have been created in the stack.
2033  *
2034  * @param numResources - pointer to count variable
2035  *
2036  * @return
2037  *     OC_STACK_OK    - no errors
2038  *     OC_STACK_ERROR - stack process error
2039
2040  */
2041 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
2042     OCResource *pointer = headResource;
2043
2044     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
2045     VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
2046     *numResources = 0;
2047     while (pointer) {
2048         *numResources = *numResources + 1;
2049         pointer = pointer->next;
2050     }
2051     return OC_STACK_OK;
2052 }
2053
2054 /**
2055  * Get a resource handle by index.
2056  *
2057  * @param index - index of resource, 0 to Count - 1
2058  *
2059  * @return
2060  *    Resource handle - if found
2061  *    NULL - if not found
2062  */
2063 OCResourceHandle OCGetResourceHandle(uint8_t index) {
2064     OCResource *pointer = headResource;
2065     uint8_t i = 0;
2066
2067     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
2068
2069     // Iterate through the list
2070     while ((i < index) && pointer) {
2071         i++;
2072         pointer = pointer->next;
2073     }
2074     return (OCResourceHandle) pointer;
2075 }
2076
2077 /**
2078  * Delete resource specified by handle.  Deletes resource and all resourcetype and resourceinterface
2079  * linked lists.
2080  *
2081  * @param handle - handle of resource to be deleted
2082  *
2083  * @return
2084  *     OC_STACK_OK              - no errors
2085  *     OC_STACK_ERROR           - stack process error
2086  *     OC_STACK_NO_RESOURCE     - resource not found
2087  *     OC_STACK_INVALID_PARAM   - invalid param
2088  */
2089 OCStackResult OCDeleteResource(OCResourceHandle handle) {
2090     OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
2091
2092     if (!handle) {
2093         OC_LOG(ERROR, TAG, PCF("Invalid param"));
2094         return OC_STACK_INVALID_PARAM;
2095     }
2096
2097     OCResource *resource = findResource((OCResource *) handle);
2098     if (resource == NULL) {
2099         OC_LOG(ERROR, TAG, PCF("Resource not found"));
2100         return OC_STACK_NO_RESOURCE;
2101     }
2102
2103     if (deleteResource((OCResource *) handle) == 0) {
2104         OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
2105         return OC_STACK_ERROR;
2106     }
2107
2108     return OC_STACK_OK;
2109 }
2110
2111 /**
2112  * Get the URI of the resource specified by handle.
2113  *
2114  * @param handle - handle of resource
2115  * @return
2116  *    URI string - if resource found
2117  *    NULL - resource not found
2118  */
2119 const char *OCGetResourceUri(OCResourceHandle handle) {
2120     OCResource *resource;
2121     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
2122
2123     resource = findResource((OCResource *) handle);
2124     if (resource) {
2125         return resource->uri;
2126     }
2127     return (const char *) NULL;
2128 }
2129
2130 /**
2131  * Get the properties of the resource specified by handle.
2132  * NOTE: that after a resource is created, the OC_ACTIVE property is set
2133  * for the resource by the stack.
2134  *
2135  * @param handle - handle of resource
2136  * @return
2137  *    property bitmap - if resource found
2138  *    NULL - resource not found
2139  */
2140 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
2141     OCResource *resource;
2142     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
2143
2144     resource = findResource((OCResource *) handle);
2145     if (resource) {
2146         return resource->resourceProperties;
2147     }
2148     return 0;
2149 }
2150
2151 /**
2152  * Get the number of resource types of the resource.
2153  *
2154  * @param handle - handle of resource
2155  * @param numResourceTypes - pointer to count variable
2156  *
2157  * @return
2158  *     OC_STACK_OK    - no errors
2159  *     OC_STACK_ERROR - stack process error
2160  */
2161 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
2162         uint8_t *numResourceTypes) {
2163     OCResource *resource;
2164     OCResourceType *pointer;
2165
2166     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
2167     VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
2168     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2169
2170     *numResourceTypes = 0;
2171
2172     resource = findResource((OCResource *) handle);
2173     if (resource) {
2174         pointer = resource->rsrcType;
2175         while (pointer) {
2176             *numResourceTypes = *numResourceTypes + 1;
2177             pointer = pointer->next;
2178         }
2179     }
2180     return OC_STACK_OK;
2181 }
2182
2183 /**
2184  * Get name of resource type of the resource.
2185  *
2186  * @param handle - handle of resource
2187  * @param index - index of resource, 0 to Count - 1
2188  *
2189  * @return
2190  *    resource type name - if resource found
2191  *    NULL - resource not found
2192  */
2193 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
2194     OCResourceType *resourceType;
2195
2196     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
2197
2198     resourceType = findResourceTypeAtIndex(handle, index);
2199     if (resourceType) {
2200         return resourceType->resourcetypename;
2201     }
2202     return (const char *) NULL;
2203 }
2204
2205
2206
2207 /**
2208  * Get the number of resource interfaces of the resource.
2209  *
2210  * @param handle - handle of resource
2211  * @param numResources - pointer to count variable
2212  *
2213  * @return
2214  *     OC_STACK_OK    - no errors
2215  *     OC_STACK_ERROR - stack process error
2216  */
2217 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
2218         uint8_t *numResourceInterfaces) {
2219     OCResourceInterface *pointer;
2220     OCResource *resource;
2221
2222     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
2223
2224     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2225     VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
2226
2227     *numResourceInterfaces = 0;
2228     resource = findResource((OCResource *) handle);
2229     if (resource) {
2230         pointer = resource->rsrcInterface;
2231         while (pointer) {
2232             *numResourceInterfaces = *numResourceInterfaces + 1;
2233             pointer = pointer->next;
2234         }
2235     }
2236     return OC_STACK_OK;
2237 }
2238
2239 /**
2240  * Get name of resource interface of the resource.
2241  *
2242  * @param handle - handle of resource
2243  * @param index - index of resource, 0 to Count - 1
2244  *
2245  * @return
2246  *    resource interface name - if resource found
2247  *    NULL - resource not found
2248  */
2249 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
2250     OCResourceInterface *resourceInterface;
2251
2252     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
2253
2254     resourceInterface = findResourceInterfaceAtIndex(handle, index);
2255     if (resourceInterface) {
2256         return resourceInterface->name;
2257     }
2258     return (const char *) NULL;
2259 }
2260
2261 /**
2262  * Get resource handle from the collection resource by index.
2263  *
2264  * @param collectionHandle - handle of collection resource
2265  * @param index - index of contained resource, 0 to Count - 1
2266  *
2267  * @return
2268  *    handle to resource - if resource found
2269  *    NULL - resource not found
2270  */
2271 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
2272         uint8_t index) {
2273     OCResource *resource;
2274
2275     OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
2276
2277     if (index >= MAX_CONTAINED_RESOURCES) {
2278         return NULL;
2279     }
2280
2281     resource = findResource((OCResource *) collectionHandle);
2282     if (!resource) {
2283         return NULL;
2284     }
2285
2286     return resource->rsrcResources[index];
2287 }
2288
2289 /**
2290  * Bind an entity handler to the resource.
2291  *
2292  * @param handle - handle to the resource that the contained resource is to be bound
2293  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
2294  * @return
2295  *     OC_STACK_OK    - no errors
2296  *     OC_STACK_ERROR - stack process error
2297  */
2298 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
2299         OCEntityHandler entityHandler) {
2300     OCResource *resource;
2301
2302     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
2303
2304     // Validate parameters
2305     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
2306     //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
2307
2308     // Use the handle to find the resource in the resource linked list
2309     resource = findResource((OCResource *)handle);
2310     if (!resource) {
2311         OC_LOG(ERROR, TAG, PCF("Resource not found"));
2312         return OC_STACK_ERROR;
2313     }
2314
2315     // Bind the handler
2316     resource->entityHandler = entityHandler;
2317
2318     #ifdef WITH_PRESENCE
2319     if(presenceResource.handle)
2320     {
2321         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2322         SendPresenceNotification(resource->rsrcType);
2323     }
2324     #endif
2325
2326     return OC_STACK_OK;
2327 }
2328
2329 /**
2330  * Get the entity handler for a resource.
2331  *
2332  * @param handle - handle of resource
2333  *
2334  * @return
2335  *    entity handler - if resource found
2336  *    NULL - resource not found
2337  */
2338 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
2339     OCResource *resource;
2340
2341     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
2342
2343     // Use the handle to find the resource in the resource linked list
2344     resource = findResource((OCResource *)handle);
2345     if (!resource) {
2346         OC_LOG(ERROR, TAG, PCF("Resource not found"));
2347         return NULL;
2348     }
2349
2350     // Bind the handler
2351     return resource->entityHandler;
2352 }
2353
2354 void incrementSequenceNumber(OCResource * resPtr)
2355 {
2356     // Increment the sequence number
2357     resPtr->sequenceNum += 1;
2358     if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
2359     {
2360         resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
2361     }
2362     return;
2363 }
2364
2365 /**
2366  * Notify Presence subscribers that a resource has been modified
2367  *
2368  * @param resourceType - Handle to the resourceType linked list of resource
2369  *                       that was modified.
2370  * @param qos          - Quality Of Service
2371  *
2372  */
2373 #ifdef WITH_PRESENCE
2374 OCStackResult SendPresenceNotification(OCResourceType *resourceType)
2375 {
2376     OCResource *resPtr = NULL;
2377     OCStackResult result;
2378     OCMethod method = OC_REST_PRESENCE;
2379     uint32_t maxAge = 0;
2380     resPtr = findResource((OCResource *) presenceResource.handle);
2381     if(NULL == resPtr)
2382     {
2383         return OC_STACK_NO_RESOURCE;
2384     }
2385     if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
2386     {
2387         maxAge = presenceResource.presenceTTL;
2388     }
2389     else
2390     {
2391         maxAge = 0;
2392     }
2393
2394     result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
2395     return result;
2396 }
2397 #endif // WITH_PRESENCE
2398 /**
2399  * Notify observers that an observed value has changed.
2400  *
2401  * @param handle - handle of resource
2402  *
2403  * @return
2404  *     OC_STACK_OK    - no errors
2405  *     OC_STACK_NO_RESOURCE - invalid resource handle
2406  *     OC_STACK_NO_OBSERVERS - no more observers intrested in resource
2407  */
2408 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
2409
2410     OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
2411
2412     OCResource *resPtr = NULL;
2413     OCStackResult result;
2414     OCMethod method = OC_REST_NOMETHOD;
2415     uint32_t maxAge = 0;
2416
2417     OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
2418     #ifdef WITH_PRESENCE
2419     if(handle == presenceResource.handle)
2420     {
2421         return OC_STACK_OK;
2422     }
2423     #endif // WITH_PRESENCE
2424     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
2425
2426     // Verify that the resource exists
2427     resPtr = findResource ((OCResource *) handle);
2428     if (NULL == resPtr)
2429     {
2430         return OC_STACK_NO_RESOURCE;
2431     }
2432     else
2433     {
2434         //only increment in the case of regular observing (not presence)
2435         incrementSequenceNumber(resPtr);
2436         method = OC_REST_OBSERVE;
2437         maxAge = MAX_OBSERVE_AGE;
2438         #ifdef WITH_PRESENCE
2439         result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos);
2440         #else
2441         result = SendAllObserverNotification (method, resPtr, maxAge, qos);
2442         #endif
2443         return result;
2444     }
2445 }
2446
2447 OCStackResult
2448 OCNotifyListOfObservers (OCResourceHandle handle,
2449                          OCObservationId  *obsIdList,
2450                          uint8_t          numberOfIds,
2451                          unsigned char    *notificationJSONPayload,
2452                          OCQualityOfService qos)
2453 {
2454     OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
2455
2456     OCResource *resPtr = NULL;
2457     //TODO: we should allow the server to define this
2458     uint32_t maxAge = MAX_OBSERVE_AGE;
2459
2460     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
2461     VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
2462     VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
2463
2464     // Verify that the resource exists
2465     resPtr = findResource ((OCResource *) handle);
2466     if (NULL == resPtr || myStackMode == OC_CLIENT)
2467     {
2468         return OC_STACK_NO_RESOURCE;
2469     }
2470     else
2471     {
2472         incrementSequenceNumber(resPtr);
2473     }
2474     return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
2475             notificationJSONPayload, maxAge, qos));
2476 }
2477
2478 /**
2479  * Send a response to a request.
2480  * The response can be a regular, slow, or block (i.e. a response that
2481  * is too large to be sent in a single PDU and must span multiple transmissions)
2482  *
2483  * @param response - pointer to structure that contains response parameters
2484  *
2485  * @return
2486  *     OC_STACK_OK                         - No errors; Success
2487  *     OC_STACK_INVALID_PARAM              - Invalid pointer to OCServerResponse
2488  *     OC_STACK_INVALID_REQUEST_HANDLE     - Request handle not found
2489  *     OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a
2490  *                                           persistent response buffer is necessary
2491  */
2492 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
2493 {
2494     OCStackResult result = OC_STACK_ERROR;
2495     OCServerRequest *serverRequest = NULL;
2496
2497     OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
2498
2499     // Validate input parameters
2500     VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
2501     VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
2502
2503     // TODO: Placeholder for creating a response entry when implementing
2504     // block transfer feature
2505
2506     // If a response payload is present, check if block transfer is required
2507     if (ehResponse->payload && OCIsPacketTransferRequired(NULL,
2508             (const char *)ehResponse->payload, ehResponse->payloadSize))
2509     {
2510         OC_LOG(INFO, TAG, PCF("Block transfer required"));
2511
2512         // Persistent response buffer is needed for block transfer
2513         if (!ehResponse->persistentBufferFlag)
2514         {
2515             OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
2516             return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
2517         }
2518         // TODO: Placeholder for block transfer handling
2519         // TODO: Placeholder for setting the the response handle in the OCServerResponse struct
2520             // when implementing the block transfer feature
2521     }
2522     else
2523     {
2524         // Normal response
2525
2526         // Get pointer to request info
2527         serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
2528         if(serverRequest)
2529         {
2530             result = serverRequest->ehResponseHandler(ehResponse);
2531         }
2532     }
2533     return result;
2534 }
2535
2536 /**
2537  * Cancel a response.  Applies to a block response
2538  *
2539  * @param responseHandle - response handle set by stack in OCServerResponse after
2540  *                         OCDoResponse is called
2541  *
2542  * @return
2543  *     OC_STACK_OK               - No errors; Success
2544  *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
2545  */
2546 OCStackResult OCCancelResponse(OCResponseHandle responseHandle)
2547 {
2548     OCStackResult result = OC_STACK_NOTIMPL;
2549
2550     OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse"));
2551
2552     // TODO: validate response handle
2553
2554     return result;
2555 }
2556
2557 //-----------------------------------------------------------------------------
2558 // Private internal function definitions
2559 //-----------------------------------------------------------------------------
2560 /**
2561  * Generate handle of OCDoResource invocation for callback management.
2562  */
2563 static OCDoHandle GenerateInvocationHandle()
2564 {
2565     OCDoHandle handle = NULL;
2566     // Generate token here, it will be deleted when the transaction is deleted
2567     handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
2568     if (handle)
2569     {
2570         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
2571     }
2572
2573     return handle;
2574 }
2575 #ifdef WITH_PRESENCE
2576 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
2577         OCResourceProperty resourceProperties, uint8_t enable)
2578 {
2579     if (resourceProperties
2580             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
2581         OC_LOG(ERROR, TAG, PCF("Invalid property"));
2582         return OC_STACK_INVALID_PARAM;
2583     }
2584     if(!enable)
2585     {
2586         *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
2587     }
2588     else
2589     {
2590         *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
2591     }
2592     return OC_STACK_OK;
2593 }
2594 #endif
2595
2596 /**
2597  * Initialize resource data structures, variables, etc.
2598  */
2599 OCStackResult initResources() {
2600     OCStackResult result = OC_STACK_OK;
2601     // Init application resource vars
2602     headResource = NULL;
2603     // Init Virtual Resources
2604     #ifdef WITH_PRESENCE
2605     presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
2606     //presenceResource.token = OCGenerateCoAPToken();
2607     result = OCCreateResource(&presenceResource.handle,
2608             OC_RSRVD_RESOURCE_TYPE_PRESENCE,
2609             "core.r",
2610             OC_PRESENCE_URI,
2611             NULL,
2612             OC_OBSERVABLE);
2613     //make resource inactive
2614     result = OCChangeResourceProperty(
2615             &(((OCResource *) presenceResource.handle)->resourceProperties),
2616             OC_ACTIVE, 0);
2617     #endif
2618     return result;
2619 }
2620
2621 /**
2622  * Add a resource to the end of the linked list of resources.
2623  *
2624  * @param resource - resource to be added
2625  */
2626 void insertResource(OCResource *resource) {
2627     OCResource *pointer;
2628
2629     if (!headResource) {
2630         headResource = resource;
2631     } else {
2632         pointer = headResource;
2633
2634         while (pointer->next) {
2635             pointer = pointer->next;
2636         }
2637         pointer->next = resource;
2638     }
2639     resource->next = NULL;
2640 }
2641
2642 /**
2643  * Find a resource in the linked list of resources.
2644  *
2645  * @param resource - resource to be found
2646  * @return
2647  *     NULL                - resource not found
2648  *     pointer to resource - pointer to resource that was found in the linked list
2649  */
2650 OCResource *findResource(OCResource *resource) {
2651     OCResource *pointer = headResource;
2652
2653     while (pointer) {
2654         if (pointer == resource) {
2655             return resource;
2656         }
2657         pointer = pointer->next;
2658     }
2659     return NULL;
2660 }
2661
2662 void deleteAllResources()
2663 {
2664     OCResource *pointer = headResource;
2665     OCResource *temp;
2666
2667     while (pointer)
2668     {
2669         temp = pointer->next;
2670         #ifdef WITH_PRESENCE
2671         if(pointer != (OCResource *) presenceResource.handle)
2672         {
2673             #endif // WITH_PRESENCE
2674             deleteResource(pointer);
2675             #ifdef WITH_PRESENCE
2676         }
2677         #endif // WITH_PRESENCE
2678         pointer = temp;
2679     }
2680
2681     #ifdef WITH_PRESENCE
2682     // Ensure that the last resource to be deleted is the presence resource. This allows for all
2683     // presence notification attributed to their deletion to be processed.
2684     deleteResource((OCResource *) presenceResource.handle);
2685     #endif // WITH_PRESENCE
2686 }
2687
2688 /**
2689  * Delete the resource from the linked list.
2690  *
2691  * @param resource - resource to be deleted
2692  * @return
2693  *    0 - error
2694  *    1 - success
2695  */
2696 int deleteResource(OCResource *resource) {
2697     OCResource *prev = NULL;
2698     OCResource *temp;
2699
2700     temp = headResource;
2701     while (temp) {
2702         if (temp == resource) {
2703             // Invalidate all Resource Properties.
2704             resource->resourceProperties = (OCResourceProperty) 0;
2705             #ifdef WITH_PRESENCE
2706             if(resource != (OCResource *) presenceResource.handle)
2707             {
2708             #endif // WITH_PRESENCE
2709                 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
2710             #ifdef WITH_PRESENCE
2711             }
2712
2713             if(presenceResource.handle)
2714             {
2715                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2716                 if(resource != (OCResource *) presenceResource.handle)
2717                 {
2718                     SendPresenceNotification(resource->rsrcType);
2719                 }
2720                 else
2721                 {
2722                     SendPresenceNotification(NULL);
2723                 }
2724             }
2725         #endif
2726
2727             if (temp == headResource) {
2728                 headResource = temp->next;
2729             } else {
2730                 prev->next = temp->next;
2731             }
2732
2733             deleteResourceElements(temp);
2734             OCFree(temp);
2735             return 1;
2736         } else {
2737             prev = temp;
2738             temp = temp->next;
2739         }
2740     }
2741
2742     return 0;
2743 }
2744
2745 /**
2746  * Delete all of the dynamically allocated elements that were created for the resource.
2747  *
2748  * @param resource - specified resource
2749  */
2750 void deleteResourceElements(OCResource *resource) {
2751     if (!resource) {
2752         return;
2753     }
2754
2755     // remove URI
2756     OCFree(resource->uri);
2757
2758     // Delete resourcetype linked list
2759     deleteResourceType(resource->rsrcType);
2760
2761     // Delete resourceinterface linked list
2762     deleteResourceInterface(resource->rsrcInterface);
2763 }
2764
2765 /**
2766  * Delete all of the dynamically allocated elements that were created for the resource type.
2767  *
2768  * @param resourceType - specified resource type
2769  */
2770 void deleteResourceType(OCResourceType *resourceType) {
2771     OCResourceType *pointer = resourceType;
2772     OCResourceType *next;
2773
2774     while (pointer) {
2775         next = pointer->next;
2776         OCFree(pointer->resourcetypename);
2777         OCFree(pointer);
2778         pointer = next;
2779     }
2780 }
2781
2782 /**
2783  * Delete all of the dynamically allocated elements that were created for the resource interface.
2784  *
2785  * @param resourceInterface - specified resource interface
2786  */
2787 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
2788     OCResourceInterface *pointer = resourceInterface;
2789     OCResourceInterface *next;
2790
2791     while (pointer) {
2792         next = pointer->next;
2793         OCFree(pointer->name);
2794         OCFree(pointer);
2795         pointer = next;
2796     }
2797 }
2798
2799 /**
2800  * Insert a resource type into a resource's resource type linked list.
2801  *
2802  * @param resource - resource where resource type is to be inserted
2803  * @param resourceType - resource type to be inserted
2804  */
2805 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
2806     OCResourceType *pointer;
2807
2808     if (resource && !resource->rsrcType) {
2809         resource->rsrcType = resourceType;
2810     } else {
2811         if(resource)
2812         {
2813             pointer = resource->rsrcType;
2814         }
2815         else
2816         {
2817             pointer = resourceType;
2818         }
2819         while (pointer->next) {
2820             pointer = pointer->next;
2821         }
2822         pointer->next = resourceType;
2823     }
2824     resourceType->next = NULL;
2825 }
2826
2827 /**
2828  * Get a resource type at the specified index within a resource.
2829  *
2830  * @param handle - handle of resource
2831  * @param index - index of resource type
2832  *
2833  * @return
2834  *    resourcetype - if found
2835  *    NULL - not found
2836  */
2837 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
2838     OCResource *resource;
2839     OCResourceType *pointer;
2840     uint8_t i;
2841
2842     // Find the specified resource
2843     resource = findResource((OCResource *) handle);
2844     if (!resource) {
2845         return NULL;
2846     }
2847
2848     // Make sure a resource has a resourcetype
2849     if (!resource->rsrcType) {
2850         return NULL;
2851     }
2852
2853     // Iterate through the list
2854     pointer = resource->rsrcType;
2855     i = 0;
2856     while ((i < index) && pointer) {
2857         i++;
2858         pointer = pointer->next;
2859     }
2860     return pointer;
2861 }
2862
2863 /**
2864  * Finds a resource type in an OCResourceType link-list.
2865  *
2866  * @param resourceTypeList - the link-list to be searched through
2867  * @param resourceTypeName - the key to search for
2868  *
2869  * @return
2870  *      resourceType that matches the key (ie. resourceTypeName)
2871  *      NULL - either an invalid parameter or this function was unable to find the key.
2872  */
2873 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
2874 {
2875     if(resourceTypeList && resourceTypeName)
2876     {
2877         OCResourceType * rtPointer = resourceTypeList;
2878         while(resourceTypeName && rtPointer)
2879         {
2880             if(rtPointer->resourcetypename &&
2881                     strcmp(resourceTypeName, (const char *)
2882                     (rtPointer->resourcetypename)) == 0)
2883             {
2884                 break;
2885             }
2886             rtPointer = rtPointer->next;
2887         }
2888         return rtPointer;
2889     }
2890     return NULL;
2891 }
2892 /**
2893  * Insert a resource interface into a resource's resource interface linked list.
2894  *
2895  * @param resource - resource where resource interface is to be inserted
2896  * @param resourceInterface - resource interface to be inserted
2897  */
2898 void insertResourceInterface(OCResource *resource,
2899         OCResourceInterface *resourceInterface) {
2900     OCResourceInterface *pointer;
2901
2902     if (!resource->rsrcInterface) {
2903         resource->rsrcInterface = resourceInterface;
2904     } else {
2905         pointer = resource->rsrcInterface;
2906         while (pointer->next) {
2907             pointer = pointer->next;
2908         }
2909         pointer->next = resourceInterface;
2910     }
2911     resourceInterface->next = NULL;
2912 }
2913
2914 /**
2915  * Get a resource interface at the specified index within a resource.
2916  *
2917  * @param handle - handle of resource
2918  * @param index - index of resource interface
2919  *
2920  * @return
2921  *    resourceinterface - if found
2922  *    NULL - not found
2923  */
2924 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
2925         uint8_t index) {
2926     OCResource *resource;
2927     OCResourceInterface *pointer;
2928     uint8_t i = 0;
2929
2930     // Find the specified resource
2931     resource = findResource((OCResource *) handle);
2932     if (!resource) {
2933         return NULL;
2934     }
2935
2936     // Make sure a resource has a resourceinterface
2937     if (!resource->rsrcInterface) {
2938         return NULL;
2939     }
2940
2941     // Iterate through the list
2942     pointer = resource->rsrcInterface;
2943
2944     while ((i < index) && pointer) {
2945         i++;
2946         pointer = pointer->next;
2947     }
2948     return pointer;
2949 }
2950
2951 /**
2952  * Determine if a request/response must be sent in a block transfer because it is too large to be
2953  * sent in a single PDU.  This function can be used for either a request or a response
2954  *
2955  * @param request  - NULL or pointer to request
2956  * @param response - NULL or pointer to response
2957  * @param size     - 0 or size of the request/response.  If 0, strlen is used for determining
2958  *                   the length of the request/response
2959  *
2960  * @return
2961  *    0 - packet transfer NOT required (i.e. normal request/response)
2962  *    1 - packet transfer required (i.e. block transfer needed)
2963  */
2964 uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size)
2965 {
2966     uint8_t result = 0;
2967
2968     // Determine if we are checking a request or a response
2969     if (request)
2970     {
2971         // If size is greater than 0, use it for the request size value, otherwise
2972         // assume request is null terminated and use strlen for size value
2973         if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH))
2974         {
2975             result = 1;
2976         }
2977     }
2978     else if (response)
2979     {
2980         // If size is greater than 0, use it for the response size value, otherwise
2981         // assume response is null terminated and use strlen for size value
2982         if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH))
2983         {
2984             result = 1;
2985         }
2986     }
2987     return result;
2988 }
2989
2990 /**
2991  * Retrieves a resource type based upon a uri string if the uri string contains only just one
2992  * resource attribute (and that has to be of type "rt").
2993  *
2994  * @remark This API malloc's memory for the resource type and newURI. Do not malloc resourceType
2995  * or newURI before passing in.
2996  *
2997  * @param uri - Valid URI for "requiredUri" parameter to OCDoResource API.
2998  * @param resourceType - The resource type to be populated; pass by reference.
2999  * @param newURI - Return URI without resourceType appended to the end of it. This is used to
3000  *                 ensure that the uri parameter is not modified; pass by reference.
3001  *
3002  * @return
3003  *  OC_STACK_INVALID_URI   - Returns this if the URI is invalid/NULL.
3004  *  OC_STACK_INVALID_PARAM - Returns this if the resourceType parameter is invalid/NULL.
3005  *  OC_STACK_OK            - Success
3006  */
3007 OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI)
3008 {
3009     if(!uri)
3010     {
3011         return OC_STACK_INVALID_URI;
3012     }
3013     if(!resourceType || !newURI)
3014     {
3015         return OC_STACK_INVALID_PARAM;
3016     }
3017     char * leftToken = NULL;
3018     char * tempURI = (char *) OCMalloc(strlen(uri) + 1);
3019     if(!tempURI)
3020     {
3021         goto exit;
3022     }
3023     strcpy(tempURI, uri);
3024     leftToken = strtok((char *)tempURI, "?");
3025
3026     while(leftToken != NULL)
3027     {
3028         if(strncmp(leftToken, "rt=", 3) == 0)
3029         {
3030             *resourceType = (unsigned char *) OCMalloc(strlen(leftToken)-3);
3031             if(!*resourceType)
3032             {
3033                 goto exit;
3034             }
3035             strcpy((char *)*resourceType, ((const char *)&leftToken[3]));
3036             break;
3037         }
3038         leftToken = strtok(NULL, "?");
3039     }
3040
3041     *newURI = tempURI;
3042
3043     return OC_STACK_OK;
3044
3045     exit:
3046         return OC_STACK_NO_MEMORY;
3047 }
3048
3049 const ServerID OCGetServerInstanceID(void)
3050 {
3051     static bool generated = false;
3052     static ServerID sid;
3053
3054     if(generated)
3055     {
3056         return sid;
3057     }
3058
3059     sid = OCGetRandom();
3060     generated = true;
3061     return sid;
3062 }
3063
3064 const char* OCGetServerInstanceIDString(void)
3065 {
3066     // max printed length of a base 10
3067     // uint32 is 10 characters, so 11 includes null.
3068     // This will change as the representation gets switched
3069     // to another value
3070     static char buffer[11];
3071     int n = sprintf(buffer, "%u", OCGetServerInstanceID());
3072     if (n < 0)
3073     {
3074         buffer[0]='\0';
3075     }
3076
3077     return buffer;
3078 }