OCMulticast start and stop APIs
[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 OCStackResult OCStartMulticastServer()
1990 {
1991     if(stackState != OC_STACK_INITIALIZED)
1992     {
1993         OC_LOG(ERROR, TAG, "OCStack is not initalized. Cannot start multicast server.");
1994         return OC_STACK_ERROR;
1995     }
1996     CAResult_t ret = CAStartListeningServer();
1997     if (CA_STATUS_OK != ret)
1998     {
1999         OC_LOG_V(ERROR, TAG, "Failed starting listening server: %d", ret);
2000         return OC_STACK_ERROR;
2001     }
2002     return OC_STACK_OK;
2003 }
2004
2005 OCStackResult OCStopMulticastServer()
2006 {
2007     CAResult_t ret = CAStopListeningServer();
2008     if (CA_STATUS_OK != ret)
2009     {
2010         OC_LOG_V(ERROR, TAG, "Failed stopping listening server: %d", ret);
2011         return OC_STACK_ERROR;
2012     }
2013     return OC_STACK_OK;
2014 }
2015
2016 CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
2017 {
2018     switch (qos)
2019     {
2020         case OC_HIGH_QOS:
2021             return CA_MSG_CONFIRM;
2022         case OC_LOW_QOS:
2023         case OC_MEDIUM_QOS:
2024         case OC_NA_QOS:
2025         default:
2026             return CA_MSG_NONCONFIRM;
2027     }
2028 }
2029
2030 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
2031 {
2032     char *query;
2033
2034     query = strchr (inputUri, '?');
2035
2036     if (query != NULL)
2037     {
2038         if((query - inputUri) > MAX_URI_LENGTH)
2039         {
2040             return OC_STACK_INVALID_URI;
2041         }
2042
2043         if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
2044         {
2045             return OC_STACK_INVALID_QUERY;
2046         }
2047     }
2048     else if(uriLen > MAX_URI_LENGTH)
2049     {
2050         return OC_STACK_INVALID_URI;
2051     }
2052     return OC_STACK_OK;
2053 }
2054
2055 /**
2056  *  A request uri consists of the following components in order:
2057  *                              example
2058  *  optionally one of
2059  *      CoAP over UDP prefix    "coap://"
2060  *      CoAP over TCP prefix    "coap+tcp://"
2061  *  optionally one of
2062  *      IPv6 address            "[1234::5678]"
2063  *      IPv4 address            "192.168.1.1"
2064  *  optional port               ":5683"
2065  *  resource uri                "/oc/core..."
2066  *
2067  *  for PRESENCE requests, extract resource type.
2068  */
2069 static OCStackResult ParseRequestUri(const char *fullUri,
2070                                         OCTransportAdapter adapter,
2071                                         OCTransportFlags flags,
2072                                         OCDevAddr **devAddr,
2073                                         char **resourceUri,
2074                                         char **resourceType)
2075 {
2076     VERIFY_NON_NULL(fullUri, FATAL, OC_STACK_INVALID_CALLBACK);
2077
2078     OCStackResult result = OC_STACK_OK;
2079     OCDevAddr *da = NULL;
2080     char *colon = NULL;
2081     char *end;
2082
2083     // provide defaults for all returned values
2084     if (devAddr)
2085     {
2086         *devAddr = NULL;
2087     }
2088     if (resourceUri)
2089     {
2090         *resourceUri = NULL;
2091     }
2092     if (resourceType)
2093     {
2094         *resourceType = NULL;
2095     }
2096
2097     // delimit url prefix, if any
2098     const char *start = fullUri;
2099     char *slash2 = strstr(start, "//");
2100     if (slash2)
2101     {
2102         start = slash2 + 2;
2103     }
2104     char *slash = strchr(start, '/');
2105     if (!slash)
2106     {
2107         return OC_STACK_INVALID_URI;
2108     }
2109
2110 #ifdef TCP_ADAPTER
2111     // process url scheme
2112     size_t prefixLen = slash2 - fullUri;
2113     bool istcp = false;
2114     if (prefixLen)
2115     {
2116         if ((prefixLen == sizeof(COAP_TCP) - 1) && (!strncmp(fullUri, COAP_TCP, prefixLen)))
2117         {
2118             istcp = true;
2119         }
2120     }
2121 #endif
2122
2123     // TODO: this logic should come in with unit tests exercising the various strings
2124     // processs url prefix, if any
2125     size_t urlLen = slash - start;
2126     // port
2127     uint16_t port = 0;
2128     size_t len = 0;
2129     if (urlLen && devAddr)
2130     {   // construct OCDevAddr
2131         if (start[0] == '[')
2132         {   // ipv6 address
2133             char *close = strchr(++start, ']');
2134             if (!close || close > slash)
2135             {
2136                 return OC_STACK_INVALID_URI;
2137             }
2138             end = close;
2139             if (close[1] == ':')
2140             {
2141                 colon = close + 1;
2142             }
2143             adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
2144             flags = (OCTransportFlags)(flags | OC_IP_USE_V6);
2145         }
2146         else
2147         {
2148             char *dot = strchr(start, '.');
2149             if (dot && dot < slash)
2150             {   // ipv4 address
2151                 colon = strchr(start, ':');
2152                 end = (colon && colon < slash) ? colon : slash;
2153 #ifdef TCP_ADAPTER
2154                 if (istcp)
2155                 {   // coap over tcp
2156                     adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_TCP);
2157                 }
2158                 else
2159 #endif
2160                 {
2161                     adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
2162                     flags = (OCTransportFlags)(flags | OC_IP_USE_V4);
2163                 }
2164             }
2165             else
2166             {   // MAC address
2167                 end = slash;
2168             }
2169         }
2170         len = end - start;
2171         if (len >= sizeof(da->addr))
2172         {
2173             return OC_STACK_INVALID_URI;
2174         }
2175         // collect port, if any
2176         if (colon && colon < slash)
2177         {
2178             for (colon++; colon < slash; colon++)
2179             {
2180                 char c = colon[0];
2181                 if (c < '0' || c > '9')
2182                 {
2183                     return OC_STACK_INVALID_URI;
2184                 }
2185                 port = 10 * port + c - '0';
2186             }
2187         }
2188
2189         len = end - start;
2190         if (len >= sizeof(da->addr))
2191         {
2192             return OC_STACK_INVALID_URI;
2193         }
2194
2195         da = (OCDevAddr *)OICCalloc(sizeof (OCDevAddr), 1);
2196         if (!da)
2197         {
2198             return OC_STACK_NO_MEMORY;
2199         }
2200         OICStrcpyPartial(da->addr, sizeof(da->addr), start, len);
2201         da->port = port;
2202         da->adapter = adapter;
2203         da->flags = flags;
2204         if (!strncmp(fullUri, "coaps:", 6))
2205         {
2206             da->flags = (OCTransportFlags)(da->flags|CA_SECURE);
2207         }
2208         *devAddr = da;
2209     }
2210
2211     // process resource uri, if any
2212     if (slash)
2213     {   // request uri and query
2214         size_t ulen = strlen(slash); // resource uri length
2215         size_t tlen = 0;      // resource type length
2216         char *type = NULL;
2217
2218         static const char strPresence[] = "/oic/ad?rt=";
2219         static const size_t lenPresence = sizeof(strPresence) - 1;
2220         if (!strncmp(slash, strPresence, lenPresence))
2221         {
2222             type = slash + lenPresence;
2223             tlen = ulen - lenPresence;
2224         }
2225         // resource uri
2226         if (resourceUri)
2227         {
2228             *resourceUri = (char *)OICMalloc(ulen + 1);
2229             if (!*resourceUri)
2230             {
2231                 result = OC_STACK_NO_MEMORY;
2232                 goto error;
2233             }
2234             strcpy(*resourceUri, slash);
2235         }
2236         // resource type
2237         if (type && resourceType)
2238         {
2239             *resourceType = (char *)OICMalloc(tlen + 1);
2240             if (!*resourceType)
2241             {
2242                 result = OC_STACK_NO_MEMORY;
2243                 goto error;
2244             }
2245
2246             OICStrcpy(*resourceType, (tlen+1), type);
2247         }
2248     }
2249
2250     return OC_STACK_OK;
2251
2252 error:
2253     // free all returned values
2254     if (devAddr)
2255     {
2256         OICFree(*devAddr);
2257     }
2258     if (resourceUri)
2259     {
2260         OICFree(*resourceUri);
2261     }
2262     if (resourceType)
2263     {
2264         OICFree(*resourceType);
2265     }
2266     return result;
2267 }
2268
2269 static OCStackResult OCPreparePresence(CAEndpoint_t *endpoint,
2270                                         char *resourceUri, char **requestUri)
2271 {
2272     char uri[CA_MAX_URI_LENGTH];
2273
2274     FormCanonicalPresenceUri(endpoint, resourceUri, uri);
2275
2276     *requestUri = OICStrdup(uri);
2277     if (!*requestUri)
2278     {
2279         return OC_STACK_NO_MEMORY;
2280     }
2281
2282     return OC_STACK_OK;
2283 }
2284
2285 /**
2286  * Discover or Perform requests on a specified resource
2287  */
2288 OCStackResult OCDoResource(OCDoHandle *handle,
2289                             OCMethod method,
2290                             const char *requestUri,
2291                             const OCDevAddr *destination,
2292                             OCPayload* payload,
2293                             OCConnectivityType connectivityType,
2294                             OCQualityOfService qos,
2295                             OCCallbackData *cbData,
2296                             OCHeaderOption *options,
2297                             uint8_t numOptions)
2298 {
2299     OC_LOG(INFO, TAG, "Entering OCDoResource");
2300
2301     // Validate input parameters
2302     VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
2303     VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
2304     VERIFY_NON_NULL(requestUri , FATAL, OC_STACK_INVALID_URI);
2305
2306     OCStackResult result = OC_STACK_ERROR;
2307     CAResult_t caResult;
2308     CAToken_t token = NULL;
2309     uint8_t tokenLength = CA_MAX_TOKEN_LEN;
2310     ClientCB *clientCB = NULL;
2311     OCDoHandle resHandle = NULL;
2312     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2313     OCDevAddr tmpDevAddr = { OC_DEFAULT_ADAPTER };
2314     uint32_t ttl = 0;
2315     OCTransportAdapter adapter;
2316     OCTransportFlags flags;
2317     // the request contents are put here
2318     CARequestInfo_t requestInfo = {.method = CA_GET};
2319     // requestUri  will be parsed into the following three variables
2320     OCDevAddr *devAddr = NULL;
2321     char *resourceUri = NULL;
2322     char *resourceType = NULL;
2323
2324     // To track if memory is allocated for additional header options
2325     uint8_t hdrOptionMemAlloc = 0;
2326
2327     // This validation is broken, but doesn't cause harm
2328     size_t uriLen = strlen(requestUri );
2329     if ((result = verifyUriQueryLength(requestUri , uriLen)) != OC_STACK_OK)
2330     {
2331         goto exit;
2332     }
2333
2334     /*
2335      * Support original behavior with address on resourceUri argument.
2336      */
2337     adapter = (OCTransportAdapter)(connectivityType >> CT_ADAPTER_SHIFT);
2338     flags = (OCTransportFlags)(connectivityType & CT_MASK_FLAGS);
2339
2340     result = ParseRequestUri(requestUri, adapter, flags, &devAddr, &resourceUri, &resourceType);
2341
2342     if (result != OC_STACK_OK)
2343     {
2344         OC_LOG_V(DEBUG, TAG, "Unable to parse uri: %s", requestUri);
2345         goto exit;
2346     }
2347
2348     switch (method)
2349     {
2350     case OC_REST_GET:
2351     case OC_REST_OBSERVE:
2352     case OC_REST_OBSERVE_ALL:
2353     case OC_REST_CANCEL_OBSERVE:
2354         requestInfo.method = CA_GET;
2355         break;
2356     case OC_REST_PUT:
2357         requestInfo.method = CA_PUT;
2358         break;
2359     case OC_REST_POST:
2360         requestInfo.method = CA_POST;
2361         break;
2362     case OC_REST_DELETE:
2363         requestInfo.method = CA_DELETE;
2364         break;
2365     case OC_REST_DISCOVER:
2366         qos = OC_LOW_QOS;
2367         if (destination || devAddr)
2368         {
2369             requestInfo.isMulticast = false;
2370         }
2371         else
2372         {
2373             tmpDevAddr.adapter = adapter;
2374             tmpDevAddr.flags = flags;
2375             destination = &tmpDevAddr;
2376             requestInfo.isMulticast = true;
2377         }
2378         // CA_DISCOVER will become GET and isMulticast
2379         requestInfo.method = CA_GET;
2380         break;
2381 #ifdef WITH_PRESENCE
2382     case OC_REST_PRESENCE:
2383         // Replacing method type with GET because "presence"
2384         // is a stack layer only implementation.
2385         requestInfo.method = CA_GET;
2386         break;
2387 #endif
2388     default:
2389         result = OC_STACK_INVALID_METHOD;
2390         goto exit;
2391     }
2392
2393     if (!devAddr && !destination)
2394     {
2395         OC_LOG(DEBUG, TAG, "no devAddr and no destination");
2396         result = OC_STACK_INVALID_PARAM;
2397         goto exit;
2398     }
2399
2400     /* If not original behavior, use destination argument */
2401     if (destination && !devAddr)
2402     {
2403         devAddr = (OCDevAddr *)OICMalloc(sizeof (OCDevAddr));
2404         if (!devAddr)
2405         {
2406             result = OC_STACK_NO_MEMORY;
2407             goto exit;
2408         }
2409         *devAddr = *destination;
2410     }
2411
2412     resHandle = GenerateInvocationHandle();
2413     if (!resHandle)
2414     {
2415         result = OC_STACK_NO_MEMORY;
2416         goto exit;
2417     }
2418
2419     caResult = CAGenerateToken(&token, tokenLength);
2420     if (caResult != CA_STATUS_OK)
2421     {
2422         OC_LOG(ERROR, TAG, "CAGenerateToken error");
2423         result= OC_STACK_ERROR;
2424         goto exit;
2425     }
2426
2427     // fill in request data
2428     requestInfo.info.type = qualityOfServiceToMessageType(qos);
2429     requestInfo.info.token = token;
2430     requestInfo.info.tokenLength = tokenLength;
2431     requestInfo.info.resourceUri = resourceUri;
2432
2433     if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
2434     {
2435         result = CreateObserveHeaderOption (&(requestInfo.info.options),
2436                                     options, numOptions, OC_OBSERVE_REGISTER);
2437         if (result != OC_STACK_OK)
2438         {
2439             goto exit;
2440         }
2441         hdrOptionMemAlloc = 1;
2442         requestInfo.info.numOptions = numOptions + 1;
2443     }
2444     else
2445     {
2446         requestInfo.info.options = (CAHeaderOption_t*)options;
2447         requestInfo.info.numOptions = numOptions;
2448     }
2449
2450     CopyDevAddrToEndpoint(devAddr, &endpoint);
2451
2452     if(payload)
2453     {
2454         if((result =
2455             OCConvertPayload(payload, &requestInfo.info.payload, &requestInfo.info.payloadSize))
2456                 != OC_STACK_OK)
2457         {
2458             OC_LOG(ERROR, TAG, "Failed to create CBOR Payload");
2459             goto exit;
2460         }
2461         requestInfo.info.payloadFormat = CA_FORMAT_APPLICATION_CBOR;
2462     }
2463     else
2464     {
2465         requestInfo.info.payload = NULL;
2466         requestInfo.info.payloadSize = 0;
2467         requestInfo.info.payloadFormat = CA_FORMAT_UNDEFINED;
2468     }
2469
2470     if (result != OC_STACK_OK)
2471     {
2472         OC_LOG(ERROR, TAG, "CACreateEndpoint error");
2473         goto exit;
2474     }
2475
2476     // prepare for response
2477 #ifdef WITH_PRESENCE
2478     if (method == OC_REST_PRESENCE)
2479     {
2480         char *presenceUri = NULL;
2481         result = OCPreparePresence(&endpoint, resourceUri, &presenceUri);
2482         if (OC_STACK_OK != result)
2483         {
2484             goto exit;
2485         }
2486
2487         // Assign full presence uri as coap://ip:port/oic/ad to add to callback list.
2488         // Presence notification will form a canonical uri to
2489         // look for callbacks into the application.
2490         resourceUri = presenceUri;
2491     }
2492 #endif
2493
2494     ttl = GetTicks(MAX_CB_TIMEOUT_SECONDS * MILLISECONDS_PER_SECOND);
2495     result = AddClientCB(&clientCB, cbData, token, tokenLength, &resHandle,
2496                             method, devAddr, resourceUri, resourceType, ttl);
2497     if (OC_STACK_OK != result)
2498     {
2499         goto exit;
2500     }
2501
2502     devAddr = NULL;       // Client CB list entry now owns it
2503     resourceUri = NULL;   // Client CB list entry now owns it
2504     resourceType = NULL;  // Client CB list entry now owns it
2505
2506     // send request
2507     result = OCSendRequest(&endpoint, &requestInfo);
2508     if (OC_STACK_OK != result)
2509     {
2510         goto exit;
2511     }
2512
2513     if (handle)
2514     {
2515         *handle = resHandle;
2516     }
2517
2518 exit:
2519     if (result != OC_STACK_OK)
2520     {
2521         OC_LOG(ERROR, TAG, "OCDoResource error");
2522         FindAndDeleteClientCB(clientCB);
2523         CADestroyToken(token);
2524         if (handle)
2525         {
2526             *handle = NULL;
2527         }
2528         OICFree(resHandle);
2529     }
2530
2531     // This is the owner of the payload object, so we free it
2532     OCPayloadDestroy(payload);
2533     OICFree(requestInfo.info.payload);
2534     OICFree(devAddr);
2535     OICFree(resourceUri);
2536     OICFree(resourceType);
2537     if (hdrOptionMemAlloc)
2538     {
2539         OICFree(requestInfo.info.options);
2540     }
2541     return result;
2542 }
2543
2544 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
2545         uint8_t numOptions)
2546 {
2547     /*
2548      * This ftn is implemented one of two ways in the case of observation:
2549      *
2550      * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
2551      *      Remove the callback associated on client side.
2552      *      When the next notification comes in from server,
2553      *      reply with RESET message to server.
2554      *      Keep in mind that the server will react to RESET only
2555      *      if the last notification was sent as CON
2556      *
2557      * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
2558      *      and it is associated with an observe request
2559      *      (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
2560      *      Send CON Observe request to server with
2561      *      observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
2562      *      Remove the callback associated on client side.
2563      */
2564     OCStackResult ret = OC_STACK_OK;
2565     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2566     CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
2567     CARequestInfo_t requestInfo = {.method = CA_GET};
2568
2569     if(!handle)
2570     {
2571         return OC_STACK_INVALID_PARAM;
2572     }
2573
2574     ClientCB *clientCB = GetClientCB(NULL, 0, handle, NULL);
2575     if (!clientCB)
2576     {
2577         OC_LOG(ERROR, TAG, "Client callback not found. Called OCCancel twice?");
2578         goto Error;
2579     }
2580
2581     switch (clientCB->method)
2582     {
2583         case OC_REST_OBSERVE:
2584         case OC_REST_OBSERVE_ALL:
2585             OC_LOG_V(INFO, TAG, "Canceling observation for resource %s",
2586                                         clientCB->requestUri);
2587             if (qos != OC_HIGH_QOS)
2588             {
2589                 FindAndDeleteClientCB(clientCB);
2590                 break;
2591             }
2592             else
2593             {
2594                 OC_LOG(INFO, TAG, "Cancelling observation as CONFIRMABLE");
2595             }
2596
2597             requestData.type = qualityOfServiceToMessageType(qos);
2598             requestData.token = clientCB->token;
2599             requestData.tokenLength = clientCB->tokenLength;
2600             if (CreateObserveHeaderOption (&(requestData.options),
2601                     options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
2602             {
2603                 return OC_STACK_ERROR;
2604             }
2605             requestData.numOptions = numOptions + 1;
2606             requestData.resourceUri = OICStrdup (clientCB->requestUri);
2607
2608             requestInfo.method = CA_GET;
2609             requestInfo.info = requestData;
2610
2611             CopyDevAddrToEndpoint(clientCB->devAddr, &endpoint);
2612
2613             // send request
2614             ret = OCSendRequest(&endpoint, &requestInfo);
2615             break;
2616
2617 #ifdef WITH_PRESENCE
2618         case OC_REST_PRESENCE:
2619             FindAndDeleteClientCB(clientCB);
2620             break;
2621 #endif
2622
2623         default:
2624             ret = OC_STACK_INVALID_METHOD;
2625             break;
2626     }
2627
2628 Error:
2629     if (requestData.numOptions > 0)
2630     {
2631         OICFree(requestData.options);
2632     }
2633     if (requestData.resourceUri)
2634     {
2635         OICFree (requestData.resourceUri);
2636     }
2637     return ret;
2638 }
2639
2640 /**
2641  * @brief   Register Persistent storage callback.
2642  * @param   persistentStorageHandler [IN] Pointers to open, read, write, close & unlink handlers.
2643  * @return
2644  *     OC_STACK_OK    - No errors; Success
2645  *     OC_STACK_INVALID_PARAM - Invalid parameter
2646  */
2647 OCStackResult OCRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
2648 {
2649     OC_LOG(INFO, TAG, "RegisterPersistentStorageHandler !!");
2650     if(!persistentStorageHandler)
2651     {
2652         OC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
2653         return OC_STACK_INVALID_PARAM;
2654     }
2655     else
2656     {
2657         if( !persistentStorageHandler->open ||
2658                 !persistentStorageHandler->close ||
2659                 !persistentStorageHandler->read ||
2660                 !persistentStorageHandler->unlink ||
2661                 !persistentStorageHandler->write)
2662         {
2663             OC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
2664             return OC_STACK_INVALID_PARAM;
2665         }
2666     }
2667     return SRMRegisterPersistentStorageHandler(persistentStorageHandler);
2668 }
2669
2670 #ifdef WITH_PRESENCE
2671
2672 OCStackResult OCProcessPresence()
2673 {
2674     OCStackResult result = OC_STACK_OK;
2675
2676     // the following line floods the log with messages that are irrelevant
2677     // to most purposes.  Uncomment as needed.
2678     //OC_LOG(INFO, TAG, "Entering RequestPresence");
2679     ClientCB* cbNode = NULL;
2680     OCClientResponse clientResponse;
2681     OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
2682
2683     LL_FOREACH(cbList, cbNode)
2684     {
2685         if (OC_REST_PRESENCE != cbNode->method || !cbNode->presence)
2686         {
2687             continue;
2688         }
2689
2690         uint32_t now = GetTicks(0);
2691         OC_LOG_V(DEBUG, TAG, "this TTL level %d",
2692                                                 cbNode->presence->TTLlevel);
2693         OC_LOG_V(DEBUG, TAG, "current ticks %d", now);
2694
2695         if (cbNode->presence->TTLlevel > PresenceTimeOutSize)
2696         {
2697             goto exit;
2698         }
2699
2700         if (cbNode->presence->TTLlevel < PresenceTimeOutSize)
2701         {
2702             OC_LOG_V(DEBUG, TAG, "timeout ticks %d",
2703                     cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
2704         }
2705         if (cbNode->presence->TTLlevel >= PresenceTimeOutSize)
2706         {
2707             OC_LOG(DEBUG, TAG, "No more timeout ticks");
2708
2709             clientResponse.sequenceNumber = 0;
2710             clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
2711             clientResponse.devAddr = *cbNode->devAddr;
2712             FixUpClientResponse(&clientResponse);
2713             clientResponse.payload = NULL;
2714
2715             // Increment the TTLLevel (going to a next state), so we don't keep
2716             // sending presence notification to client.
2717             cbNode->presence->TTLlevel++;
2718             OC_LOG_V(DEBUG, TAG, "moving to TTL level %d",
2719                                         cbNode->presence->TTLlevel);
2720
2721             cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse);
2722             if (cbResult == OC_STACK_DELETE_TRANSACTION)
2723             {
2724                 FindAndDeleteClientCB(cbNode);
2725             }
2726         }
2727
2728         if (now < cbNode->presence->timeOut[cbNode->presence->TTLlevel])
2729         {
2730             continue;
2731         }
2732
2733         CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2734         CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
2735         CARequestInfo_t requestInfo = {.method = CA_GET};
2736
2737         OC_LOG(DEBUG, TAG, "time to test server presence");
2738
2739         CopyDevAddrToEndpoint(cbNode->devAddr, &endpoint);
2740
2741         requestData.type = CA_MSG_NONCONFIRM;
2742         requestData.token = cbNode->token;
2743         requestData.tokenLength = cbNode->tokenLength;
2744         requestData.resourceUri = OC_RSRVD_PRESENCE_URI;
2745         requestInfo.method = CA_GET;
2746         requestInfo.info = requestData;
2747
2748         result = OCSendRequest(&endpoint, &requestInfo);
2749         if (OC_STACK_OK != result)
2750         {
2751             goto exit;
2752         }
2753
2754         cbNode->presence->TTLlevel++;
2755         OC_LOG_V(DEBUG, TAG, "moving to TTL level %d", cbNode->presence->TTLlevel);
2756     }
2757 exit:
2758     if (result != OC_STACK_OK)
2759     {
2760         OC_LOG(ERROR, TAG, "OCProcessPresence error");
2761     }
2762
2763     return result;
2764 }
2765 #endif // WITH_PRESENCE
2766
2767 OCStackResult OCProcess()
2768 {
2769 #ifdef WITH_PRESENCE
2770     OCProcessPresence();
2771 #endif
2772     CAHandleRequestResponse();
2773
2774 #ifdef ROUTING_GATEWAY
2775     RMProcess();
2776 #endif
2777     return OC_STACK_OK;
2778 }
2779
2780 #ifdef WITH_PRESENCE
2781 OCStackResult OCStartPresence(const uint32_t ttl)
2782 {
2783     uint8_t tokenLength = CA_MAX_TOKEN_LEN;
2784     OCChangeResourceProperty(
2785             &(((OCResource *)presenceResource.handle)->resourceProperties),
2786             OC_ACTIVE, 1);
2787
2788     if (OC_MAX_PRESENCE_TTL_SECONDS < ttl)
2789     {
2790         presenceResource.presenceTTL = OC_MAX_PRESENCE_TTL_SECONDS;
2791         OC_LOG(INFO, TAG, "Setting Presence TTL to max value");
2792     }
2793     else if (0 == ttl)
2794     {
2795         presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
2796         OC_LOG(INFO, TAG, "Setting Presence TTL to default value");
2797     }
2798     else
2799     {
2800         presenceResource.presenceTTL = ttl;
2801     }
2802     OC_LOG_V(DEBUG, TAG, "Presence TTL is %lu seconds", presenceResource.presenceTTL);
2803
2804     if (OC_PRESENCE_UNINITIALIZED == presenceState)
2805     {
2806         presenceState = OC_PRESENCE_INITIALIZED;
2807
2808         OCDevAddr devAddr = { OC_DEFAULT_ADAPTER };
2809
2810         CAToken_t caToken = NULL;
2811         CAResult_t caResult = CAGenerateToken(&caToken, tokenLength);
2812         if (caResult != CA_STATUS_OK)
2813         {
2814             OC_LOG(ERROR, TAG, "CAGenerateToken error");
2815             CADestroyToken(caToken);
2816             return OC_STACK_ERROR;
2817         }
2818
2819         AddObserver(OC_RSRVD_PRESENCE_URI, NULL, 0, caToken, tokenLength,
2820                 (OCResource *)presenceResource.handle, OC_LOW_QOS, OC_FORMAT_UNDEFINED, &devAddr);
2821         CADestroyToken(caToken);
2822     }
2823
2824     // Each time OCStartPresence is called
2825     // a different random 32-bit integer number is used
2826     ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2827
2828     return SendPresenceNotification(((OCResource *)presenceResource.handle)->rsrcType,
2829             OC_PRESENCE_TRIGGER_CREATE);
2830 }
2831
2832 OCStackResult OCStopPresence()
2833 {
2834     OCStackResult result = OC_STACK_ERROR;
2835
2836     if(presenceResource.handle)
2837     {
2838         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2839
2840     // make resource inactive
2841     result = OCChangeResourceProperty(
2842             &(((OCResource *) presenceResource.handle)->resourceProperties),
2843             OC_ACTIVE, 0);
2844     }
2845
2846     if(result != OC_STACK_OK)
2847     {
2848         OC_LOG(ERROR, TAG,
2849                       "Changing the presence resource properties to ACTIVE not successful");
2850         return result;
2851     }
2852
2853     return SendStopNotification();
2854 }
2855 #endif
2856
2857 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler,
2858                                             void* callbackParameter)
2859 {
2860     defaultDeviceHandler = entityHandler;
2861     defaultDeviceHandlerCallbackParameter = callbackParameter;
2862
2863     return OC_STACK_OK;
2864 }
2865
2866 OCStackResult OCSetPlatformInfo(OCPlatformInfo platformInfo)
2867 {
2868     OC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
2869
2870     if(myStackMode ==  OC_SERVER || myStackMode == OC_CLIENT_SERVER || myStackMode == OC_GATEWAY)
2871     {
2872         if (validatePlatformInfo(platformInfo))
2873         {
2874             return SavePlatformInfo(platformInfo);
2875         }
2876         else
2877         {
2878             return OC_STACK_INVALID_PARAM;
2879         }
2880     }
2881     else
2882     {
2883         return OC_STACK_ERROR;
2884     }
2885 }
2886
2887 OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
2888 {
2889     OC_LOG(INFO, TAG, "Entering OCSetDeviceInfo");
2890
2891     if (!deviceInfo.deviceName || deviceInfo.deviceName[0] == '\0')
2892     {
2893         OC_LOG(ERROR, TAG, "Null or empty device name.");
2894         return OC_STACK_INVALID_PARAM;
2895     }
2896
2897     return SaveDeviceInfo(deviceInfo);
2898 }
2899
2900 OCStackResult OCCreateResource(OCResourceHandle *handle,
2901         const char *resourceTypeName,
2902         const char *resourceInterfaceName,
2903         const char *uri, OCEntityHandler entityHandler,
2904         void* callbackParam,
2905         uint8_t resourceProperties)
2906 {
2907
2908     OCResource *pointer = NULL;
2909     char *str = NULL;
2910     OCStackResult result = OC_STACK_ERROR;
2911
2912     OC_LOG(INFO, TAG, "Entering OCCreateResource");
2913
2914     if(myStackMode == OC_CLIENT)
2915     {
2916         return OC_STACK_INVALID_PARAM;
2917     }
2918     // Validate parameters
2919     if(!uri || uri[0]=='\0' || strlen(uri)>=MAX_URI_LENGTH )
2920     {
2921         OC_LOG(ERROR, TAG, "URI is empty or too long");
2922         return OC_STACK_INVALID_URI;
2923     }
2924     // Is it presented during resource discovery?
2925     if (!handle || !resourceTypeName || resourceTypeName[0] == '\0' )
2926     {
2927         OC_LOG(ERROR, TAG, "Input parameter is NULL");
2928         return OC_STACK_INVALID_PARAM;
2929     }
2930
2931     if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0)
2932     {
2933         resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
2934     }
2935
2936     // Make sure resourceProperties bitmask has allowed properties specified
2937     if (resourceProperties
2938             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE |
2939                OC_EXPLICIT_DISCOVERABLE))
2940     {
2941         OC_LOG(ERROR, TAG, "Invalid property");
2942         return OC_STACK_INVALID_PARAM;
2943     }
2944
2945     // If the headResource is NULL, then no resources have been created...
2946     pointer = headResource;
2947     if (pointer)
2948     {
2949         // At least one resources is in the resource list, so we need to search for
2950         // repeated URLs, which are not allowed.  If a repeat is found, exit with an error
2951         while (pointer)
2952         {
2953             if (strncmp(uri, pointer->uri, MAX_URI_LENGTH) == 0)
2954             {
2955                 OC_LOG_V(ERROR, TAG, "Resource %s already exists", uri);
2956                 return OC_STACK_INVALID_PARAM;
2957             }
2958             pointer = pointer->next;
2959         }
2960     }
2961     // Create the pointer and insert it into the resource list
2962     pointer = (OCResource *) OICCalloc(1, sizeof(OCResource));
2963     if (!pointer)
2964     {
2965         result = OC_STACK_NO_MEMORY;
2966         goto exit;
2967     }
2968     pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
2969
2970     insertResource(pointer);
2971
2972     // Set the uri
2973     str = OICStrdup(uri);
2974     if (!str)
2975     {
2976         result = OC_STACK_NO_MEMORY;
2977         goto exit;
2978     }
2979     pointer->uri = str;
2980
2981     // Set properties.  Set OC_ACTIVE
2982     pointer->resourceProperties = (OCResourceProperty) (resourceProperties
2983             | OC_ACTIVE);
2984
2985     // Add the resourcetype to the resource
2986     result = BindResourceTypeToResource(pointer, resourceTypeName);
2987     if (result != OC_STACK_OK)
2988     {
2989         OC_LOG(ERROR, TAG, "Error adding resourcetype");
2990         goto exit;
2991     }
2992
2993     // Add the resourceinterface to the resource
2994     result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
2995     if (result != OC_STACK_OK)
2996     {
2997         OC_LOG(ERROR, TAG, "Error adding resourceinterface");
2998         goto exit;
2999     }
3000
3001     // If an entity handler has been passed, attach it to the newly created
3002     // resource.  Otherwise, set the default entity handler.
3003     if (entityHandler)
3004     {
3005         pointer->entityHandler = entityHandler;
3006         pointer->entityHandlerCallbackParam = callbackParam;
3007     }
3008     else
3009     {
3010         pointer->entityHandler = defaultResourceEHandler;
3011         pointer->entityHandlerCallbackParam = NULL;
3012     }
3013
3014     *handle = pointer;
3015     result = OC_STACK_OK;
3016
3017 #ifdef WITH_PRESENCE
3018     if (presenceResource.handle)
3019     {
3020         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3021         SendPresenceNotification(pointer->rsrcType, OC_PRESENCE_TRIGGER_CREATE);
3022     }
3023 #endif
3024 exit:
3025     if (result != OC_STACK_OK)
3026     {
3027         // Deep delete of resource and other dynamic elements that it contains
3028         deleteResource(pointer);
3029         OICFree(str);
3030     }
3031     return result;
3032 }
3033
3034
3035 OCStackResult OCBindResource(
3036         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
3037 {
3038     OCResource *resource = NULL;
3039     uint8_t i = 0;
3040
3041     OC_LOG(INFO, TAG, "Entering OCBindResource");
3042
3043     // Validate parameters
3044     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
3045     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
3046     // Container cannot contain itself
3047     if (collectionHandle == resourceHandle)
3048     {
3049         OC_LOG(ERROR, TAG, "Added handle equals collection handle");
3050         return OC_STACK_INVALID_PARAM;
3051     }
3052
3053     // Use the handle to find the resource in the resource linked list
3054     resource = findResource((OCResource *) collectionHandle);
3055     if (!resource)
3056     {
3057         OC_LOG(ERROR, TAG, "Collection handle not found");
3058         return OC_STACK_INVALID_PARAM;
3059     }
3060
3061     // Look for an open slot to add add the child resource.
3062     // If found, add it and return success
3063     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
3064     {
3065         if (!resource->rsrcResources[i])
3066         {
3067             resource->rsrcResources[i] = (OCResource *) resourceHandle;
3068             OC_LOG(INFO, TAG, "resource bound");
3069
3070 #ifdef WITH_PRESENCE
3071             if (presenceResource.handle)
3072             {
3073                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3074                 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
3075                         OC_PRESENCE_TRIGGER_CHANGE);
3076             }
3077 #endif
3078             return OC_STACK_OK;
3079
3080         }
3081     }
3082
3083     // Unable to add resourceHandle, so return error
3084     return OC_STACK_ERROR;
3085 }
3086
3087 OCStackResult OCUnBindResource(
3088         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
3089 {
3090     OCResource *resource = NULL;
3091     uint8_t i = 0;
3092
3093     OC_LOG(INFO, TAG, "Entering OCUnBindResource");
3094
3095     // Validate parameters
3096     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
3097     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
3098     // Container cannot contain itself
3099     if (collectionHandle == resourceHandle)
3100     {
3101         OC_LOG(ERROR, TAG, "removing handle equals collection handle");
3102         return OC_STACK_INVALID_PARAM;
3103     }
3104
3105     // Use the handle to find the resource in the resource linked list
3106     resource = findResource((OCResource *) collectionHandle);
3107     if (!resource)
3108     {
3109         OC_LOG(ERROR, TAG, "Collection handle not found");
3110         return OC_STACK_INVALID_PARAM;
3111     }
3112
3113     // Look for an open slot to add add the child resource.
3114     // If found, add it and return success
3115     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
3116     {
3117         if (resourceHandle == resource->rsrcResources[i])
3118         {
3119             resource->rsrcResources[i] = (OCResource *) NULL;
3120             OC_LOG(INFO, TAG, "resource unbound");
3121
3122             // Send notification when resource is unbounded successfully.
3123 #ifdef WITH_PRESENCE
3124             if (presenceResource.handle)
3125             {
3126                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3127                 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
3128                         OC_PRESENCE_TRIGGER_CHANGE);
3129             }
3130 #endif
3131             return OC_STACK_OK;
3132         }
3133     }
3134
3135     OC_LOG(INFO, TAG, "resource not found in collection");
3136
3137     // Unable to add resourceHandle, so return error
3138     return OC_STACK_ERROR;
3139 }
3140
3141 OCStackResult BindResourceTypeToResource(OCResource* resource,
3142                                             const char *resourceTypeName)
3143 {
3144     OCResourceType *pointer = NULL;
3145     char *str = NULL;
3146     OCStackResult result = OC_STACK_ERROR;
3147
3148     VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
3149
3150     pointer = (OCResourceType *) OICCalloc(1, sizeof(OCResourceType));
3151     if (!pointer)
3152     {
3153         result = OC_STACK_NO_MEMORY;
3154         goto exit;
3155     }
3156
3157     str = OICStrdup(resourceTypeName);
3158     if (!str)
3159     {
3160         result = OC_STACK_NO_MEMORY;
3161         goto exit;
3162     }
3163     pointer->resourcetypename = str;
3164
3165     insertResourceType(resource, pointer);
3166     result = OC_STACK_OK;
3167
3168     exit:
3169     if (result != OC_STACK_OK)
3170     {
3171         OICFree(pointer);
3172         OICFree(str);
3173     }
3174
3175     return result;
3176 }
3177
3178 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
3179         const char *resourceInterfaceName)
3180 {
3181     OCResourceInterface *pointer = NULL;
3182     char *str = NULL;
3183     OCStackResult result = OC_STACK_ERROR;
3184
3185     VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
3186
3187     OC_LOG_V(INFO, TAG, "Binding %s interface to %s", resourceInterfaceName, resource->uri);
3188
3189     pointer = (OCResourceInterface *) OICCalloc(1, sizeof(OCResourceInterface));
3190     if (!pointer)
3191     {
3192         result = OC_STACK_NO_MEMORY;
3193         goto exit;
3194     }
3195
3196     str = OICStrdup(resourceInterfaceName);
3197     if (!str)
3198     {
3199         result = OC_STACK_NO_MEMORY;
3200         goto exit;
3201     }
3202     pointer->name = str;
3203
3204     // Bind the resourceinterface to the resource
3205     insertResourceInterface(resource, pointer);
3206
3207     result = OC_STACK_OK;
3208
3209     exit:
3210     if (result != OC_STACK_OK)
3211     {
3212         OICFree(pointer);
3213         OICFree(str);
3214     }
3215
3216     return result;
3217 }
3218
3219 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
3220         const char *resourceTypeName)
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 = BindResourceTypeToResource(resource, resourceTypeName);
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 OCBindResourceInterfaceToResource(OCResourceHandle handle,
3247         const char *resourceInterfaceName)
3248 {
3249
3250     OCStackResult result = OC_STACK_ERROR;
3251     OCResource *resource = NULL;
3252
3253     resource = findResource((OCResource *) handle);
3254     if (!resource)
3255     {
3256         OC_LOG(ERROR, TAG, "Resource not found");
3257         return OC_STACK_ERROR;
3258     }
3259
3260     result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
3261
3262 #ifdef WITH_PRESENCE
3263     if (presenceResource.handle)
3264     {
3265         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3266         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3267     }
3268 #endif
3269
3270     return result;
3271 }
3272
3273 OCStackResult OCGetNumberOfResources(uint8_t *numResources)
3274 {
3275     OCResource *pointer = headResource;
3276
3277     VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
3278     *numResources = 0;
3279     while (pointer)
3280     {
3281         *numResources = *numResources + 1;
3282         pointer = pointer->next;
3283     }
3284     return OC_STACK_OK;
3285 }
3286
3287 OCResourceHandle OCGetResourceHandle(uint8_t index)
3288 {
3289     OCResource *pointer = headResource;
3290
3291     for( uint8_t i = 0; i < index && pointer; ++i)
3292     {
3293         pointer = pointer->next;
3294     }
3295     return (OCResourceHandle) pointer;
3296 }
3297
3298 OCStackResult OCDeleteResource(OCResourceHandle handle)
3299 {
3300     if (!handle)
3301     {
3302         OC_LOG(ERROR, TAG, "Invalid handle for deletion");
3303         return OC_STACK_INVALID_PARAM;
3304     }
3305
3306     OCResource *resource = findResource((OCResource *) handle);
3307     if (resource == NULL)
3308     {
3309         OC_LOG(ERROR, TAG, "Resource not found");
3310         return OC_STACK_NO_RESOURCE;
3311     }
3312
3313     if (deleteResource((OCResource *) handle) != OC_STACK_OK)
3314     {
3315         OC_LOG(ERROR, TAG, "Error deleting resource");
3316         return OC_STACK_ERROR;
3317     }
3318
3319     return OC_STACK_OK;
3320 }
3321
3322 const char *OCGetResourceUri(OCResourceHandle handle)
3323 {
3324     OCResource *resource = NULL;
3325
3326     resource = findResource((OCResource *) handle);
3327     if (resource)
3328     {
3329         return resource->uri;
3330     }
3331     return (const char *) NULL;
3332 }
3333
3334 OCResourceProperty OCGetResourceProperties(OCResourceHandle handle)
3335 {
3336     OCResource *resource = NULL;
3337
3338     resource = findResource((OCResource *) handle);
3339     if (resource)
3340     {
3341         return resource->resourceProperties;
3342     }
3343     return (OCResourceProperty)-1;
3344 }
3345
3346 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
3347         uint8_t *numResourceTypes)
3348 {
3349     OCResource *resource = NULL;
3350     OCResourceType *pointer = NULL;
3351
3352     VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
3353     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3354
3355     *numResourceTypes = 0;
3356
3357     resource = findResource((OCResource *) handle);
3358     if (resource)
3359     {
3360         pointer = resource->rsrcType;
3361         while (pointer)
3362         {
3363             *numResourceTypes = *numResourceTypes + 1;
3364             pointer = pointer->next;
3365         }
3366     }
3367     return OC_STACK_OK;
3368 }
3369
3370 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index)
3371 {
3372     OCResourceType *resourceType = NULL;
3373
3374     resourceType = findResourceTypeAtIndex(handle, index);
3375     if (resourceType)
3376     {
3377         return resourceType->resourcetypename;
3378     }
3379     return (const char *) NULL;
3380 }
3381
3382 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
3383         uint8_t *numResourceInterfaces)
3384 {
3385     OCResourceInterface *pointer = NULL;
3386     OCResource *resource = NULL;
3387
3388     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3389     VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
3390
3391     *numResourceInterfaces = 0;
3392     resource = findResource((OCResource *) handle);
3393     if (resource)
3394     {
3395         pointer = resource->rsrcInterface;
3396         while (pointer)
3397         {
3398             *numResourceInterfaces = *numResourceInterfaces + 1;
3399             pointer = pointer->next;
3400         }
3401     }
3402     return OC_STACK_OK;
3403 }
3404
3405 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index)
3406 {
3407     OCResourceInterface *resourceInterface = NULL;
3408
3409     resourceInterface = findResourceInterfaceAtIndex(handle, index);
3410     if (resourceInterface)
3411     {
3412         return resourceInterface->name;
3413     }
3414     return (const char *) NULL;
3415 }
3416
3417 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
3418         uint8_t index)
3419 {
3420     OCResource *resource = NULL;
3421
3422     if (index >= MAX_CONTAINED_RESOURCES)
3423     {
3424         return NULL;
3425     }
3426
3427     resource = findResource((OCResource *) collectionHandle);
3428     if (!resource)
3429     {
3430         return NULL;
3431     }
3432
3433     return resource->rsrcResources[index];
3434 }
3435
3436 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
3437         OCEntityHandler entityHandler,
3438         void* callbackParam)
3439 {
3440     OCResource *resource = NULL;
3441
3442     // Validate parameters
3443     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3444
3445     // Use the handle to find the resource in the resource linked list
3446     resource = findResource((OCResource *)handle);
3447     if (!resource)
3448     {
3449         OC_LOG(ERROR, TAG, "Resource not found");
3450         return OC_STACK_ERROR;
3451     }
3452
3453     // Bind the handler
3454     resource->entityHandler = entityHandler;
3455     resource->entityHandlerCallbackParam = callbackParam;
3456
3457 #ifdef WITH_PRESENCE
3458     if (presenceResource.handle)
3459     {
3460         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3461         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3462     }
3463 #endif
3464
3465     return OC_STACK_OK;
3466 }
3467
3468 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle)
3469 {
3470     OCResource *resource = NULL;
3471
3472     resource = findResource((OCResource *)handle);
3473     if (!resource)
3474     {
3475         OC_LOG(ERROR, TAG, "Resource not found");
3476         return NULL;
3477     }
3478
3479     // Bind the handler
3480     return resource->entityHandler;
3481 }
3482
3483 void incrementSequenceNumber(OCResource * resPtr)
3484 {
3485     // Increment the sequence number
3486     resPtr->sequenceNum += 1;
3487     if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
3488     {
3489         resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
3490     }
3491     return;
3492 }
3493
3494 #ifdef WITH_PRESENCE
3495 OCStackResult SendPresenceNotification(OCResourceType *resourceType,
3496         OCPresenceTrigger trigger)
3497 {
3498     OCResource *resPtr = NULL;
3499     OCStackResult result = OC_STACK_ERROR;
3500     OCMethod method = OC_REST_PRESENCE;
3501     uint32_t maxAge = 0;
3502     resPtr = findResource((OCResource *) presenceResource.handle);
3503     if(NULL == resPtr)
3504     {
3505         return OC_STACK_NO_RESOURCE;
3506     }
3507
3508     if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
3509     {
3510         maxAge = presenceResource.presenceTTL;
3511
3512         result = SendAllObserverNotification(method, resPtr, maxAge,
3513                 trigger, resourceType, OC_LOW_QOS);
3514     }
3515
3516     return result;
3517 }
3518
3519 OCStackResult SendStopNotification()
3520 {
3521     OCResource *resPtr = NULL;
3522     OCStackResult result = OC_STACK_ERROR;
3523     OCMethod method = OC_REST_PRESENCE;
3524     resPtr = findResource((OCResource *) presenceResource.handle);
3525     if(NULL == resPtr)
3526     {
3527         return OC_STACK_NO_RESOURCE;
3528     }
3529
3530     // maxAge is 0. ResourceType is NULL.
3531     result = SendAllObserverNotification(method, resPtr, 0, OC_PRESENCE_TRIGGER_DELETE,
3532             NULL, OC_LOW_QOS);
3533
3534     return result;
3535 }
3536
3537 #endif // WITH_PRESENCE
3538 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos)
3539 {
3540     OCResource *resPtr = NULL;
3541     OCStackResult result = OC_STACK_ERROR;
3542     OCMethod method = OC_REST_NOMETHOD;
3543     uint32_t maxAge = 0;
3544
3545     OC_LOG(INFO, TAG, "Notifying all observers");
3546 #ifdef WITH_PRESENCE
3547     if(handle == presenceResource.handle)
3548     {
3549         return OC_STACK_OK;
3550     }
3551 #endif // WITH_PRESENCE
3552     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3553
3554     // Verify that the resource exists
3555     resPtr = findResource ((OCResource *) handle);
3556     if (NULL == resPtr)
3557     {
3558         return OC_STACK_NO_RESOURCE;
3559     }
3560     else
3561     {
3562         //only increment in the case of regular observing (not presence)
3563         incrementSequenceNumber(resPtr);
3564         method = OC_REST_OBSERVE;
3565         maxAge = MAX_OBSERVE_AGE;
3566 #ifdef WITH_PRESENCE
3567         result = SendAllObserverNotification (method, resPtr, maxAge,
3568                 OC_PRESENCE_TRIGGER_DELETE, NULL, qos);
3569 #else
3570         result = SendAllObserverNotification (method, resPtr, maxAge, qos);
3571 #endif
3572         return result;
3573     }
3574 }
3575
3576 OCStackResult
3577 OCNotifyListOfObservers (OCResourceHandle handle,
3578                          OCObservationId  *obsIdList,
3579                          uint8_t          numberOfIds,
3580                          const OCRepPayload       *payload,
3581                          OCQualityOfService qos)
3582 {
3583     OC_LOG(INFO, TAG, "Entering OCNotifyListOfObservers");
3584
3585     OCResource *resPtr = NULL;
3586     //TODO: we should allow the server to define this
3587     uint32_t maxAge = MAX_OBSERVE_AGE;
3588
3589     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3590     VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
3591     VERIFY_NON_NULL(payload, ERROR, OC_STACK_ERROR);
3592
3593     resPtr = findResource ((OCResource *) handle);
3594     if (NULL == resPtr || myStackMode == OC_CLIENT)
3595     {
3596         return OC_STACK_NO_RESOURCE;
3597     }
3598     else
3599     {
3600         incrementSequenceNumber(resPtr);
3601     }
3602     return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
3603             payload, maxAge, qos));
3604 }
3605
3606 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
3607 {
3608     OCStackResult result = OC_STACK_ERROR;
3609     OCServerRequest *serverRequest = NULL;
3610
3611     OC_LOG(INFO, TAG, "Entering OCDoResponse");
3612
3613     // Validate input parameters
3614     VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
3615     VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
3616
3617     // Normal response
3618     // Get pointer to request info
3619     serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
3620     if(serverRequest)
3621     {
3622         // response handler in ocserverrequest.c. Usually HandleSingleResponse.
3623         result = serverRequest->ehResponseHandler(ehResponse);
3624     }
3625
3626     return result;
3627 }
3628
3629 //-----------------------------------------------------------------------------
3630 // Private internal function definitions
3631 //-----------------------------------------------------------------------------
3632 static OCDoHandle GenerateInvocationHandle()
3633 {
3634     OCDoHandle handle = NULL;
3635     // Generate token here, it will be deleted when the transaction is deleted
3636     handle = (OCDoHandle) OICMalloc(sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3637     if (handle)
3638     {
3639         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3640     }
3641
3642     return handle;
3643 }
3644
3645 #ifdef WITH_PRESENCE
3646 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
3647         OCResourceProperty resourceProperties, uint8_t enable)
3648 {
3649     if (!inputProperty)
3650     {
3651         return OC_STACK_INVALID_PARAM;
3652     }
3653     if (resourceProperties
3654             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW))
3655     {
3656         OC_LOG(ERROR, TAG, "Invalid property");
3657         return OC_STACK_INVALID_PARAM;
3658     }
3659     if(!enable)
3660     {
3661         *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
3662     }
3663     else
3664     {
3665         *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
3666     }
3667     return OC_STACK_OK;
3668 }
3669 #endif
3670
3671 OCStackResult initResources()
3672 {
3673     OCStackResult result = OC_STACK_OK;
3674
3675     headResource = NULL;
3676     tailResource = NULL;
3677     // Init Virtual Resources
3678 #ifdef WITH_PRESENCE
3679     presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
3680
3681     result = OCCreateResource(&presenceResource.handle,
3682             OC_RSRVD_RESOURCE_TYPE_PRESENCE,
3683             "core.r",
3684             OC_RSRVD_PRESENCE_URI,
3685             NULL,
3686             NULL,
3687             OC_OBSERVABLE);
3688     //make resource inactive
3689     result = OCChangeResourceProperty(
3690             &(((OCResource *) presenceResource.handle)->resourceProperties),
3691             OC_ACTIVE, 0);
3692 #endif
3693
3694     if (result == OC_STACK_OK)
3695     {
3696         result = SRMInitSecureResources();
3697     }
3698
3699     return result;
3700 }
3701
3702 void insertResource(OCResource *resource)
3703 {
3704     if (!headResource)
3705     {
3706         headResource = resource;
3707         tailResource = resource;
3708     }
3709     else
3710     {
3711         tailResource->next = resource;
3712         tailResource = resource;
3713     }
3714     resource->next = NULL;
3715 }
3716
3717 OCResource *findResource(OCResource *resource)
3718 {
3719     OCResource *pointer = headResource;
3720
3721     while (pointer)
3722     {
3723         if (pointer == resource)
3724         {
3725             return resource;
3726         }
3727         pointer = pointer->next;
3728     }
3729     return NULL;
3730 }
3731
3732 void deleteAllResources()
3733 {
3734     OCResource *pointer = headResource;
3735     OCResource *temp = NULL;
3736
3737     while (pointer)
3738     {
3739         temp = pointer->next;
3740 #ifdef WITH_PRESENCE
3741         if (pointer != (OCResource *) presenceResource.handle)
3742         {
3743 #endif // WITH_PRESENCE
3744             deleteResource(pointer);
3745 #ifdef WITH_PRESENCE
3746         }
3747 #endif // WITH_PRESENCE
3748         pointer = temp;
3749     }
3750
3751     SRMDeInitSecureResources();
3752
3753 #ifdef WITH_PRESENCE
3754     // Ensure that the last resource to be deleted is the presence resource. This allows for all
3755     // presence notification attributed to their deletion to be processed.
3756     deleteResource((OCResource *) presenceResource.handle);
3757 #endif // WITH_PRESENCE
3758 }
3759
3760 OCStackResult deleteResource(OCResource *resource)
3761 {
3762     OCResource *prev = NULL;
3763     OCResource *temp = NULL;
3764     if(!resource)
3765     {
3766         OC_LOG(DEBUG,TAG,"resource is NULL");
3767         return OC_STACK_INVALID_PARAM;
3768     }
3769
3770     OC_LOG_V (INFO, TAG, "Deleting resource %s", resource->uri);
3771
3772     temp = headResource;
3773     while (temp)
3774     {
3775         if (temp == resource)
3776         {
3777             // Invalidate all Resource Properties.
3778             resource->resourceProperties = (OCResourceProperty) 0;
3779 #ifdef WITH_PRESENCE
3780             if(resource != (OCResource *) presenceResource.handle)
3781             {
3782 #endif // WITH_PRESENCE
3783                 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
3784 #ifdef WITH_PRESENCE
3785             }
3786
3787             if(presenceResource.handle)
3788             {
3789                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3790                 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_DELETE);
3791             }
3792 #endif
3793             // Only resource in list.
3794             if (temp == headResource && temp == tailResource)
3795             {
3796                 headResource = NULL;
3797                 tailResource = NULL;
3798             }
3799             // Deleting head.
3800             else if (temp == headResource)
3801             {
3802                 headResource = temp->next;
3803             }
3804             // Deleting tail.
3805             else if (temp == tailResource)
3806             {
3807                 tailResource = prev;
3808                 tailResource->next = NULL;
3809             }
3810             else
3811             {
3812                 prev->next = temp->next;
3813             }
3814
3815             deleteResourceElements(temp);
3816             OICFree(temp);
3817             return OC_STACK_OK;
3818         }
3819         else
3820         {
3821             prev = temp;
3822             temp = temp->next;
3823         }
3824     }
3825
3826     return OC_STACK_ERROR;
3827 }
3828
3829 void deleteResourceElements(OCResource *resource)
3830 {
3831     if (!resource)
3832     {
3833         return;
3834     }
3835
3836     OICFree(resource->uri);
3837     deleteResourceType(resource->rsrcType);
3838     deleteResourceInterface(resource->rsrcInterface);
3839 }
3840
3841 void deleteResourceType(OCResourceType *resourceType)
3842 {
3843     OCResourceType *pointer = resourceType;
3844     OCResourceType *next = NULL;
3845
3846     while (pointer)
3847     {
3848         next = pointer->next;
3849         OICFree(pointer->resourcetypename);
3850         OICFree(pointer);
3851         pointer = next;
3852     }
3853 }
3854
3855 void deleteResourceInterface(OCResourceInterface *resourceInterface)
3856 {
3857     OCResourceInterface *pointer = resourceInterface;
3858     OCResourceInterface *next = NULL;
3859
3860     while (pointer)
3861     {
3862         next = pointer->next;
3863         OICFree(pointer->name);
3864         OICFree(pointer);
3865         pointer = next;
3866     }
3867 }
3868
3869 void insertResourceType(OCResource *resource, OCResourceType *resourceType)
3870 {
3871     OCResourceType *pointer = NULL;
3872     OCResourceType *previous = NULL;
3873     if (!resource || !resourceType)
3874     {
3875         return;
3876     }
3877     // resource type list is empty.
3878     else if (!resource->rsrcType)
3879     {
3880         resource->rsrcType = resourceType;
3881     }
3882     else
3883     {
3884         pointer = resource->rsrcType;
3885
3886         while (pointer)
3887         {
3888             if (!strcmp(resourceType->resourcetypename, pointer->resourcetypename))
3889             {
3890                 OC_LOG_V(INFO, TAG, "Type %s already exists", resourceType->resourcetypename);
3891                 OICFree(resourceType->resourcetypename);
3892                 OICFree(resourceType);
3893                 return;
3894             }
3895             previous = pointer;
3896             pointer = pointer->next;
3897         }
3898         previous->next = resourceType;
3899     }
3900     resourceType->next = NULL;
3901
3902     OC_LOG_V(INFO, TAG, "Added type %s to %s", resourceType->resourcetypename, resource->uri);
3903 }
3904
3905 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index)
3906 {
3907     OCResource *resource = NULL;
3908     OCResourceType *pointer = NULL;
3909
3910     // Find the specified resource
3911     resource = findResource((OCResource *) handle);
3912     if (!resource)
3913     {
3914         return NULL;
3915     }
3916
3917     // Make sure a resource has a resourcetype
3918     if (!resource->rsrcType)
3919     {
3920         return NULL;
3921     }
3922
3923     // Iterate through the list
3924     pointer = resource->rsrcType;
3925     for(uint8_t i = 0; i< index && pointer; ++i)
3926     {
3927         pointer = pointer->next;
3928     }
3929     return pointer;
3930 }
3931
3932 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
3933 {
3934     if(resourceTypeList && resourceTypeName)
3935     {
3936         OCResourceType * rtPointer = resourceTypeList;
3937         while(resourceTypeName && rtPointer)
3938         {
3939             if(rtPointer->resourcetypename &&
3940                     strcmp(resourceTypeName, (const char *)
3941                     (rtPointer->resourcetypename)) == 0)
3942             {
3943                 break;
3944             }
3945             rtPointer = rtPointer->next;
3946         }
3947         return rtPointer;
3948     }
3949     return NULL;
3950 }
3951
3952 /*
3953  * Insert a new interface into interface linked list only if not already present.
3954  * If alredy present, 2nd arg is free'd.
3955  * Default interface will always be first if present.
3956  */
3957 void insertResourceInterface(OCResource *resource, OCResourceInterface *newInterface)
3958 {
3959     OCResourceInterface *pointer = NULL;
3960     OCResourceInterface *previous = NULL;
3961
3962     newInterface->next = NULL;
3963
3964     OCResourceInterface **firstInterface = &(resource->rsrcInterface);
3965
3966     if (!*firstInterface)
3967     {
3968         *firstInterface = newInterface;
3969     }
3970     else if (strcmp(newInterface->name, OC_RSRVD_INTERFACE_DEFAULT) == 0)
3971     {
3972         if (strcmp((*firstInterface)->name, OC_RSRVD_INTERFACE_DEFAULT) == 0)
3973         {
3974             OICFree(newInterface->name);
3975             OICFree(newInterface);
3976             return;
3977         }
3978         else
3979         {
3980             newInterface->next = *firstInterface;
3981             *firstInterface = newInterface;
3982         }
3983     }
3984     else
3985     {
3986         pointer = *firstInterface;
3987         while (pointer)
3988         {
3989             if (strcmp(newInterface->name, pointer->name) == 0)
3990             {
3991                 OICFree(newInterface->name);
3992                 OICFree(newInterface);
3993                 return;
3994             }
3995             previous = pointer;
3996             pointer = pointer->next;
3997         }
3998         previous->next = newInterface;
3999     }
4000 }
4001
4002 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
4003         uint8_t index)
4004 {
4005     OCResource *resource = NULL;
4006     OCResourceInterface *pointer = NULL;
4007
4008     // Find the specified resource
4009     resource = findResource((OCResource *) handle);
4010     if (!resource)
4011     {
4012         return NULL;
4013     }
4014
4015     // Make sure a resource has a resourceinterface
4016     if (!resource->rsrcInterface)
4017     {
4018         return NULL;
4019     }
4020
4021     // Iterate through the list
4022     pointer = resource->rsrcInterface;
4023
4024     for (uint8_t i = 0; i < index && pointer; ++i)
4025     {
4026         pointer = pointer->next;
4027     }
4028     return pointer;
4029 }
4030
4031 /*
4032  * This function splits the uri using the '?' delimiter.
4033  * "uriWithoutQuery" is the block of characters between the beginning
4034  * till the delimiter or '\0' which ever comes first.
4035  * "query" is whatever is to the right of the delimiter if present.
4036  * No delimiter sets the query to NULL.
4037  * If either are present, they will be malloc'ed into the params 2, 3.
4038  * The first param, *uri is left untouched.
4039
4040  * NOTE: This function does not account for whitespace at the end of the uri NOR
4041  *       malformed uri's with '??'. Whitespace at the end will be assumed to be
4042  *       part of the query.
4043  */
4044 OCStackResult getQueryFromUri(const char * uri, char** query, char ** uriWithoutQuery)
4045 {
4046     if(!uri)
4047     {
4048         return OC_STACK_INVALID_URI;
4049     }
4050     if(!query || !uriWithoutQuery)
4051     {
4052         return OC_STACK_INVALID_PARAM;
4053     }
4054
4055     *query           = NULL;
4056     *uriWithoutQuery = NULL;
4057
4058     size_t uriWithoutQueryLen = 0;
4059     size_t queryLen = 0;
4060     size_t uriLen = strlen(uri);
4061
4062     char *pointerToDelimiter = strstr(uri, "?");
4063
4064     uriWithoutQueryLen = pointerToDelimiter == NULL ? uriLen : (size_t)(pointerToDelimiter - uri);
4065     queryLen = pointerToDelimiter == NULL ? 0 : uriLen - uriWithoutQueryLen - 1;
4066
4067     if (uriWithoutQueryLen)
4068     {
4069         *uriWithoutQuery =  (char *) OICCalloc(uriWithoutQueryLen + 1, 1);
4070         if (!*uriWithoutQuery)
4071         {
4072             goto exit;
4073         }
4074         OICStrcpy(*uriWithoutQuery, uriWithoutQueryLen +1, uri);
4075     }
4076     if (queryLen)
4077     {
4078         *query = (char *) OICCalloc(queryLen + 1, 1);
4079         if (!*query)
4080         {
4081             OICFree(*uriWithoutQuery);
4082             *uriWithoutQuery = NULL;
4083             goto exit;
4084         }
4085         OICStrcpy(*query, queryLen + 1, pointerToDelimiter + 1);
4086     }
4087
4088     return OC_STACK_OK;
4089
4090     exit:
4091         return OC_STACK_NO_MEMORY;
4092 }
4093
4094 const OicUuid_t* OCGetServerInstanceID(void)
4095 {
4096     static bool generated = false;
4097     static OicUuid_t sid;
4098     if (generated)
4099     {
4100         return &sid;
4101     }
4102
4103     if (GetDoxmDeviceID(&sid) != OC_STACK_OK)
4104     {
4105         OC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
4106         return NULL;
4107     }
4108     generated = true;
4109     return &sid;
4110 }
4111
4112 const char* OCGetServerInstanceIDString(void)
4113 {
4114     static bool generated = false;
4115     static char sidStr[UUID_STRING_SIZE];
4116
4117     if(generated)
4118     {
4119         return sidStr;
4120     }
4121
4122     const OicUuid_t* sid = OCGetServerInstanceID();
4123
4124     if(OCConvertUuidToString(sid->id, sidStr) != RAND_UUID_OK)
4125     {
4126         OC_LOG(FATAL, TAG, "Generate UUID String for Server Instance failed!");
4127         return NULL;
4128     }
4129
4130     generated = true;
4131     return sidStr;
4132 }
4133
4134 CAResult_t OCSelectNetwork()
4135 {
4136     CAResult_t retResult = CA_STATUS_FAILED;
4137     CAResult_t caResult = CA_STATUS_OK;
4138
4139     CATransportAdapter_t connTypes[] = {
4140             CA_ADAPTER_IP,
4141             CA_ADAPTER_RFCOMM_BTEDR,
4142             CA_ADAPTER_GATT_BTLE
4143
4144 #ifdef RA_ADAPTER
4145             ,CA_ADAPTER_REMOTE_ACCESS
4146 #endif
4147         };
4148     int numConnTypes = sizeof(connTypes)/sizeof(connTypes[0]);
4149
4150     for(int i = 0; i<numConnTypes; i++)
4151     {
4152         // Ignore CA_NOT_SUPPORTED error. The CA Layer may have not compiled in the interface.
4153         if(caResult == CA_STATUS_OK || caResult == CA_NOT_SUPPORTED)
4154         {
4155            caResult = CASelectNetwork(connTypes[i]);
4156            if(caResult == CA_STATUS_OK)
4157            {
4158                retResult = CA_STATUS_OK;
4159            }
4160         }
4161     }
4162
4163     if(retResult != CA_STATUS_OK)
4164     {
4165         return caResult; // Returns error of appropriate transport that failed fatally.
4166     }
4167
4168     return retResult;
4169 }
4170
4171 OCStackResult CAResultToOCResult(CAResult_t caResult)
4172 {
4173     switch (caResult)
4174     {
4175         case CA_STATUS_OK:
4176             return OC_STACK_OK;
4177         case CA_STATUS_INVALID_PARAM:
4178             return OC_STACK_INVALID_PARAM;
4179         case CA_ADAPTER_NOT_ENABLED:
4180             return OC_STACK_ADAPTER_NOT_ENABLED;
4181         case CA_SERVER_STARTED_ALREADY:
4182             return OC_STACK_OK;
4183         case CA_SERVER_NOT_STARTED:
4184             return OC_STACK_ERROR;
4185         case CA_DESTINATION_NOT_REACHABLE:
4186             return OC_STACK_COMM_ERROR;
4187         case CA_SOCKET_OPERATION_FAILED:
4188             return OC_STACK_COMM_ERROR;
4189         case CA_SEND_FAILED:
4190             return OC_STACK_COMM_ERROR;
4191         case CA_RECEIVE_FAILED:
4192             return OC_STACK_COMM_ERROR;
4193         case CA_MEMORY_ALLOC_FAILED:
4194             return OC_STACK_NO_MEMORY;
4195         case CA_REQUEST_TIMEOUT:
4196             return OC_STACK_TIMEOUT;
4197         case CA_DESTINATION_DISCONNECTED:
4198             return OC_STACK_COMM_ERROR;
4199         case CA_STATUS_FAILED:
4200             return OC_STACK_ERROR;
4201         case CA_NOT_SUPPORTED:
4202             return OC_STACK_NOTIMPL;
4203         default:
4204             return OC_STACK_ERROR;
4205     }
4206 }