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