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