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