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