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