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