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