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