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