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