/oic/res response based on the collection response structure
[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 if (strcmp(cbNode->requestUri, OC_RSRVD_RD_URI) == 0)
1177                     {
1178                         type = PAYLOAD_TYPE_RD;
1179                     }
1180                     else
1181                     {
1182                         OC_LOG_V(ERROR, TAG, "Unknown Payload type in Discovery: %d %s",
1183                                 cbNode->method, cbNode->requestUri);
1184                         return;
1185                     }
1186                 }
1187                 else if (cbNode->method == OC_REST_GET ||
1188                          cbNode->method == OC_REST_PUT ||
1189                          cbNode->method == OC_REST_POST ||
1190                          cbNode->method == OC_REST_OBSERVE ||
1191                          cbNode->method == OC_REST_OBSERVE_ALL ||
1192                          cbNode->method == OC_REST_DELETE)
1193                 {
1194                     char targetUri[MAX_URI_LENGTH];
1195                     snprintf(targetUri, MAX_URI_LENGTH, "%s?rt=%s",
1196                             OC_RSRVD_RD_URI, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH);
1197                     if (strcmp(targetUri, cbNode->requestUri) == 0)
1198                     {
1199                         type = PAYLOAD_TYPE_RD;
1200                     }
1201                     if (type == PAYLOAD_TYPE_INVALID)
1202                     {
1203                         OC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_REPRESENTATION: %d %s",
1204                                 cbNode->method, cbNode->requestUri);
1205                         type = PAYLOAD_TYPE_REPRESENTATION;
1206                     }
1207                 }
1208                 else
1209                 {
1210                     OC_LOG_V(ERROR, TAG, "Unknown Payload type: %d %s",
1211                             cbNode->method, cbNode->requestUri);
1212                     return;
1213                 }
1214
1215                 if(OC_STACK_OK != OCParsePayload(&response.payload,
1216                             type,
1217                             responseInfo->info.payload,
1218                             responseInfo->info.payloadSize))
1219                 {
1220                     OC_LOG(ERROR, TAG, "Error converting payload");
1221                     OCPayloadDestroy(response.payload);
1222                     return;
1223                 }
1224             }
1225
1226             response.numRcvdVendorSpecificHeaderOptions = 0;
1227             if(responseInfo->info.numOptions > 0)
1228             {
1229                 int start = 0;
1230                 //First option always with option ID is COAP_OPTION_OBSERVE if it is available.
1231                 if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
1232                 {
1233                     size_t i;
1234                     uint32_t observationOption;
1235                     uint8_t* optionData = (uint8_t*)responseInfo->info.options[0].optionData;
1236                     for (observationOption=0, i=0;
1237                             i<sizeof(uint32_t) && i<responseInfo->info.options[0].optionLength;
1238                             i++)
1239                     {
1240                         observationOption =
1241                             (observationOption << 8) | optionData[i];
1242                     }
1243                     response.sequenceNumber = observationOption;
1244
1245                     response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
1246                     start = 1;
1247                 }
1248                 else
1249                 {
1250                     response.numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
1251                 }
1252
1253                 if(response.numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
1254                 {
1255                     OC_LOG(ERROR, TAG, "#header options are more than MAX_HEADER_OPTIONS");
1256                     OCPayloadDestroy(response.payload);
1257                     return;
1258                 }
1259
1260                 for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
1261                 {
1262                     memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]),
1263                             &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
1264                 }
1265             }
1266
1267             if (cbNode->method == OC_REST_OBSERVE &&
1268                 response.sequenceNumber > OC_OFFSET_SEQUENCE_NUMBER &&
1269                 response.sequenceNumber <= cbNode->sequenceNumber)
1270             {
1271                 OC_LOG_V(INFO, TAG, "Received stale notification. Number :%d",
1272                                                  response.sequenceNumber);
1273             }
1274             else
1275             {
1276                 OCStackApplicationResult appFeedback = cbNode->callBack(cbNode->context,
1277                                                                         cbNode->handle,
1278                                                                         &response);
1279                 cbNode->sequenceNumber = response.sequenceNumber;
1280
1281                 if (appFeedback == OC_STACK_DELETE_TRANSACTION)
1282                 {
1283                     FindAndDeleteClientCB(cbNode);
1284                 }
1285                 else
1286                 {
1287                     // To keep discovery callbacks active.
1288                     cbNode->TTL = GetTicks(MAX_CB_TIMEOUT_SECONDS *
1289                                             MILLISECONDS_PER_SECOND);
1290                 }
1291             }
1292
1293             //Need to send ACK when the response is CON
1294             if(responseInfo->info.type == CA_MSG_CONFIRM)
1295             {
1296                 SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY,
1297                         CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0, NULL);
1298             }
1299
1300             OCPayloadDestroy(response.payload);
1301         }
1302         return;
1303     }
1304
1305     if(observer)
1306     {
1307         OC_LOG(INFO, TAG, "There is an observer associated with the response token");
1308         if(responseInfo->result == CA_EMPTY)
1309         {
1310             OC_LOG(INFO, TAG, "Receiving A ACK/RESET for this token");
1311             if(responseInfo->info.type == CA_MSG_RESET)
1312             {
1313                 OC_LOG(INFO, TAG, "This is a RESET");
1314                 OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
1315                         OC_OBSERVER_NOT_INTERESTED);
1316             }
1317             else if(responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
1318             {
1319                 OC_LOG(INFO, TAG, "This is a pure ACK");
1320                 OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
1321                         OC_OBSERVER_STILL_INTERESTED);
1322             }
1323         }
1324         else if(responseInfo->result == CA_RETRANSMIT_TIMEOUT)
1325         {
1326             OC_LOG(INFO, TAG, "Receiving Time Out for an observer");
1327             OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
1328                     OC_OBSERVER_FAILED_COMM);
1329         }
1330         return;
1331     }
1332
1333     if(!cbNode && !observer)
1334     {
1335         if(myStackMode == OC_CLIENT || myStackMode == OC_CLIENT_SERVER
1336            || myStackMode == OC_GATEWAY)
1337         {
1338             OC_LOG(INFO, TAG, "This is a client, but no cbNode was found for token");
1339             if(responseInfo->result == CA_EMPTY)
1340             {
1341                 OC_LOG(INFO, TAG, "Receiving CA_EMPTY in the ocstack");
1342             }
1343             else
1344             {
1345                 OC_LOG(INFO, TAG, "Received a message without callbacks. Sending RESET");
1346                 SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY,
1347                         CA_MSG_RESET, 0, NULL, NULL, 0, NULL);
1348             }
1349         }
1350
1351         if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER
1352            || myStackMode == OC_GATEWAY)
1353         {
1354             OC_LOG(INFO, TAG, "This is a server, but no observer was found for token");
1355             if (responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
1356             {
1357                 OC_LOG_V(INFO, TAG, "Received ACK at server for messageId : %d",
1358                                             responseInfo->info.messageId);
1359             }
1360             if (responseInfo->info.type == CA_MSG_RESET)
1361             {
1362                 OC_LOG_V(INFO, TAG, "Received RESET at server for messageId : %d",
1363                                             responseInfo->info.messageId);
1364             }
1365         }
1366
1367         return;
1368     }
1369
1370     OC_LOG(INFO, TAG, "Exit HandleCAResponses");
1371 }
1372
1373 /*
1374  * This function handles error response from CA
1375  * code shall be added to handle the errors
1376  */
1377 void HandleCAErrorResponse(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errrorInfo)
1378 {
1379     OC_LOG(INFO, TAG, "Enter HandleCAErrorResponse");
1380
1381     if(NULL == endPoint)
1382     {
1383         OC_LOG(ERROR, TAG, "endPoint is NULL");
1384         return;
1385     }
1386
1387     if(NULL == errrorInfo)
1388     {
1389         OC_LOG(ERROR, TAG, "errrorInfo is NULL");
1390         return;
1391     }
1392     OC_LOG(INFO, TAG, "Exit HandleCAErrorResponse");
1393 }
1394
1395 /*
1396  * This function sends out Direct Stack Responses. These are responses that are not coming
1397  * from the application entity handler. These responses have no payload and are usually ACKs,
1398  * RESETs or some error conditions that were caught by the stack.
1399  */
1400 OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16_t coapID,
1401         const CAResponseResult_t responseResult, const CAMessageType_t type,
1402         const uint8_t numOptions, const CAHeaderOption_t *options,
1403         CAToken_t token, uint8_t tokenLength, const char *resourceUri)
1404 {
1405     CAResponseInfo_t respInfo = {
1406         .result = responseResult
1407     };
1408     respInfo.info.messageId = coapID;
1409     respInfo.info.numOptions = numOptions;
1410     respInfo.info.options = (CAHeaderOption_t*)options;
1411     respInfo.info.payload = NULL;
1412     respInfo.info.token = token;
1413     respInfo.info.tokenLength = tokenLength;
1414     respInfo.info.type = type;
1415     respInfo.info.resourceUri = OICStrdup (resourceUri);
1416     respInfo.info.acceptFormat = CA_FORMAT_UNDEFINED;
1417
1418 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
1419     // Add the destination to route option from the endpoint->routeData.
1420     OCStackResult result = RMAddInfo(endPoint->routeData,
1421                                      &(respInfo.info.options),
1422                                      &(respInfo.info.numOptions));
1423     if(OC_STACK_OK != result)
1424     {
1425         OC_LOG_V(ERROR, TAG, "Add routing option failed [%d]", result);
1426         return result;
1427     }
1428 #endif
1429
1430     CAResult_t caResult = CASendResponse(endPoint, &respInfo);
1431
1432     // resourceUri in the info field is cloned in the CA layer and
1433     // thus ownership is still here.
1434     OICFree (respInfo.info.resourceUri);
1435
1436     if(CA_STATUS_OK != caResult)
1437     {
1438         OC_LOG(ERROR, TAG, "CASendResponse error");
1439         return CAResultToOCResult(caResult);
1440     }
1441     return OC_STACK_OK;
1442 }
1443
1444 //This function will be called back by CA layer when a request is received
1445 void HandleCARequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
1446 {
1447     OC_LOG(INFO, TAG, "Enter HandleCARequests");
1448     if(!endPoint)
1449     {
1450         OC_LOG(ERROR, TAG, "endPoint is NULL");
1451         return;
1452     }
1453
1454     if(!requestInfo)
1455     {
1456         OC_LOG(ERROR, TAG, "requestInfo is NULL");
1457         return;
1458     }
1459
1460 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
1461 #ifdef ROUTING_GATEWAY
1462     bool needRIHandling = false;
1463     /*
1464      * Routing manager is going to update either of endpoint or request or both.
1465      * This typecasting is done to avoid unnecessary duplication of Endpoint and requestInfo
1466      * RM can update "routeData" option in endPoint so that future RI requests can be sent to proper
1467      * destination. It can also remove "RM" coap header option before passing request / response to
1468      * RI as this option will make no sense to either RI or application.
1469      */
1470     OCStackResult ret = RMHandleRequest((CARequestInfo_t *)requestInfo, (CAEndpoint_t *)endPoint,
1471                                      &needRIHandling);
1472     if(OC_STACK_OK != ret || !needRIHandling)
1473     {
1474         OC_LOG_V(INFO, TAG, "Routing status![%d]. Not forwarding to RI", ret);
1475         return;
1476     }
1477 #endif
1478
1479     /*
1480      * Put source in sender endpoint so that the next packet from application can be routed to
1481      * proper destination and remove RM header option.
1482      */
1483     RMUpdateInfo((CAHeaderOption_t **) &(requestInfo->info.options),
1484                  (uint8_t *) &(requestInfo->info.numOptions),
1485                  (CAEndpoint_t *) endPoint);
1486 #endif
1487
1488     OCStackResult requestResult = OC_STACK_ERROR;
1489
1490     if(myStackMode == OC_CLIENT)
1491     {
1492         //TODO: should the client be responding to requests?
1493         return;
1494     }
1495
1496     OCServerProtocolRequest serverRequest = {0};
1497
1498     OC_LOG_V(INFO, TAG, "Endpoint URI : %s", requestInfo->info.resourceUri);
1499
1500     char * uriWithoutQuery = NULL;
1501     char * query  = NULL;
1502
1503     requestResult = getQueryFromUri(requestInfo->info.resourceUri, &query, &uriWithoutQuery);
1504
1505     if (requestResult != OC_STACK_OK || !uriWithoutQuery)
1506     {
1507         OC_LOG_V(ERROR, TAG, "getQueryFromUri() failed with OC error code %d\n", requestResult);
1508         return;
1509     }
1510     OC_LOG_V(INFO, TAG, "URI without query: %s", uriWithoutQuery);
1511     OC_LOG_V(INFO, TAG, "Query : %s", query);
1512
1513     if(strlen(uriWithoutQuery) < MAX_URI_LENGTH)
1514     {
1515         OICStrcpy(serverRequest.resourceUrl, sizeof(serverRequest.resourceUrl), uriWithoutQuery);
1516         OICFree(uriWithoutQuery);
1517     }
1518     else
1519     {
1520         OC_LOG(ERROR, TAG, "URI length exceeds MAX_URI_LENGTH.");
1521         OICFree(uriWithoutQuery);
1522         OICFree(query);
1523         return;
1524     }
1525
1526     if(query)
1527     {
1528         if(strlen(query) < MAX_QUERY_LENGTH)
1529         {
1530             OICStrcpy(serverRequest.query, sizeof(serverRequest.query), query);
1531             OICFree(query);
1532         }
1533         else
1534         {
1535             OC_LOG(ERROR, TAG, "Query length exceeds MAX_QUERY_LENGTH.");
1536             OICFree(query);
1537             return;
1538         }
1539     }
1540
1541     if ((requestInfo->info.payload) && (0 < requestInfo->info.payloadSize))
1542     {
1543         serverRequest.reqTotalSize = requestInfo->info.payloadSize;
1544         serverRequest.payload = (uint8_t *) OICMalloc(requestInfo->info.payloadSize);
1545         memcpy (serverRequest.payload, requestInfo->info.payload,
1546                 requestInfo->info.payloadSize);
1547     }
1548     else
1549     {
1550         serverRequest.reqTotalSize = 0;
1551     }
1552
1553     switch (requestInfo->method)
1554     {
1555         case CA_GET:
1556             serverRequest.method = OC_REST_GET;
1557             break;
1558         case CA_PUT:
1559             serverRequest.method = OC_REST_PUT;
1560             break;
1561         case CA_POST:
1562             serverRequest.method = OC_REST_POST;
1563             break;
1564         case CA_DELETE:
1565             serverRequest.method = OC_REST_DELETE;
1566             break;
1567         default:
1568             OC_LOG_V(ERROR, TAG, "Received CA method %d not supported", requestInfo->method);
1569             SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_REQ,
1570                         requestInfo->info.type, requestInfo->info.numOptions,
1571                         requestInfo->info.options, requestInfo->info.token,
1572                         requestInfo->info.tokenLength, requestInfo->info.resourceUri);
1573             OICFree(serverRequest.payload);
1574             return;
1575     }
1576
1577     OC_LOG_BUFFER(INFO, TAG, (const uint8_t *)requestInfo->info.token,
1578             requestInfo->info.tokenLength);
1579     serverRequest.requestToken = (CAToken_t)OICMalloc(requestInfo->info.tokenLength);
1580     serverRequest.tokenLength = requestInfo->info.tokenLength;
1581
1582     if (!serverRequest.requestToken)
1583     {
1584         OC_LOG(FATAL, TAG, "Allocation for token failed.");
1585         SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_INTERNAL_SERVER_ERROR,
1586                 requestInfo->info.type, requestInfo->info.numOptions,
1587                 requestInfo->info.options, requestInfo->info.token,
1588                 requestInfo->info.tokenLength, requestInfo->info.resourceUri);
1589         OICFree(serverRequest.payload);
1590         return;
1591     }
1592     memcpy(serverRequest.requestToken, requestInfo->info.token, requestInfo->info.tokenLength);
1593
1594     switch (requestInfo->info.acceptFormat)
1595     {
1596         case CA_FORMAT_APPLICATION_CBOR:
1597             serverRequest.acceptFormat = OC_FORMAT_CBOR;
1598             break;
1599         case CA_FORMAT_UNDEFINED:
1600             serverRequest.acceptFormat = OC_FORMAT_UNDEFINED;
1601             break;
1602         default:
1603             serverRequest.acceptFormat = OC_FORMAT_UNSUPPORTED;
1604     }
1605
1606     if (requestInfo->info.type == CA_MSG_CONFIRM)
1607     {
1608         serverRequest.qos = OC_HIGH_QOS;
1609     }
1610     else
1611     {
1612         serverRequest.qos = OC_LOW_QOS;
1613     }
1614     // CA does not need the following field
1615     // Are we sure CA does not need them? how is it responding to multicast
1616     serverRequest.delayedResNeeded = 0;
1617
1618     serverRequest.coapID = requestInfo->info.messageId;
1619
1620     CopyEndpointToDevAddr(endPoint, &serverRequest.devAddr);
1621
1622     // copy vendor specific header options
1623     uint8_t tempNum = (requestInfo->info.numOptions);
1624     GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &tempNum);
1625     if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
1626     {
1627         OC_LOG(ERROR, TAG,
1628                 "The request info numOptions is greater than MAX_HEADER_OPTIONS");
1629         SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_OPT,
1630                 requestInfo->info.type, requestInfo->info.numOptions,
1631                 requestInfo->info.options, requestInfo->info.token,
1632                 requestInfo->info.tokenLength, requestInfo->info.resourceUri);
1633         OICFree(serverRequest.payload);
1634         OICFree(serverRequest.requestToken);
1635         return;
1636     }
1637     serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
1638     if (serverRequest.numRcvdVendorSpecificHeaderOptions)
1639     {
1640         memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
1641             sizeof(CAHeaderOption_t)*tempNum);
1642     }
1643
1644     requestResult = HandleStackRequests (&serverRequest);
1645
1646     // Send ACK to client as precursor to slow response
1647     if(requestResult == OC_STACK_SLOW_RESOURCE)
1648     {
1649         SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_EMPTY,
1650                     CA_MSG_ACKNOWLEDGE,0, NULL, NULL, 0, NULL);
1651     }
1652     else if(requestResult != OC_STACK_OK)
1653     {
1654         OC_LOG_V(ERROR, TAG, "HandleStackRequests failed. error: %d", requestResult);
1655
1656         CAResponseResult_t stackResponse =
1657             OCToCAStackResult(requestResult, serverRequest.method);
1658
1659         SendDirectStackResponse(endPoint, requestInfo->info.messageId, stackResponse,
1660                 requestInfo->info.type, requestInfo->info.numOptions,
1661                 requestInfo->info.options, requestInfo->info.token,
1662                 requestInfo->info.tokenLength, requestInfo->info.resourceUri);
1663     }
1664     // requestToken is fed to HandleStackRequests, which then goes to AddServerRequest.
1665     // The token is copied in there, and is thus still owned by this function.
1666     OICFree(serverRequest.payload);
1667     OICFree(serverRequest.requestToken);
1668     OC_LOG(INFO, TAG, "Exit HandleCARequests");
1669 }
1670
1671 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
1672 {
1673     OC_LOG(INFO, TAG, "Entering HandleStackRequests (OCStack Layer)");
1674     OCStackResult result = OC_STACK_ERROR;
1675     ResourceHandling resHandling;
1676     OCResource *resource;
1677     if(!protocolRequest)
1678     {
1679         OC_LOG(ERROR, TAG, "protocolRequest is NULL");
1680         return OC_STACK_INVALID_PARAM;
1681     }
1682
1683     OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken,
1684             protocolRequest->tokenLength);
1685     if(!request)
1686     {
1687         OC_LOG(INFO, TAG, "This is a new Server Request");
1688         result = AddServerRequest(&request, protocolRequest->coapID,
1689                 protocolRequest->delayedResNeeded, 0, protocolRequest->method,
1690                 protocolRequest->numRcvdVendorSpecificHeaderOptions,
1691                 protocolRequest->observationOption, protocolRequest->qos,
1692                 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
1693                 protocolRequest->payload, protocolRequest->requestToken,
1694                 protocolRequest->tokenLength, protocolRequest->resourceUrl,
1695                 protocolRequest->reqTotalSize, protocolRequest->acceptFormat,
1696                 &protocolRequest->devAddr);
1697         if (OC_STACK_OK != result)
1698         {
1699             OC_LOG(ERROR, TAG, "Error adding server request");
1700             return result;
1701         }
1702
1703         if(!request)
1704         {
1705             OC_LOG(ERROR, TAG, "Out of Memory");
1706             return OC_STACK_NO_MEMORY;
1707         }
1708
1709         if(!protocolRequest->reqMorePacket)
1710         {
1711             request->requestComplete = 1;
1712         }
1713     }
1714     else
1715     {
1716         OC_LOG(INFO, TAG, "This is either a repeated or blocked Server Request");
1717     }
1718
1719     if(request->requestComplete)
1720     {
1721         OC_LOG(INFO, TAG, "This Server Request is complete");
1722         result = DetermineResourceHandling (request, &resHandling, &resource);
1723         if (result == OC_STACK_OK)
1724         {
1725             result = ProcessRequest(resHandling, resource, request);
1726         }
1727     }
1728     else
1729     {
1730         OC_LOG(INFO, TAG, "This Server Request is incomplete");
1731         result = OC_STACK_CONTINUE;
1732     }
1733     return result;
1734 }
1735
1736 bool validatePlatformInfo(OCPlatformInfo info)
1737 {
1738
1739     if (!info.platformID)
1740     {
1741         OC_LOG(ERROR, TAG, "No platform ID found.");
1742         return false;
1743     }
1744
1745     if (info.manufacturerName)
1746     {
1747         size_t lenManufacturerName = strlen(info.manufacturerName);
1748
1749         if(lenManufacturerName == 0 || lenManufacturerName > MAX_MANUFACTURER_NAME_LENGTH)
1750         {
1751             OC_LOG(ERROR, TAG, "Manufacturer name fails length requirements.");
1752             return false;
1753         }
1754     }
1755     else
1756     {
1757         OC_LOG(ERROR, TAG, "No manufacturer name present");
1758         return false;
1759     }
1760
1761     if (info.manufacturerUrl)
1762     {
1763         if(strlen(info.manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH)
1764         {
1765             OC_LOG(ERROR, TAG, "Manufacturer url fails length requirements.");
1766             return false;
1767         }
1768     }
1769     return true;
1770 }
1771
1772 //-----------------------------------------------------------------------------
1773 // Public APIs
1774 //-----------------------------------------------------------------------------
1775 #ifdef RA_ADAPTER
1776 OCStackResult OCSetRAInfo(const OCRAInfo_t *raInfo)
1777 {
1778     if (!raInfo           ||
1779         !raInfo->username ||
1780         !raInfo->hostname ||
1781         !raInfo->xmpp_domain)
1782     {
1783
1784         return OC_STACK_INVALID_PARAM;
1785     }
1786     OCStackResult result = CAResultToOCResult(CASetRAInfo((const CARAInfo_t *) raInfo));
1787     gRASetInfo = (result == OC_STACK_OK)? true : false;
1788
1789     return result;
1790 }
1791 #endif
1792
1793 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
1794 {
1795     (void) ipAddr;
1796     (void) port;
1797     return OCInit1(mode, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS);
1798 }
1799
1800 OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlags clientFlags)
1801 {
1802     if(stackState == OC_STACK_INITIALIZED)
1803     {
1804         OC_LOG(INFO, TAG, "Subsequent calls to OCInit() without calling \
1805                 OCStop() between them are ignored.");
1806         return OC_STACK_OK;
1807     }
1808
1809 #ifndef ROUTING_GATEWAY
1810     if (OC_GATEWAY == mode)
1811     {
1812         OC_LOG(ERROR, TAG, "Routing Manager not supported");
1813         return OC_STACK_INVALID_PARAM;
1814     }
1815 #endif
1816
1817 #ifdef RA_ADAPTER
1818     if(!gRASetInfo)
1819     {
1820         OC_LOG(ERROR, TAG, "Need to call OCSetRAInfo before calling OCInit");
1821         return OC_STACK_ERROR;
1822     }
1823 #endif
1824
1825     OCStackResult result = OC_STACK_ERROR;
1826     OC_LOG(INFO, TAG, "Entering OCInit");
1827
1828     // Validate mode
1829     if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)
1830         || (mode == OC_GATEWAY)))
1831     {
1832         OC_LOG(ERROR, TAG, "Invalid mode");
1833         return OC_STACK_ERROR;
1834     }
1835     myStackMode = mode;
1836
1837     if (mode == OC_CLIENT || mode == OC_CLIENT_SERVER || mode == OC_GATEWAY)
1838     {
1839         caglobals.client = true;
1840     }
1841     if (mode == OC_SERVER || mode == OC_CLIENT_SERVER || mode == OC_GATEWAY)
1842     {
1843         caglobals.server = true;
1844     }
1845
1846     caglobals.serverFlags = (CATransportFlags_t)serverFlags;
1847     if (!(caglobals.serverFlags & CA_IPFAMILY_MASK))
1848     {
1849         caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4|CA_IPV6);
1850     }
1851     caglobals.clientFlags = (CATransportFlags_t)clientFlags;
1852     if (!(caglobals.clientFlags & CA_IPFAMILY_MASK))
1853     {
1854         caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4|CA_IPV6);
1855     }
1856
1857 #ifdef TCP_ADAPTER
1858     if (!(caglobals.serverFlags & CA_IPFAMILY_MASK))
1859     {
1860         caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4);
1861     }
1862     if (!(caglobals.clientFlags & CA_IPFAMILY_MASK))
1863     {
1864         caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4);
1865     }
1866 #endif
1867
1868     defaultDeviceHandler = NULL;
1869     defaultDeviceHandlerCallbackParameter = NULL;
1870     OCSeedRandom();
1871
1872     result = CAResultToOCResult(CAInitialize());
1873     VERIFY_SUCCESS(result, OC_STACK_OK);
1874
1875     result = CAResultToOCResult(OCSelectNetwork());
1876     VERIFY_SUCCESS(result, OC_STACK_OK);
1877
1878     switch (myStackMode)
1879     {
1880         case OC_CLIENT:
1881                         CARegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
1882             result = CAResultToOCResult(CAStartDiscoveryServer());
1883             OC_LOG(INFO, TAG, "Client mode: CAStartDiscoveryServer");
1884             break;
1885         case OC_SERVER:
1886                         SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
1887             result = CAResultToOCResult(CAStartListeningServer());
1888             OC_LOG(INFO, TAG, "Server mode: CAStartListeningServer");
1889             break;
1890         case OC_CLIENT_SERVER:
1891         case OC_GATEWAY:
1892                         SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
1893             result = CAResultToOCResult(CAStartListeningServer());
1894             if(result == OC_STACK_OK)
1895             {
1896                 result = CAResultToOCResult(CAStartDiscoveryServer());
1897             }
1898             break;
1899     }
1900     VERIFY_SUCCESS(result, OC_STACK_OK);
1901
1902 #ifdef WITH_PRESENCE
1903     PresenceTimeOutSize = sizeof (PresenceTimeOut) / sizeof (PresenceTimeOut[0]) - 1;
1904 #endif // WITH_PRESENCE
1905
1906     //Update Stack state to initialized
1907     stackState = OC_STACK_INITIALIZED;
1908
1909     // Initialize resource
1910     if(myStackMode != OC_CLIENT)
1911     {
1912         result = initResources();
1913     }
1914
1915     // Initialize the SRM Policy Engine
1916     if(result == OC_STACK_OK)
1917     {
1918         result = SRMInitPolicyEngine();
1919         // TODO after BeachHead delivery: consolidate into single SRMInit()
1920     }
1921
1922 #ifdef ROUTING_GATEWAY
1923     if (OC_GATEWAY == myStackMode)
1924     {
1925         result = RMInitialize();
1926     }
1927 #endif
1928
1929 exit:
1930     if(result != OC_STACK_OK)
1931     {
1932         OC_LOG(ERROR, TAG, "Stack initialization error");
1933         deleteAllResources();
1934         CATerminate();
1935         stackState = OC_STACK_UNINITIALIZED;
1936     }
1937     return result;
1938 }
1939
1940 OCStackResult OCStop()
1941 {
1942     OC_LOG(INFO, TAG, "Entering OCStop");
1943
1944     if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
1945     {
1946         OC_LOG(DEBUG, TAG, "Stack already stopping, exiting");
1947         return OC_STACK_OK;
1948     }
1949     else if (stackState != OC_STACK_INITIALIZED)
1950     {
1951         OC_LOG(ERROR, TAG, "Stack not initialized");
1952         return OC_STACK_ERROR;
1953     }
1954
1955     stackState = OC_STACK_UNINIT_IN_PROGRESS;
1956
1957 #ifdef WITH_PRESENCE
1958     // Ensure that the TTL associated with ANY and ALL presence notifications originating from
1959     // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
1960     presenceResource.presenceTTL = 0;
1961 #endif // WITH_PRESENCE
1962
1963 #ifdef ROUTING_GATEWAY
1964     if (OC_GATEWAY == myStackMode)
1965     {
1966         RMTerminate();
1967     }
1968 #endif
1969
1970     // Free memory dynamically allocated for resources
1971     deleteAllResources();
1972     DeleteDeviceInfo();
1973     DeletePlatformInfo();
1974     CATerminate();
1975     // Remove all observers
1976     DeleteObserverList();
1977     // Remove all the client callbacks
1978     DeleteClientCBList();
1979
1980         // De-init the SRM Policy Engine
1981     // TODO after BeachHead delivery: consolidate into single SRMDeInit()
1982     SRMDeInitPolicyEngine();
1983
1984
1985     stackState = OC_STACK_UNINITIALIZED;
1986     return OC_STACK_OK;
1987 }
1988
1989 CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
1990 {
1991     switch (qos)
1992     {
1993         case OC_HIGH_QOS:
1994             return CA_MSG_CONFIRM;
1995         case OC_LOW_QOS:
1996         case OC_MEDIUM_QOS:
1997         case OC_NA_QOS:
1998         default:
1999             return CA_MSG_NONCONFIRM;
2000     }
2001 }
2002
2003 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
2004 {
2005     char *query;
2006
2007     query = strchr (inputUri, '?');
2008
2009     if (query != NULL)
2010     {
2011         if((query - inputUri) > MAX_URI_LENGTH)
2012         {
2013             return OC_STACK_INVALID_URI;
2014         }
2015
2016         if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
2017         {
2018             return OC_STACK_INVALID_QUERY;
2019         }
2020     }
2021     else if(uriLen > MAX_URI_LENGTH)
2022     {
2023         return OC_STACK_INVALID_URI;
2024     }
2025     return OC_STACK_OK;
2026 }
2027
2028 /**
2029  *  A request uri consists of the following components in order:
2030  *                              example
2031  *  optionally one of
2032  *      CoAP over UDP prefix    "coap://"
2033  *      CoAP over TCP prefix    "coap+tcp://"
2034  *  optionally one of
2035  *      IPv6 address            "[1234::5678]"
2036  *      IPv4 address            "192.168.1.1"
2037  *  optional port               ":5683"
2038  *  resource uri                "/oc/core..."
2039  *
2040  *  for PRESENCE requests, extract resource type.
2041  */
2042 static OCStackResult ParseRequestUri(const char *fullUri,
2043                                         OCTransportAdapter adapter,
2044                                         OCTransportFlags flags,
2045                                         OCDevAddr **devAddr,
2046                                         char **resourceUri,
2047                                         char **resourceType)
2048 {
2049     VERIFY_NON_NULL(fullUri, FATAL, OC_STACK_INVALID_CALLBACK);
2050
2051     OCStackResult result = OC_STACK_OK;
2052     OCDevAddr *da = NULL;
2053     char *colon = NULL;
2054     char *end;
2055
2056     // provide defaults for all returned values
2057     if (devAddr)
2058     {
2059         *devAddr = NULL;
2060     }
2061     if (resourceUri)
2062     {
2063         *resourceUri = NULL;
2064     }
2065     if (resourceType)
2066     {
2067         *resourceType = NULL;
2068     }
2069
2070     // delimit url prefix, if any
2071     const char *start = fullUri;
2072     char *slash2 = strstr(start, "//");
2073     if (slash2)
2074     {
2075         start = slash2 + 2;
2076     }
2077     char *slash = strchr(start, '/');
2078     if (!slash)
2079     {
2080         return OC_STACK_INVALID_URI;
2081     }
2082
2083 #ifdef TCP_ADAPTER
2084     // process url scheme
2085     size_t prefixLen = slash2 - fullUri;
2086     bool istcp = false;
2087     if (prefixLen)
2088     {
2089         if ((prefixLen == sizeof(COAP_TCP) - 1) && (!strncmp(fullUri, COAP_TCP, prefixLen)))
2090         {
2091             istcp = true;
2092         }
2093     }
2094 #endif
2095
2096     // TODO: this logic should come in with unit tests exercising the various strings
2097     // processs url prefix, if any
2098     size_t urlLen = slash - start;
2099     // port
2100     uint16_t port = 0;
2101     size_t len = 0;
2102     if (urlLen && devAddr)
2103     {   // construct OCDevAddr
2104         if (start[0] == '[')
2105         {   // ipv6 address
2106             char *close = strchr(++start, ']');
2107             if (!close || close > slash)
2108             {
2109                 return OC_STACK_INVALID_URI;
2110             }
2111             end = close;
2112             if (close[1] == ':')
2113             {
2114                 colon = close + 1;
2115             }
2116             adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
2117             flags = (OCTransportFlags)(flags | OC_IP_USE_V6);
2118         }
2119         else
2120         {
2121             char *dot = strchr(start, '.');
2122             if (dot && dot < slash)
2123             {   // ipv4 address
2124                 colon = strchr(start, ':');
2125                 end = (colon && colon < slash) ? colon : slash;
2126 #ifdef TCP_ADAPTER
2127                 if (istcp)
2128                 {   // coap over tcp
2129                     adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_TCP);
2130                 }
2131                 else
2132 #endif
2133                 {
2134                     adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
2135                     flags = (OCTransportFlags)(flags | OC_IP_USE_V4);
2136                 }
2137             }
2138             else
2139             {   // MAC address
2140                 end = slash;
2141             }
2142         }
2143         len = end - start;
2144         if (len >= sizeof(da->addr))
2145         {
2146             return OC_STACK_INVALID_URI;
2147         }
2148         // collect port, if any
2149         if (colon && colon < slash)
2150         {
2151             for (colon++; colon < slash; colon++)
2152             {
2153                 char c = colon[0];
2154                 if (c < '0' || c > '9')
2155                 {
2156                     return OC_STACK_INVALID_URI;
2157                 }
2158                 port = 10 * port + c - '0';
2159             }
2160         }
2161
2162         len = end - start;
2163         if (len >= sizeof(da->addr))
2164         {
2165             return OC_STACK_INVALID_URI;
2166         }
2167
2168         da = (OCDevAddr *)OICCalloc(sizeof (OCDevAddr), 1);
2169         if (!da)
2170         {
2171             return OC_STACK_NO_MEMORY;
2172         }
2173         OICStrcpyPartial(da->addr, sizeof(da->addr), start, len);
2174         da->port = port;
2175         da->adapter = adapter;
2176         da->flags = flags;
2177         if (!strncmp(fullUri, "coaps:", 6))
2178         {
2179             da->flags = (OCTransportFlags)(da->flags|CA_SECURE);
2180         }
2181         *devAddr = da;
2182     }
2183
2184     // process resource uri, if any
2185     if (slash)
2186     {   // request uri and query
2187         size_t ulen = strlen(slash); // resource uri length
2188         size_t tlen = 0;      // resource type length
2189         char *type = NULL;
2190
2191         static const char strPresence[] = "/oic/ad?rt=";
2192         static const size_t lenPresence = sizeof(strPresence) - 1;
2193         if (!strncmp(slash, strPresence, lenPresence))
2194         {
2195             type = slash + lenPresence;
2196             tlen = ulen - lenPresence;
2197         }
2198         // resource uri
2199         if (resourceUri)
2200         {
2201             *resourceUri = (char *)OICMalloc(ulen + 1);
2202             if (!*resourceUri)
2203             {
2204                 result = OC_STACK_NO_MEMORY;
2205                 goto error;
2206             }
2207             strcpy(*resourceUri, slash);
2208         }
2209         // resource type
2210         if (type && resourceType)
2211         {
2212             *resourceType = (char *)OICMalloc(tlen + 1);
2213             if (!*resourceType)
2214             {
2215                 result = OC_STACK_NO_MEMORY;
2216                 goto error;
2217             }
2218
2219             OICStrcpy(*resourceType, (tlen+1), type);
2220         }
2221     }
2222
2223     return OC_STACK_OK;
2224
2225 error:
2226     // free all returned values
2227     if (devAddr)
2228     {
2229         OICFree(*devAddr);
2230     }
2231     if (resourceUri)
2232     {
2233         OICFree(*resourceUri);
2234     }
2235     if (resourceType)
2236     {
2237         OICFree(*resourceType);
2238     }
2239     return result;
2240 }
2241
2242 static OCStackResult OCPreparePresence(CAEndpoint_t *endpoint,
2243                                         char *resourceUri, char **requestUri)
2244 {
2245     char uri[CA_MAX_URI_LENGTH];
2246
2247     FormCanonicalPresenceUri(endpoint, resourceUri, uri);
2248
2249     *requestUri = OICStrdup(uri);
2250     if (!*requestUri)
2251     {
2252         return OC_STACK_NO_MEMORY;
2253     }
2254
2255     return OC_STACK_OK;
2256 }
2257
2258 /**
2259  * Discover or Perform requests on a specified resource
2260  */
2261 OCStackResult OCDoResource(OCDoHandle *handle,
2262                             OCMethod method,
2263                             const char *requestUri,
2264                             const OCDevAddr *destination,
2265                             OCPayload* payload,
2266                             OCConnectivityType connectivityType,
2267                             OCQualityOfService qos,
2268                             OCCallbackData *cbData,
2269                             OCHeaderOption *options,
2270                             uint8_t numOptions)
2271 {
2272     OC_LOG(INFO, TAG, "Entering OCDoResource");
2273
2274     // Validate input parameters
2275     VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
2276     VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
2277     VERIFY_NON_NULL(requestUri , FATAL, OC_STACK_INVALID_URI);
2278
2279     OCStackResult result = OC_STACK_ERROR;
2280     CAResult_t caResult;
2281     CAToken_t token = NULL;
2282     uint8_t tokenLength = CA_MAX_TOKEN_LEN;
2283     ClientCB *clientCB = NULL;
2284     OCDoHandle resHandle = NULL;
2285     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2286     OCDevAddr tmpDevAddr = { OC_DEFAULT_ADAPTER };
2287     uint32_t ttl = 0;
2288     OCTransportAdapter adapter;
2289     OCTransportFlags flags;
2290     // the request contents are put here
2291     CARequestInfo_t requestInfo = {.method = CA_GET};
2292     // requestUri  will be parsed into the following three variables
2293     OCDevAddr *devAddr = NULL;
2294     char *resourceUri = NULL;
2295     char *resourceType = NULL;
2296
2297     // To track if memory is allocated for additional header options
2298     uint8_t hdrOptionMemAlloc = 0;
2299
2300     // This validation is broken, but doesn't cause harm
2301     size_t uriLen = strlen(requestUri );
2302     if ((result = verifyUriQueryLength(requestUri , uriLen)) != OC_STACK_OK)
2303     {
2304         goto exit;
2305     }
2306
2307     /*
2308      * Support original behavior with address on resourceUri argument.
2309      */
2310     adapter = (OCTransportAdapter)(connectivityType >> CT_ADAPTER_SHIFT);
2311     flags = (OCTransportFlags)(connectivityType & CT_MASK_FLAGS);
2312
2313     result = ParseRequestUri(requestUri, adapter, flags, &devAddr, &resourceUri, &resourceType);
2314
2315     if (result != OC_STACK_OK)
2316     {
2317         OC_LOG_V(DEBUG, TAG, "Unable to parse uri: %s", requestUri);
2318         goto exit;
2319     }
2320
2321     switch (method)
2322     {
2323     case OC_REST_GET:
2324     case OC_REST_OBSERVE:
2325     case OC_REST_OBSERVE_ALL:
2326     case OC_REST_CANCEL_OBSERVE:
2327         requestInfo.method = CA_GET;
2328         break;
2329     case OC_REST_PUT:
2330         requestInfo.method = CA_PUT;
2331         break;
2332     case OC_REST_POST:
2333         requestInfo.method = CA_POST;
2334         break;
2335     case OC_REST_DELETE:
2336         requestInfo.method = CA_DELETE;
2337         break;
2338     case OC_REST_DISCOVER:
2339         qos = OC_LOW_QOS;
2340         if (destination || devAddr)
2341         {
2342             requestInfo.isMulticast = false;
2343         }
2344         else
2345         {
2346             tmpDevAddr.adapter = adapter;
2347             tmpDevAddr.flags = flags;
2348             destination = &tmpDevAddr;
2349             requestInfo.isMulticast = true;
2350         }
2351         // CA_DISCOVER will become GET and isMulticast
2352         requestInfo.method = CA_GET;
2353         break;
2354 #ifdef WITH_PRESENCE
2355     case OC_REST_PRESENCE:
2356         // Replacing method type with GET because "presence"
2357         // is a stack layer only implementation.
2358         requestInfo.method = CA_GET;
2359         break;
2360 #endif
2361     default:
2362         result = OC_STACK_INVALID_METHOD;
2363         goto exit;
2364     }
2365
2366     if (!devAddr && !destination)
2367     {
2368         OC_LOG(DEBUG, TAG, "no devAddr and no destination");
2369         result = OC_STACK_INVALID_PARAM;
2370         goto exit;
2371     }
2372
2373     /* If not original behavior, use destination argument */
2374     if (destination && !devAddr)
2375     {
2376         devAddr = (OCDevAddr *)OICMalloc(sizeof (OCDevAddr));
2377         if (!devAddr)
2378         {
2379             result = OC_STACK_NO_MEMORY;
2380             goto exit;
2381         }
2382         *devAddr = *destination;
2383     }
2384
2385     resHandle = GenerateInvocationHandle();
2386     if (!resHandle)
2387     {
2388         result = OC_STACK_NO_MEMORY;
2389         goto exit;
2390     }
2391
2392     caResult = CAGenerateToken(&token, tokenLength);
2393     if (caResult != CA_STATUS_OK)
2394     {
2395         OC_LOG(ERROR, TAG, "CAGenerateToken error");
2396         result= OC_STACK_ERROR;
2397         goto exit;
2398     }
2399
2400     // fill in request data
2401     requestInfo.info.type = qualityOfServiceToMessageType(qos);
2402     requestInfo.info.token = token;
2403     requestInfo.info.tokenLength = tokenLength;
2404     requestInfo.info.resourceUri = resourceUri;
2405
2406     if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
2407     {
2408         result = CreateObserveHeaderOption (&(requestInfo.info.options),
2409                                     options, numOptions, OC_OBSERVE_REGISTER);
2410         if (result != OC_STACK_OK)
2411         {
2412             goto exit;
2413         }
2414         hdrOptionMemAlloc = 1;
2415         requestInfo.info.numOptions = numOptions + 1;
2416     }
2417     else
2418     {
2419         requestInfo.info.options = (CAHeaderOption_t*)options;
2420         requestInfo.info.numOptions = numOptions;
2421     }
2422
2423     CopyDevAddrToEndpoint(devAddr, &endpoint);
2424
2425     if(payload)
2426     {
2427         if((result =
2428             OCConvertPayload(payload, &requestInfo.info.payload, &requestInfo.info.payloadSize))
2429                 != OC_STACK_OK)
2430         {
2431             OC_LOG(ERROR, TAG, "Failed to create CBOR Payload");
2432             goto exit;
2433         }
2434         requestInfo.info.payloadFormat = CA_FORMAT_APPLICATION_CBOR;
2435     }
2436     else
2437     {
2438         requestInfo.info.payload = NULL;
2439         requestInfo.info.payloadSize = 0;
2440         requestInfo.info.payloadFormat = CA_FORMAT_UNDEFINED;
2441     }
2442
2443     if (result != OC_STACK_OK)
2444     {
2445         OC_LOG(ERROR, TAG, "CACreateEndpoint error");
2446         goto exit;
2447     }
2448
2449     // prepare for response
2450 #ifdef WITH_PRESENCE
2451     if (method == OC_REST_PRESENCE)
2452     {
2453         char *presenceUri = NULL;
2454         result = OCPreparePresence(&endpoint, resourceUri, &presenceUri);
2455         if (OC_STACK_OK != result)
2456         {
2457             goto exit;
2458         }
2459
2460         // Assign full presence uri as coap://ip:port/oic/ad to add to callback list.
2461         // Presence notification will form a canonical uri to
2462         // look for callbacks into the application.
2463         resourceUri = presenceUri;
2464     }
2465 #endif
2466
2467     ttl = GetTicks(MAX_CB_TIMEOUT_SECONDS * MILLISECONDS_PER_SECOND);
2468     result = AddClientCB(&clientCB, cbData, token, tokenLength, &resHandle,
2469                             method, devAddr, resourceUri, resourceType, ttl);
2470     if (OC_STACK_OK != result)
2471     {
2472         goto exit;
2473     }
2474
2475     devAddr = NULL;       // Client CB list entry now owns it
2476     resourceUri = NULL;   // Client CB list entry now owns it
2477     resourceType = NULL;  // Client CB list entry now owns it
2478
2479     // send request
2480     result = OCSendRequest(&endpoint, &requestInfo);
2481     if (OC_STACK_OK != result)
2482     {
2483         goto exit;
2484     }
2485
2486     if (handle)
2487     {
2488         *handle = resHandle;
2489     }
2490
2491 exit:
2492     if (result != OC_STACK_OK)
2493     {
2494         OC_LOG(ERROR, TAG, "OCDoResource error");
2495         FindAndDeleteClientCB(clientCB);
2496         CADestroyToken(token);
2497         if (handle)
2498         {
2499             *handle = NULL;
2500         }
2501         OICFree(resHandle);
2502     }
2503
2504     // This is the owner of the payload object, so we free it
2505     OCPayloadDestroy(payload);
2506     OICFree(requestInfo.info.payload);
2507     OICFree(devAddr);
2508     OICFree(resourceUri);
2509     OICFree(resourceType);
2510     if (hdrOptionMemAlloc)
2511     {
2512         OICFree(requestInfo.info.options);
2513     }
2514     return result;
2515 }
2516
2517 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
2518         uint8_t numOptions)
2519 {
2520     /*
2521      * This ftn is implemented one of two ways in the case of observation:
2522      *
2523      * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
2524      *      Remove the callback associated on client side.
2525      *      When the next notification comes in from server,
2526      *      reply with RESET message to server.
2527      *      Keep in mind that the server will react to RESET only
2528      *      if the last notification was sent as CON
2529      *
2530      * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
2531      *      and it is associated with an observe request
2532      *      (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
2533      *      Send CON Observe request to server with
2534      *      observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
2535      *      Remove the callback associated on client side.
2536      */
2537     OCStackResult ret = OC_STACK_OK;
2538     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2539     CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
2540     CARequestInfo_t requestInfo = {.method = CA_GET};
2541
2542     if(!handle)
2543     {
2544         return OC_STACK_INVALID_PARAM;
2545     }
2546
2547     ClientCB *clientCB = GetClientCB(NULL, 0, handle, NULL);
2548     if (!clientCB)
2549     {
2550         OC_LOG(ERROR, TAG, "Client callback not found. Called OCCancel twice?");
2551         goto Error;
2552     }
2553
2554     switch (clientCB->method)
2555     {
2556         case OC_REST_OBSERVE:
2557         case OC_REST_OBSERVE_ALL:
2558             OC_LOG_V(INFO, TAG, "Canceling observation for resource %s",
2559                                         clientCB->requestUri);
2560             if (qos != OC_HIGH_QOS)
2561             {
2562                 FindAndDeleteClientCB(clientCB);
2563                 break;
2564             }
2565             else
2566             {
2567                 OC_LOG(INFO, TAG, "Cancelling observation as CONFIRMABLE");
2568             }
2569
2570             requestData.type = qualityOfServiceToMessageType(qos);
2571             requestData.token = clientCB->token;
2572             requestData.tokenLength = clientCB->tokenLength;
2573             if (CreateObserveHeaderOption (&(requestData.options),
2574                     options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
2575             {
2576                 return OC_STACK_ERROR;
2577             }
2578             requestData.numOptions = numOptions + 1;
2579             requestData.resourceUri = OICStrdup (clientCB->requestUri);
2580
2581             requestInfo.method = CA_GET;
2582             requestInfo.info = requestData;
2583
2584             CopyDevAddrToEndpoint(clientCB->devAddr, &endpoint);
2585
2586             // send request
2587             ret = OCSendRequest(&endpoint, &requestInfo);
2588             break;
2589
2590 #ifdef WITH_PRESENCE
2591         case OC_REST_PRESENCE:
2592             FindAndDeleteClientCB(clientCB);
2593             break;
2594 #endif
2595
2596         default:
2597             ret = OC_STACK_INVALID_METHOD;
2598             break;
2599     }
2600
2601 Error:
2602     if (requestData.numOptions > 0)
2603     {
2604         OICFree(requestData.options);
2605     }
2606     if (requestData.resourceUri)
2607     {
2608         OICFree (requestData.resourceUri);
2609     }
2610     return ret;
2611 }
2612
2613 /**
2614  * @brief   Register Persistent storage callback.
2615  * @param   persistentStorageHandler [IN] Pointers to open, read, write, close & unlink handlers.
2616  * @return
2617  *     OC_STACK_OK    - No errors; Success
2618  *     OC_STACK_INVALID_PARAM - Invalid parameter
2619  */
2620 OCStackResult OCRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
2621 {
2622     OC_LOG(INFO, TAG, "RegisterPersistentStorageHandler !!");
2623     if(!persistentStorageHandler)
2624     {
2625         OC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
2626         return OC_STACK_INVALID_PARAM;
2627     }
2628     else
2629     {
2630         if( !persistentStorageHandler->open ||
2631                 !persistentStorageHandler->close ||
2632                 !persistentStorageHandler->read ||
2633                 !persistentStorageHandler->unlink ||
2634                 !persistentStorageHandler->write)
2635         {
2636             OC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
2637             return OC_STACK_INVALID_PARAM;
2638         }
2639     }
2640     return SRMRegisterPersistentStorageHandler(persistentStorageHandler);
2641 }
2642
2643 #ifdef WITH_PRESENCE
2644
2645 OCStackResult OCProcessPresence()
2646 {
2647     OCStackResult result = OC_STACK_OK;
2648
2649     // the following line floods the log with messages that are irrelevant
2650     // to most purposes.  Uncomment as needed.
2651     //OC_LOG(INFO, TAG, "Entering RequestPresence");
2652     ClientCB* cbNode = NULL;
2653     OCClientResponse clientResponse;
2654     OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
2655
2656     LL_FOREACH(cbList, cbNode)
2657     {
2658         if (OC_REST_PRESENCE != cbNode->method || !cbNode->presence)
2659         {
2660             continue;
2661         }
2662
2663         uint32_t now = GetTicks(0);
2664         OC_LOG_V(DEBUG, TAG, "this TTL level %d",
2665                                                 cbNode->presence->TTLlevel);
2666         OC_LOG_V(DEBUG, TAG, "current ticks %d", now);
2667
2668         if (cbNode->presence->TTLlevel > PresenceTimeOutSize)
2669         {
2670             goto exit;
2671         }
2672
2673         if (cbNode->presence->TTLlevel < PresenceTimeOutSize)
2674         {
2675             OC_LOG_V(DEBUG, TAG, "timeout ticks %d",
2676                     cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
2677         }
2678         if (cbNode->presence->TTLlevel >= PresenceTimeOutSize)
2679         {
2680             OC_LOG(DEBUG, TAG, "No more timeout ticks");
2681
2682             clientResponse.sequenceNumber = 0;
2683             clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
2684             clientResponse.devAddr = *cbNode->devAddr;
2685             FixUpClientResponse(&clientResponse);
2686             clientResponse.payload = NULL;
2687
2688             // Increment the TTLLevel (going to a next state), so we don't keep
2689             // sending presence notification to client.
2690             cbNode->presence->TTLlevel++;
2691             OC_LOG_V(DEBUG, TAG, "moving to TTL level %d",
2692                                         cbNode->presence->TTLlevel);
2693
2694             cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse);
2695             if (cbResult == OC_STACK_DELETE_TRANSACTION)
2696             {
2697                 FindAndDeleteClientCB(cbNode);
2698             }
2699         }
2700
2701         if (now < cbNode->presence->timeOut[cbNode->presence->TTLlevel])
2702         {
2703             continue;
2704         }
2705
2706         CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2707         CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
2708         CARequestInfo_t requestInfo = {.method = CA_GET};
2709
2710         OC_LOG(DEBUG, TAG, "time to test server presence");
2711
2712         CopyDevAddrToEndpoint(cbNode->devAddr, &endpoint);
2713
2714         requestData.type = CA_MSG_NONCONFIRM;
2715         requestData.token = cbNode->token;
2716         requestData.tokenLength = cbNode->tokenLength;
2717         requestData.resourceUri = OC_RSRVD_PRESENCE_URI;
2718         requestInfo.method = CA_GET;
2719         requestInfo.info = requestData;
2720
2721         result = OCSendRequest(&endpoint, &requestInfo);
2722         if (OC_STACK_OK != result)
2723         {
2724             goto exit;
2725         }
2726
2727         cbNode->presence->TTLlevel++;
2728         OC_LOG_V(DEBUG, TAG, "moving to TTL level %d", cbNode->presence->TTLlevel);
2729     }
2730 exit:
2731     if (result != OC_STACK_OK)
2732     {
2733         OC_LOG(ERROR, TAG, "OCProcessPresence error");
2734     }
2735
2736     return result;
2737 }
2738 #endif // WITH_PRESENCE
2739
2740 OCStackResult OCProcess()
2741 {
2742 #ifdef WITH_PRESENCE
2743     OCProcessPresence();
2744 #endif
2745     CAHandleRequestResponse();
2746
2747 #ifdef ROUTING_GATEWAY
2748     RMProcess();
2749 #endif
2750     return OC_STACK_OK;
2751 }
2752
2753 #ifdef WITH_PRESENCE
2754 OCStackResult OCStartPresence(const uint32_t ttl)
2755 {
2756     uint8_t tokenLength = CA_MAX_TOKEN_LEN;
2757     OCChangeResourceProperty(
2758             &(((OCResource *)presenceResource.handle)->resourceProperties),
2759             OC_ACTIVE, 1);
2760
2761     if (OC_MAX_PRESENCE_TTL_SECONDS < ttl)
2762     {
2763         presenceResource.presenceTTL = OC_MAX_PRESENCE_TTL_SECONDS;
2764         OC_LOG(INFO, TAG, "Setting Presence TTL to max value");
2765     }
2766     else if (0 == ttl)
2767     {
2768         presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
2769         OC_LOG(INFO, TAG, "Setting Presence TTL to default value");
2770     }
2771     else
2772     {
2773         presenceResource.presenceTTL = ttl;
2774     }
2775     OC_LOG_V(DEBUG, TAG, "Presence TTL is %lu seconds", presenceResource.presenceTTL);
2776
2777     if (OC_PRESENCE_UNINITIALIZED == presenceState)
2778     {
2779         presenceState = OC_PRESENCE_INITIALIZED;
2780
2781         OCDevAddr devAddr = { OC_DEFAULT_ADAPTER };
2782
2783         CAToken_t caToken = NULL;
2784         CAResult_t caResult = CAGenerateToken(&caToken, tokenLength);
2785         if (caResult != CA_STATUS_OK)
2786         {
2787             OC_LOG(ERROR, TAG, "CAGenerateToken error");
2788             CADestroyToken(caToken);
2789             return OC_STACK_ERROR;
2790         }
2791
2792         AddObserver(OC_RSRVD_PRESENCE_URI, NULL, 0, caToken, tokenLength,
2793                 (OCResource *)presenceResource.handle, OC_LOW_QOS, OC_FORMAT_UNDEFINED, &devAddr);
2794         CADestroyToken(caToken);
2795     }
2796
2797     // Each time OCStartPresence is called
2798     // a different random 32-bit integer number is used
2799     ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2800
2801     return SendPresenceNotification(((OCResource *)presenceResource.handle)->rsrcType,
2802             OC_PRESENCE_TRIGGER_CREATE);
2803 }
2804
2805 OCStackResult OCStopPresence()
2806 {
2807     OCStackResult result = OC_STACK_ERROR;
2808
2809     if(presenceResource.handle)
2810     {
2811         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2812
2813     // make resource inactive
2814     result = OCChangeResourceProperty(
2815             &(((OCResource *) presenceResource.handle)->resourceProperties),
2816             OC_ACTIVE, 0);
2817     }
2818
2819     if(result != OC_STACK_OK)
2820     {
2821         OC_LOG(ERROR, TAG,
2822                       "Changing the presence resource properties to ACTIVE not successful");
2823         return result;
2824     }
2825
2826     return SendStopNotification();
2827 }
2828 #endif
2829
2830 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler,
2831                                             void* callbackParameter)
2832 {
2833     defaultDeviceHandler = entityHandler;
2834     defaultDeviceHandlerCallbackParameter = callbackParameter;
2835
2836     return OC_STACK_OK;
2837 }
2838
2839 OCStackResult OCSetPlatformInfo(OCPlatformInfo platformInfo)
2840 {
2841     OC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
2842
2843     if(myStackMode ==  OC_SERVER || myStackMode == OC_CLIENT_SERVER || myStackMode == OC_GATEWAY)
2844     {
2845         if (validatePlatformInfo(platformInfo))
2846         {
2847             return SavePlatformInfo(platformInfo);
2848         }
2849         else
2850         {
2851             return OC_STACK_INVALID_PARAM;
2852         }
2853     }
2854     else
2855     {
2856         return OC_STACK_ERROR;
2857     }
2858 }
2859
2860 OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
2861 {
2862     OC_LOG(INFO, TAG, "Entering OCSetDeviceInfo");
2863
2864     if (!deviceInfo.deviceName || deviceInfo.deviceName[0] == '\0')
2865     {
2866         OC_LOG(ERROR, TAG, "Null or empty device name.");
2867         return OC_STACK_INVALID_PARAM;
2868     }
2869
2870     return SaveDeviceInfo(deviceInfo);
2871 }
2872
2873 OCStackResult OCCreateResource(OCResourceHandle *handle,
2874         const char *resourceTypeName,
2875         const char *resourceInterfaceName,
2876         const char *uri, OCEntityHandler entityHandler,
2877         void* callbackParam,
2878         uint8_t resourceProperties)
2879 {
2880
2881     OCResource *pointer = NULL;
2882     char *str = NULL;
2883     OCStackResult result = OC_STACK_ERROR;
2884
2885     OC_LOG(INFO, TAG, "Entering OCCreateResource");
2886
2887     if(myStackMode == OC_CLIENT)
2888     {
2889         return OC_STACK_INVALID_PARAM;
2890     }
2891     // Validate parameters
2892     if(!uri || uri[0]=='\0' || strlen(uri)>=MAX_URI_LENGTH )
2893     {
2894         OC_LOG(ERROR, TAG, "URI is empty or too long");
2895         return OC_STACK_INVALID_URI;
2896     }
2897     // Is it presented during resource discovery?
2898     if (!handle || !resourceTypeName || resourceTypeName[0] == '\0' )
2899     {
2900         OC_LOG(ERROR, TAG, "Input parameter is NULL");
2901         return OC_STACK_INVALID_PARAM;
2902     }
2903
2904     if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0)
2905     {
2906         resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
2907     }
2908
2909     // Make sure resourceProperties bitmask has allowed properties specified
2910     if (resourceProperties
2911             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE |
2912                OC_EXPLICIT_DISCOVERABLE))
2913     {
2914         OC_LOG(ERROR, TAG, "Invalid property");
2915         return OC_STACK_INVALID_PARAM;
2916     }
2917
2918     // If the headResource is NULL, then no resources have been created...
2919     pointer = headResource;
2920     if (pointer)
2921     {
2922         // At least one resources is in the resource list, so we need to search for
2923         // repeated URLs, which are not allowed.  If a repeat is found, exit with an error
2924         while (pointer)
2925         {
2926             if (strncmp(uri, pointer->uri, MAX_URI_LENGTH) == 0)
2927             {
2928                 OC_LOG_V(ERROR, TAG, "Resource %s already exists", uri);
2929                 return OC_STACK_INVALID_PARAM;
2930             }
2931             pointer = pointer->next;
2932         }
2933     }
2934     // Create the pointer and insert it into the resource list
2935     pointer = (OCResource *) OICCalloc(1, sizeof(OCResource));
2936     if (!pointer)
2937     {
2938         result = OC_STACK_NO_MEMORY;
2939         goto exit;
2940     }
2941     pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
2942
2943     insertResource(pointer);
2944
2945     // Set the uri
2946     str = OICStrdup(uri);
2947     if (!str)
2948     {
2949         result = OC_STACK_NO_MEMORY;
2950         goto exit;
2951     }
2952     pointer->uri = str;
2953
2954     // Set properties.  Set OC_ACTIVE
2955     pointer->resourceProperties = (OCResourceProperty) (resourceProperties
2956             | OC_ACTIVE);
2957
2958     // Add the resourcetype to the resource
2959     result = BindResourceTypeToResource(pointer, resourceTypeName);
2960     if (result != OC_STACK_OK)
2961     {
2962         OC_LOG(ERROR, TAG, "Error adding resourcetype");
2963         goto exit;
2964     }
2965
2966     // Add the resourceinterface to the resource
2967     result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
2968     if (result != OC_STACK_OK)
2969     {
2970         OC_LOG(ERROR, TAG, "Error adding resourceinterface");
2971         goto exit;
2972     }
2973
2974     // If an entity handler has been passed, attach it to the newly created
2975     // resource.  Otherwise, set the default entity handler.
2976     if (entityHandler)
2977     {
2978         pointer->entityHandler = entityHandler;
2979         pointer->entityHandlerCallbackParam = callbackParam;
2980     }
2981     else
2982     {
2983         pointer->entityHandler = defaultResourceEHandler;
2984         pointer->entityHandlerCallbackParam = NULL;
2985     }
2986
2987     *handle = pointer;
2988     result = OC_STACK_OK;
2989
2990 #ifdef WITH_PRESENCE
2991     if (presenceResource.handle)
2992     {
2993         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2994         SendPresenceNotification(pointer->rsrcType, OC_PRESENCE_TRIGGER_CREATE);
2995     }
2996 #endif
2997 exit:
2998     if (result != OC_STACK_OK)
2999     {
3000         // Deep delete of resource and other dynamic elements that it contains
3001         deleteResource(pointer);
3002         OICFree(str);
3003     }
3004     return result;
3005 }
3006
3007
3008 OCStackResult OCBindResource(
3009         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
3010 {
3011     OCResource *resource = NULL;
3012     uint8_t i = 0;
3013
3014     OC_LOG(INFO, TAG, "Entering OCBindResource");
3015
3016     // Validate parameters
3017     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
3018     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
3019     // Container cannot contain itself
3020     if (collectionHandle == resourceHandle)
3021     {
3022         OC_LOG(ERROR, TAG, "Added handle equals collection handle");
3023         return OC_STACK_INVALID_PARAM;
3024     }
3025
3026     // Use the handle to find the resource in the resource linked list
3027     resource = findResource((OCResource *) collectionHandle);
3028     if (!resource)
3029     {
3030         OC_LOG(ERROR, TAG, "Collection handle not found");
3031         return OC_STACK_INVALID_PARAM;
3032     }
3033
3034     // Look for an open slot to add add the child resource.
3035     // If found, add it and return success
3036     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
3037     {
3038         if (!resource->rsrcResources[i])
3039         {
3040             resource->rsrcResources[i] = (OCResource *) resourceHandle;
3041             OC_LOG(INFO, TAG, "resource bound");
3042
3043 #ifdef WITH_PRESENCE
3044             if (presenceResource.handle)
3045             {
3046                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3047                 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
3048                         OC_PRESENCE_TRIGGER_CHANGE);
3049             }
3050 #endif
3051             return OC_STACK_OK;
3052
3053         }
3054     }
3055
3056     // Unable to add resourceHandle, so return error
3057     return OC_STACK_ERROR;
3058 }
3059
3060 OCStackResult OCUnBindResource(
3061         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
3062 {
3063     OCResource *resource = NULL;
3064     uint8_t i = 0;
3065
3066     OC_LOG(INFO, TAG, "Entering OCUnBindResource");
3067
3068     // Validate parameters
3069     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
3070     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
3071     // Container cannot contain itself
3072     if (collectionHandle == resourceHandle)
3073     {
3074         OC_LOG(ERROR, TAG, "removing handle equals collection handle");
3075         return OC_STACK_INVALID_PARAM;
3076     }
3077
3078     // Use the handle to find the resource in the resource linked list
3079     resource = findResource((OCResource *) collectionHandle);
3080     if (!resource)
3081     {
3082         OC_LOG(ERROR, TAG, "Collection handle not found");
3083         return OC_STACK_INVALID_PARAM;
3084     }
3085
3086     // Look for an open slot to add add the child resource.
3087     // If found, add it and return success
3088     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
3089     {
3090         if (resourceHandle == resource->rsrcResources[i])
3091         {
3092             resource->rsrcResources[i] = (OCResource *) NULL;
3093             OC_LOG(INFO, TAG, "resource unbound");
3094
3095             // Send notification when resource is unbounded successfully.
3096 #ifdef WITH_PRESENCE
3097             if (presenceResource.handle)
3098             {
3099                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3100                 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
3101                         OC_PRESENCE_TRIGGER_CHANGE);
3102             }
3103 #endif
3104             return OC_STACK_OK;
3105         }
3106     }
3107
3108     OC_LOG(INFO, TAG, "resource not found in collection");
3109
3110     // Unable to add resourceHandle, so return error
3111     return OC_STACK_ERROR;
3112 }
3113
3114 OCStackResult BindResourceTypeToResource(OCResource* resource,
3115                                             const char *resourceTypeName)
3116 {
3117     OCResourceType *pointer = NULL;
3118     char *str = NULL;
3119     OCStackResult result = OC_STACK_ERROR;
3120
3121     VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
3122
3123     pointer = (OCResourceType *) OICCalloc(1, sizeof(OCResourceType));
3124     if (!pointer)
3125     {
3126         result = OC_STACK_NO_MEMORY;
3127         goto exit;
3128     }
3129
3130     str = OICStrdup(resourceTypeName);
3131     if (!str)
3132     {
3133         result = OC_STACK_NO_MEMORY;
3134         goto exit;
3135     }
3136     pointer->resourcetypename = str;
3137
3138     insertResourceType(resource, pointer);
3139     result = OC_STACK_OK;
3140
3141     exit:
3142     if (result != OC_STACK_OK)
3143     {
3144         OICFree(pointer);
3145         OICFree(str);
3146     }
3147
3148     return result;
3149 }
3150
3151 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
3152         const char *resourceInterfaceName)
3153 {
3154     OCResourceInterface *pointer = NULL;
3155     char *str = NULL;
3156     OCStackResult result = OC_STACK_ERROR;
3157
3158     VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
3159
3160     OC_LOG_V(INFO, TAG, "Binding %s interface to %s", resourceInterfaceName, resource->uri);
3161
3162     pointer = (OCResourceInterface *) OICCalloc(1, sizeof(OCResourceInterface));
3163     if (!pointer)
3164     {
3165         result = OC_STACK_NO_MEMORY;
3166         goto exit;
3167     }
3168
3169     str = OICStrdup(resourceInterfaceName);
3170     if (!str)
3171     {
3172         result = OC_STACK_NO_MEMORY;
3173         goto exit;
3174     }
3175     pointer->name = str;
3176
3177     // Bind the resourceinterface to the resource
3178     insertResourceInterface(resource, pointer);
3179
3180     result = OC_STACK_OK;
3181
3182     exit:
3183     if (result != OC_STACK_OK)
3184     {
3185         OICFree(pointer);
3186         OICFree(str);
3187     }
3188
3189     return result;
3190 }
3191
3192 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
3193         const char *resourceTypeName)
3194 {
3195
3196     OCStackResult result = OC_STACK_ERROR;
3197     OCResource *resource = NULL;
3198
3199     resource = findResource((OCResource *) handle);
3200     if (!resource)
3201     {
3202         OC_LOG(ERROR, TAG, "Resource not found");
3203         return OC_STACK_ERROR;
3204     }
3205
3206     result = BindResourceTypeToResource(resource, resourceTypeName);
3207
3208 #ifdef WITH_PRESENCE
3209     if(presenceResource.handle)
3210     {
3211         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3212         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3213     }
3214 #endif
3215
3216     return result;
3217 }
3218
3219 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
3220         const char *resourceInterfaceName)
3221 {
3222
3223     OCStackResult result = OC_STACK_ERROR;
3224     OCResource *resource = NULL;
3225
3226     resource = findResource((OCResource *) handle);
3227     if (!resource)
3228     {
3229         OC_LOG(ERROR, TAG, "Resource not found");
3230         return OC_STACK_ERROR;
3231     }
3232
3233     result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
3234
3235 #ifdef WITH_PRESENCE
3236     if (presenceResource.handle)
3237     {
3238         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3239         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3240     }
3241 #endif
3242
3243     return result;
3244 }
3245
3246 OCStackResult OCGetNumberOfResources(uint8_t *numResources)
3247 {
3248     OCResource *pointer = headResource;
3249
3250     VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
3251     *numResources = 0;
3252     while (pointer)
3253     {
3254         *numResources = *numResources + 1;
3255         pointer = pointer->next;
3256     }
3257     return OC_STACK_OK;
3258 }
3259
3260 OCResourceHandle OCGetResourceHandle(uint8_t index)
3261 {
3262     OCResource *pointer = headResource;
3263
3264     for( uint8_t i = 0; i < index && pointer; ++i)
3265     {
3266         pointer = pointer->next;
3267     }
3268     return (OCResourceHandle) pointer;
3269 }
3270
3271 OCStackResult OCDeleteResource(OCResourceHandle handle)
3272 {
3273     if (!handle)
3274     {
3275         OC_LOG(ERROR, TAG, "Invalid handle for deletion");
3276         return OC_STACK_INVALID_PARAM;
3277     }
3278
3279     OCResource *resource = findResource((OCResource *) handle);
3280     if (resource == NULL)
3281     {
3282         OC_LOG(ERROR, TAG, "Resource not found");
3283         return OC_STACK_NO_RESOURCE;
3284     }
3285
3286     if (deleteResource((OCResource *) handle) != OC_STACK_OK)
3287     {
3288         OC_LOG(ERROR, TAG, "Error deleting resource");
3289         return OC_STACK_ERROR;
3290     }
3291
3292     return OC_STACK_OK;
3293 }
3294
3295 const char *OCGetResourceUri(OCResourceHandle handle)
3296 {
3297     OCResource *resource = NULL;
3298
3299     resource = findResource((OCResource *) handle);
3300     if (resource)
3301     {
3302         return resource->uri;
3303     }
3304     return (const char *) NULL;
3305 }
3306
3307 OCResourceProperty OCGetResourceProperties(OCResourceHandle handle)
3308 {
3309     OCResource *resource = NULL;
3310
3311     resource = findResource((OCResource *) handle);
3312     if (resource)
3313     {
3314         return resource->resourceProperties;
3315     }
3316     return (OCResourceProperty)-1;
3317 }
3318
3319 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
3320         uint8_t *numResourceTypes)
3321 {
3322     OCResource *resource = NULL;
3323     OCResourceType *pointer = NULL;
3324
3325     VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
3326     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3327
3328     *numResourceTypes = 0;
3329
3330     resource = findResource((OCResource *) handle);
3331     if (resource)
3332     {
3333         pointer = resource->rsrcType;
3334         while (pointer)
3335         {
3336             *numResourceTypes = *numResourceTypes + 1;
3337             pointer = pointer->next;
3338         }
3339     }
3340     return OC_STACK_OK;
3341 }
3342
3343 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index)
3344 {
3345     OCResourceType *resourceType = NULL;
3346
3347     resourceType = findResourceTypeAtIndex(handle, index);
3348     if (resourceType)
3349     {
3350         return resourceType->resourcetypename;
3351     }
3352     return (const char *) NULL;
3353 }
3354
3355 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
3356         uint8_t *numResourceInterfaces)
3357 {
3358     OCResourceInterface *pointer = NULL;
3359     OCResource *resource = NULL;
3360
3361     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3362     VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
3363
3364     *numResourceInterfaces = 0;
3365     resource = findResource((OCResource *) handle);
3366     if (resource)
3367     {
3368         pointer = resource->rsrcInterface;
3369         while (pointer)
3370         {
3371             *numResourceInterfaces = *numResourceInterfaces + 1;
3372             pointer = pointer->next;
3373         }
3374     }
3375     return OC_STACK_OK;
3376 }
3377
3378 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index)
3379 {
3380     OCResourceInterface *resourceInterface = NULL;
3381
3382     resourceInterface = findResourceInterfaceAtIndex(handle, index);
3383     if (resourceInterface)
3384     {
3385         return resourceInterface->name;
3386     }
3387     return (const char *) NULL;
3388 }
3389
3390 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
3391         uint8_t index)
3392 {
3393     OCResource *resource = NULL;
3394
3395     if (index >= MAX_CONTAINED_RESOURCES)
3396     {
3397         return NULL;
3398     }
3399
3400     resource = findResource((OCResource *) collectionHandle);
3401     if (!resource)
3402     {
3403         return NULL;
3404     }
3405
3406     return resource->rsrcResources[index];
3407 }
3408
3409 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
3410         OCEntityHandler entityHandler,
3411         void* callbackParam)
3412 {
3413     OCResource *resource = NULL;
3414
3415     // Validate parameters
3416     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3417
3418     // Use the handle to find the resource in the resource linked list
3419     resource = findResource((OCResource *)handle);
3420     if (!resource)
3421     {
3422         OC_LOG(ERROR, TAG, "Resource not found");
3423         return OC_STACK_ERROR;
3424     }
3425
3426     // Bind the handler
3427     resource->entityHandler = entityHandler;
3428     resource->entityHandlerCallbackParam = callbackParam;
3429
3430 #ifdef WITH_PRESENCE
3431     if (presenceResource.handle)
3432     {
3433         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3434         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3435     }
3436 #endif
3437
3438     return OC_STACK_OK;
3439 }
3440
3441 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle)
3442 {
3443     OCResource *resource = NULL;
3444
3445     resource = findResource((OCResource *)handle);
3446     if (!resource)
3447     {
3448         OC_LOG(ERROR, TAG, "Resource not found");
3449         return NULL;
3450     }
3451
3452     // Bind the handler
3453     return resource->entityHandler;
3454 }
3455
3456 void incrementSequenceNumber(OCResource * resPtr)
3457 {
3458     // Increment the sequence number
3459     resPtr->sequenceNum += 1;
3460     if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
3461     {
3462         resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
3463     }
3464     return;
3465 }
3466
3467 #ifdef WITH_PRESENCE
3468 OCStackResult SendPresenceNotification(OCResourceType *resourceType,
3469         OCPresenceTrigger trigger)
3470 {
3471     OCResource *resPtr = NULL;
3472     OCStackResult result = OC_STACK_ERROR;
3473     OCMethod method = OC_REST_PRESENCE;
3474     uint32_t maxAge = 0;
3475     resPtr = findResource((OCResource *) presenceResource.handle);
3476     if(NULL == resPtr)
3477     {
3478         return OC_STACK_NO_RESOURCE;
3479     }
3480
3481     if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
3482     {
3483         maxAge = presenceResource.presenceTTL;
3484
3485         result = SendAllObserverNotification(method, resPtr, maxAge,
3486                 trigger, resourceType, OC_LOW_QOS);
3487     }
3488
3489     return result;
3490 }
3491
3492 OCStackResult SendStopNotification()
3493 {
3494     OCResource *resPtr = NULL;
3495     OCStackResult result = OC_STACK_ERROR;
3496     OCMethod method = OC_REST_PRESENCE;
3497     resPtr = findResource((OCResource *) presenceResource.handle);
3498     if(NULL == resPtr)
3499     {
3500         return OC_STACK_NO_RESOURCE;
3501     }
3502
3503     // maxAge is 0. ResourceType is NULL.
3504     result = SendAllObserverNotification(method, resPtr, 0, OC_PRESENCE_TRIGGER_DELETE,
3505             NULL, OC_LOW_QOS);
3506
3507     return result;
3508 }
3509
3510 #endif // WITH_PRESENCE
3511 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos)
3512 {
3513     OCResource *resPtr = NULL;
3514     OCStackResult result = OC_STACK_ERROR;
3515     OCMethod method = OC_REST_NOMETHOD;
3516     uint32_t maxAge = 0;
3517
3518     OC_LOG(INFO, TAG, "Notifying all observers");
3519 #ifdef WITH_PRESENCE
3520     if(handle == presenceResource.handle)
3521     {
3522         return OC_STACK_OK;
3523     }
3524 #endif // WITH_PRESENCE
3525     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3526
3527     // Verify that the resource exists
3528     resPtr = findResource ((OCResource *) handle);
3529     if (NULL == resPtr)
3530     {
3531         return OC_STACK_NO_RESOURCE;
3532     }
3533     else
3534     {
3535         //only increment in the case of regular observing (not presence)
3536         incrementSequenceNumber(resPtr);
3537         method = OC_REST_OBSERVE;
3538         maxAge = MAX_OBSERVE_AGE;
3539 #ifdef WITH_PRESENCE
3540         result = SendAllObserverNotification (method, resPtr, maxAge,
3541                 OC_PRESENCE_TRIGGER_DELETE, NULL, qos);
3542 #else
3543         result = SendAllObserverNotification (method, resPtr, maxAge, qos);
3544 #endif
3545         return result;
3546     }
3547 }
3548
3549 OCStackResult
3550 OCNotifyListOfObservers (OCResourceHandle handle,
3551                          OCObservationId  *obsIdList,
3552                          uint8_t          numberOfIds,
3553                          const OCRepPayload       *payload,
3554                          OCQualityOfService qos)
3555 {
3556     OC_LOG(INFO, TAG, "Entering OCNotifyListOfObservers");
3557
3558     OCResource *resPtr = NULL;
3559     //TODO: we should allow the server to define this
3560     uint32_t maxAge = MAX_OBSERVE_AGE;
3561
3562     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3563     VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
3564     VERIFY_NON_NULL(payload, ERROR, OC_STACK_ERROR);
3565
3566     resPtr = findResource ((OCResource *) handle);
3567     if (NULL == resPtr || myStackMode == OC_CLIENT)
3568     {
3569         return OC_STACK_NO_RESOURCE;
3570     }
3571     else
3572     {
3573         incrementSequenceNumber(resPtr);
3574     }
3575     return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
3576             payload, maxAge, qos));
3577 }
3578
3579 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
3580 {
3581     OCStackResult result = OC_STACK_ERROR;
3582     OCServerRequest *serverRequest = NULL;
3583
3584     OC_LOG(INFO, TAG, "Entering OCDoResponse");
3585
3586     // Validate input parameters
3587     VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
3588     VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
3589
3590     // Normal response
3591     // Get pointer to request info
3592     serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
3593     if(serverRequest)
3594     {
3595         // response handler in ocserverrequest.c. Usually HandleSingleResponse.
3596         result = serverRequest->ehResponseHandler(ehResponse);
3597     }
3598
3599     return result;
3600 }
3601
3602 //-----------------------------------------------------------------------------
3603 // Private internal function definitions
3604 //-----------------------------------------------------------------------------
3605 static OCDoHandle GenerateInvocationHandle()
3606 {
3607     OCDoHandle handle = NULL;
3608     // Generate token here, it will be deleted when the transaction is deleted
3609     handle = (OCDoHandle) OICMalloc(sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3610     if (handle)
3611     {
3612         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3613     }
3614
3615     return handle;
3616 }
3617
3618 #ifdef WITH_PRESENCE
3619 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
3620         OCResourceProperty resourceProperties, uint8_t enable)
3621 {
3622     if (!inputProperty)
3623     {
3624         return OC_STACK_INVALID_PARAM;
3625     }
3626     if (resourceProperties
3627             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW))
3628     {
3629         OC_LOG(ERROR, TAG, "Invalid property");
3630         return OC_STACK_INVALID_PARAM;
3631     }
3632     if(!enable)
3633     {
3634         *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
3635     }
3636     else
3637     {
3638         *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
3639     }
3640     return OC_STACK_OK;
3641 }
3642 #endif
3643
3644 OCStackResult initResources()
3645 {
3646     OCStackResult result = OC_STACK_OK;
3647
3648     headResource = NULL;
3649     tailResource = NULL;
3650     // Init Virtual Resources
3651 #ifdef WITH_PRESENCE
3652     presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
3653
3654     result = OCCreateResource(&presenceResource.handle,
3655             OC_RSRVD_RESOURCE_TYPE_PRESENCE,
3656             "core.r",
3657             OC_RSRVD_PRESENCE_URI,
3658             NULL,
3659             NULL,
3660             OC_OBSERVABLE);
3661     //make resource inactive
3662     result = OCChangeResourceProperty(
3663             &(((OCResource *) presenceResource.handle)->resourceProperties),
3664             OC_ACTIVE, 0);
3665 #endif
3666
3667     if (result == OC_STACK_OK)
3668     {
3669         result = SRMInitSecureResources();
3670     }
3671
3672     return result;
3673 }
3674
3675 void insertResource(OCResource *resource)
3676 {
3677     if (!headResource)
3678     {
3679         headResource = resource;
3680         tailResource = resource;
3681     }
3682     else
3683     {
3684         tailResource->next = resource;
3685         tailResource = resource;
3686     }
3687     resource->next = NULL;
3688 }
3689
3690 OCResource *findResource(OCResource *resource)
3691 {
3692     OCResource *pointer = headResource;
3693
3694     while (pointer)
3695     {
3696         if (pointer == resource)
3697         {
3698             return resource;
3699         }
3700         pointer = pointer->next;
3701     }
3702     return NULL;
3703 }
3704
3705 void deleteAllResources()
3706 {
3707     OCResource *pointer = headResource;
3708     OCResource *temp = NULL;
3709
3710     while (pointer)
3711     {
3712         temp = pointer->next;
3713 #ifdef WITH_PRESENCE
3714         if (pointer != (OCResource *) presenceResource.handle)
3715         {
3716 #endif // WITH_PRESENCE
3717             deleteResource(pointer);
3718 #ifdef WITH_PRESENCE
3719         }
3720 #endif // WITH_PRESENCE
3721         pointer = temp;
3722     }
3723
3724     SRMDeInitSecureResources();
3725
3726 #ifdef WITH_PRESENCE
3727     // Ensure that the last resource to be deleted is the presence resource. This allows for all
3728     // presence notification attributed to their deletion to be processed.
3729     deleteResource((OCResource *) presenceResource.handle);
3730 #endif // WITH_PRESENCE
3731 }
3732
3733 OCStackResult deleteResource(OCResource *resource)
3734 {
3735     OCResource *prev = NULL;
3736     OCResource *temp = NULL;
3737     if(!resource)
3738     {
3739         OC_LOG(DEBUG,TAG,"resource is NULL");
3740         return OC_STACK_INVALID_PARAM;
3741     }
3742
3743     OC_LOG_V (INFO, TAG, "Deleting resource %s", resource->uri);
3744
3745     temp = headResource;
3746     while (temp)
3747     {
3748         if (temp == resource)
3749         {
3750             // Invalidate all Resource Properties.
3751             resource->resourceProperties = (OCResourceProperty) 0;
3752 #ifdef WITH_PRESENCE
3753             if(resource != (OCResource *) presenceResource.handle)
3754             {
3755 #endif // WITH_PRESENCE
3756                 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
3757 #ifdef WITH_PRESENCE
3758             }
3759
3760             if(presenceResource.handle)
3761             {
3762                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3763                 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_DELETE);
3764             }
3765 #endif
3766             // Only resource in list.
3767             if (temp == headResource && temp == tailResource)
3768             {
3769                 headResource = NULL;
3770                 tailResource = NULL;
3771             }
3772             // Deleting head.
3773             else if (temp == headResource)
3774             {
3775                 headResource = temp->next;
3776             }
3777             // Deleting tail.
3778             else if (temp == tailResource)
3779             {
3780                 tailResource = prev;
3781                 tailResource->next = NULL;
3782             }
3783             else
3784             {
3785                 prev->next = temp->next;
3786             }
3787
3788             deleteResourceElements(temp);
3789             OICFree(temp);
3790             return OC_STACK_OK;
3791         }
3792         else
3793         {
3794             prev = temp;
3795             temp = temp->next;
3796         }
3797     }
3798
3799     return OC_STACK_ERROR;
3800 }
3801
3802 void deleteResourceElements(OCResource *resource)
3803 {
3804     if (!resource)
3805     {
3806         return;
3807     }
3808
3809     OICFree(resource->uri);
3810     deleteResourceType(resource->rsrcType);
3811     deleteResourceInterface(resource->rsrcInterface);
3812 }
3813
3814 void deleteResourceType(OCResourceType *resourceType)
3815 {
3816     OCResourceType *pointer = resourceType;
3817     OCResourceType *next = NULL;
3818
3819     while (pointer)
3820     {
3821         next = pointer->next;
3822         OICFree(pointer->resourcetypename);
3823         OICFree(pointer);
3824         pointer = next;
3825     }
3826 }
3827
3828 void deleteResourceInterface(OCResourceInterface *resourceInterface)
3829 {
3830     OCResourceInterface *pointer = resourceInterface;
3831     OCResourceInterface *next = NULL;
3832
3833     while (pointer)
3834     {
3835         next = pointer->next;
3836         OICFree(pointer->name);
3837         OICFree(pointer);
3838         pointer = next;
3839     }
3840 }
3841
3842 void insertResourceType(OCResource *resource, OCResourceType *resourceType)
3843 {
3844     OCResourceType *pointer = NULL;
3845     OCResourceType *previous = NULL;
3846     if (!resource || !resourceType)
3847     {
3848         return;
3849     }
3850     // resource type list is empty.
3851     else if (!resource->rsrcType)
3852     {
3853         resource->rsrcType = resourceType;
3854     }
3855     else
3856     {
3857         pointer = resource->rsrcType;
3858
3859         while (pointer)
3860         {
3861             if (!strcmp(resourceType->resourcetypename, pointer->resourcetypename))
3862             {
3863                 OC_LOG_V(INFO, TAG, "Type %s already exists", resourceType->resourcetypename);
3864                 OICFree(resourceType->resourcetypename);
3865                 OICFree(resourceType);
3866                 return;
3867             }
3868             previous = pointer;
3869             pointer = pointer->next;
3870         }
3871         previous->next = resourceType;
3872     }
3873     resourceType->next = NULL;
3874
3875     OC_LOG_V(INFO, TAG, "Added type %s to %s", resourceType->resourcetypename, resource->uri);
3876 }
3877
3878 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index)
3879 {
3880     OCResource *resource = NULL;
3881     OCResourceType *pointer = NULL;
3882
3883     // Find the specified resource
3884     resource = findResource((OCResource *) handle);
3885     if (!resource)
3886     {
3887         return NULL;
3888     }
3889
3890     // Make sure a resource has a resourcetype
3891     if (!resource->rsrcType)
3892     {
3893         return NULL;
3894     }
3895
3896     // Iterate through the list
3897     pointer = resource->rsrcType;
3898     for(uint8_t i = 0; i< index && pointer; ++i)
3899     {
3900         pointer = pointer->next;
3901     }
3902     return pointer;
3903 }
3904
3905 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
3906 {
3907     if(resourceTypeList && resourceTypeName)
3908     {
3909         OCResourceType * rtPointer = resourceTypeList;
3910         while(resourceTypeName && rtPointer)
3911         {
3912             if(rtPointer->resourcetypename &&
3913                     strcmp(resourceTypeName, (const char *)
3914                     (rtPointer->resourcetypename)) == 0)
3915             {
3916                 break;
3917             }
3918             rtPointer = rtPointer->next;
3919         }
3920         return rtPointer;
3921     }
3922     return NULL;
3923 }
3924
3925 /*
3926  * Insert a new interface into interface linked list only if not already present.
3927  * If alredy present, 2nd arg is free'd.
3928  * Default interface will always be first if present.
3929  */
3930 void insertResourceInterface(OCResource *resource, OCResourceInterface *newInterface)
3931 {
3932     OCResourceInterface *pointer = NULL;
3933     OCResourceInterface *previous = NULL;
3934
3935     newInterface->next = NULL;
3936
3937     OCResourceInterface **firstInterface = &(resource->rsrcInterface);
3938
3939     if (!*firstInterface)
3940     {
3941         *firstInterface = newInterface;
3942     }
3943     else if (strcmp(newInterface->name, OC_RSRVD_INTERFACE_DEFAULT) == 0)
3944     {
3945         if (strcmp((*firstInterface)->name, OC_RSRVD_INTERFACE_DEFAULT) == 0)
3946         {
3947             OICFree(newInterface->name);
3948             OICFree(newInterface);
3949             return;
3950         }
3951         else
3952         {
3953             newInterface->next = *firstInterface;
3954             *firstInterface = newInterface;
3955         }
3956     }
3957     else
3958     {
3959         pointer = *firstInterface;
3960         while (pointer)
3961         {
3962             if (strcmp(newInterface->name, pointer->name) == 0)
3963             {
3964                 OICFree(newInterface->name);
3965                 OICFree(newInterface);
3966                 return;
3967             }
3968             previous = pointer;
3969             pointer = pointer->next;
3970         }
3971         previous->next = newInterface;
3972     }
3973 }
3974
3975 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
3976         uint8_t index)
3977 {
3978     OCResource *resource = NULL;
3979     OCResourceInterface *pointer = NULL;
3980
3981     // Find the specified resource
3982     resource = findResource((OCResource *) handle);
3983     if (!resource)
3984     {
3985         return NULL;
3986     }
3987
3988     // Make sure a resource has a resourceinterface
3989     if (!resource->rsrcInterface)
3990     {
3991         return NULL;
3992     }
3993
3994     // Iterate through the list
3995     pointer = resource->rsrcInterface;
3996
3997     for (uint8_t i = 0; i < index && pointer; ++i)
3998     {
3999         pointer = pointer->next;
4000     }
4001     return pointer;
4002 }
4003
4004 /*
4005  * This function splits the uri using the '?' delimiter.
4006  * "uriWithoutQuery" is the block of characters between the beginning
4007  * till the delimiter or '\0' which ever comes first.
4008  * "query" is whatever is to the right of the delimiter if present.
4009  * No delimiter sets the query to NULL.
4010  * If either are present, they will be malloc'ed into the params 2, 3.
4011  * The first param, *uri is left untouched.
4012
4013  * NOTE: This function does not account for whitespace at the end of the uri NOR
4014  *       malformed uri's with '??'. Whitespace at the end will be assumed to be
4015  *       part of the query.
4016  */
4017 OCStackResult getQueryFromUri(const char * uri, char** query, char ** uriWithoutQuery)
4018 {
4019     if(!uri)
4020     {
4021         return OC_STACK_INVALID_URI;
4022     }
4023     if(!query || !uriWithoutQuery)
4024     {
4025         return OC_STACK_INVALID_PARAM;
4026     }
4027
4028     *query           = NULL;
4029     *uriWithoutQuery = NULL;
4030
4031     size_t uriWithoutQueryLen = 0;
4032     size_t queryLen = 0;
4033     size_t uriLen = strlen(uri);
4034
4035     char *pointerToDelimiter = strstr(uri, "?");
4036
4037     uriWithoutQueryLen = pointerToDelimiter == NULL ? uriLen : (size_t)(pointerToDelimiter - uri);
4038     queryLen = pointerToDelimiter == NULL ? 0 : uriLen - uriWithoutQueryLen - 1;
4039
4040     if (uriWithoutQueryLen)
4041     {
4042         *uriWithoutQuery =  (char *) OICCalloc(uriWithoutQueryLen + 1, 1);
4043         if (!*uriWithoutQuery)
4044         {
4045             goto exit;
4046         }
4047         OICStrcpy(*uriWithoutQuery, uriWithoutQueryLen +1, uri);
4048     }
4049     if (queryLen)
4050     {
4051         *query = (char *) OICCalloc(queryLen + 1, 1);
4052         if (!*query)
4053         {
4054             OICFree(*uriWithoutQuery);
4055             *uriWithoutQuery = NULL;
4056             goto exit;
4057         }
4058         OICStrcpy(*query, queryLen + 1, pointerToDelimiter + 1);
4059     }
4060
4061     return OC_STACK_OK;
4062
4063     exit:
4064         return OC_STACK_NO_MEMORY;
4065 }
4066
4067 const OicUuid_t* OCGetServerInstanceID(void)
4068 {
4069     static bool generated = false;
4070     static OicUuid_t sid;
4071     if (generated)
4072     {
4073         return &sid;
4074     }
4075
4076     if (GetDoxmDeviceID(&sid) != OC_STACK_OK)
4077     {
4078         OC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
4079         return NULL;
4080     }
4081     generated = true;
4082     return &sid;
4083 }
4084
4085 const char* OCGetServerInstanceIDString(void)
4086 {
4087     static bool generated = false;
4088     static char sidStr[UUID_STRING_SIZE];
4089
4090     if(generated)
4091     {
4092         return sidStr;
4093     }
4094
4095     const OicUuid_t* sid = OCGetServerInstanceID();
4096
4097     if(OCConvertUuidToString(sid->id, sidStr) != RAND_UUID_OK)
4098     {
4099         OC_LOG(FATAL, TAG, "Generate UUID String for Server Instance failed!");
4100         return NULL;
4101     }
4102
4103     generated = true;
4104     return sidStr;
4105 }
4106
4107 CAResult_t OCSelectNetwork()
4108 {
4109     CAResult_t retResult = CA_STATUS_FAILED;
4110     CAResult_t caResult = CA_STATUS_OK;
4111
4112     CATransportAdapter_t connTypes[] = {
4113             CA_ADAPTER_IP,
4114             CA_ADAPTER_RFCOMM_BTEDR,
4115             CA_ADAPTER_GATT_BTLE
4116
4117 #ifdef RA_ADAPTER
4118             ,CA_ADAPTER_REMOTE_ACCESS
4119 #endif
4120         };
4121     int numConnTypes = sizeof(connTypes)/sizeof(connTypes[0]);
4122
4123     for(int i = 0; i<numConnTypes; i++)
4124     {
4125         // Ignore CA_NOT_SUPPORTED error. The CA Layer may have not compiled in the interface.
4126         if(caResult == CA_STATUS_OK || caResult == CA_NOT_SUPPORTED)
4127         {
4128            caResult = CASelectNetwork(connTypes[i]);
4129            if(caResult == CA_STATUS_OK)
4130            {
4131                retResult = CA_STATUS_OK;
4132            }
4133         }
4134     }
4135
4136     if(retResult != CA_STATUS_OK)
4137     {
4138         return caResult; // Returns error of appropriate transport that failed fatally.
4139     }
4140
4141     return retResult;
4142 }
4143
4144 OCStackResult CAResultToOCResult(CAResult_t caResult)
4145 {
4146     switch (caResult)
4147     {
4148         case CA_STATUS_OK:
4149             return OC_STACK_OK;
4150         case CA_STATUS_INVALID_PARAM:
4151             return OC_STACK_INVALID_PARAM;
4152         case CA_ADAPTER_NOT_ENABLED:
4153             return OC_STACK_ADAPTER_NOT_ENABLED;
4154         case CA_SERVER_STARTED_ALREADY:
4155             return OC_STACK_OK;
4156         case CA_SERVER_NOT_STARTED:
4157             return OC_STACK_ERROR;
4158         case CA_DESTINATION_NOT_REACHABLE:
4159             return OC_STACK_COMM_ERROR;
4160         case CA_SOCKET_OPERATION_FAILED:
4161             return OC_STACK_COMM_ERROR;
4162         case CA_SEND_FAILED:
4163             return OC_STACK_COMM_ERROR;
4164         case CA_RECEIVE_FAILED:
4165             return OC_STACK_COMM_ERROR;
4166         case CA_MEMORY_ALLOC_FAILED:
4167             return OC_STACK_NO_MEMORY;
4168         case CA_REQUEST_TIMEOUT:
4169             return OC_STACK_TIMEOUT;
4170         case CA_DESTINATION_DISCONNECTED:
4171             return OC_STACK_COMM_ERROR;
4172         case CA_STATUS_FAILED:
4173             return OC_STACK_ERROR;
4174         case CA_NOT_SUPPORTED:
4175             return OC_STACK_NOTIMPL;
4176         default:
4177             return OC_STACK_ERROR;
4178     }
4179 }