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