Handling of missing parent property in collection response
[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 <stdlib.h>
41 #include <inttypes.h>
42 #include <string.h>
43 #include <ctype.h>
44
45 #include "ocstack.h"
46 #include "ocstackinternal.h"
47 #include "ocresourcehandler.h"
48 #include "occlientcb.h"
49 #include "ocobserve.h"
50 #include "ocrandom.h"
51 #include "oic_malloc.h"
52 #include "oic_string.h"
53 #include "logger.h"
54 #include "trace.h"
55 #include "ocserverrequest.h"
56 #include "secureresourcemanager.h"
57 #include "psinterface.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 "cainterface.h"
65 #include "oicgroup.h"
66 #include "ocendpoint.h"
67
68 #if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
69 #include "occonnectionmanager.h"
70 #endif
71
72 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
73 #include "routingutility.h"
74 #ifdef ROUTING_GATEWAY
75 #include "routingmanager.h"
76 #endif
77 #endif
78
79 #ifdef TCP_ADAPTER
80 #include "oickeepalive.h"
81 #endif
82
83 //#ifdef DIRECT_PAIRING
84 #include "directpairing.h"
85 //#endif
86
87 #ifdef HAVE_ARDUINO_TIME_H
88 #include "Time.h"
89 #endif
90 #ifdef HAVE_SYS_TIME_H
91 #include <sys/time.h>
92 #endif
93 #include <coap/coap.h>
94
95 #ifdef HAVE_ARPA_INET_H
96 #include <arpa/inet.h>
97 #endif
98
99 #ifndef UINT32_MAX
100 #define UINT32_MAX   (0xFFFFFFFFUL)
101 #endif
102
103 //-----------------------------------------------------------------------------
104 // Typedefs
105 //-----------------------------------------------------------------------------
106 typedef enum
107 {
108     OC_STACK_UNINITIALIZED = 0,
109     OC_STACK_INITIALIZED,
110     OC_STACK_UNINIT_IN_PROGRESS
111 } OCStackState;
112
113 #ifdef WITH_PRESENCE
114 typedef enum
115 {
116     OC_PRESENCE_UNINITIALIZED = 0,
117     OC_PRESENCE_INITIALIZED
118 } OCPresenceState;
119 #endif
120
121 //-----------------------------------------------------------------------------
122 // Private variables
123 //-----------------------------------------------------------------------------
124 static OCStackState stackState = OC_STACK_UNINITIALIZED;
125
126 OCResource *headResource = NULL;
127 static OCResource *tailResource = NULL;
128 static OCResourceHandle platformResource = {0};
129 static OCResourceHandle deviceResource = {0};
130 static OCResourceHandle introspectionResource = {0};
131 static OCResourceHandle introspectionPayloadResource = {0};
132 static OCResourceHandle wellKnownResource = {0};
133 #ifdef MQ_BROKER
134 static OCResourceHandle brokerResource = {0};
135 #endif
136
137 #ifdef WITH_PRESENCE
138 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
139 static PresenceResource presenceResource = {0};
140 static uint8_t PresenceTimeOutSize = 0;
141 static uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
142 #endif
143
144 static OCMode myStackMode;
145 #ifdef RA_ADAPTER
146 //TODO: revisit this design
147 static bool gRASetInfo = false;
148 #endif
149 OCDeviceEntityHandler defaultDeviceHandler;
150 void* defaultDeviceHandlerCallbackParameter = NULL;
151 static const char COAP_TCP_SCHEME[] = "coap+tcp:";
152 static const char COAPS_TCP_SCHEME[] = "coaps+tcp:";
153 static const char CORESPEC[] = "core";
154
155 CAAdapterStateChangedCB g_adapterHandler = NULL;
156 CAConnectionStateChangedCB g_connectionHandler = NULL;
157 // Persistent Storage callback handler for open/read/write/close/unlink
158 static OCPersistentStorage *g_PersistentStorageHandler = NULL;
159
160 //-----------------------------------------------------------------------------
161 // Macros
162 //-----------------------------------------------------------------------------
163 #define TAG  "OIC_RI_STACK"
164 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
165             {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
166 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OIC_LOG((logLevel), \
167              TAG, #arg " is NULL"); return (retVal); } }
168 #define VERIFY_NON_NULL_NR(arg, logLevel) { if (!(arg)) { OIC_LOG((logLevel), \
169              TAG, #arg " is NULL"); return; } }
170 #define VERIFY_NON_NULL_V(arg) { if (!arg) {OIC_LOG(FATAL, TAG, #arg " is NULL");\
171     goto exit;} }
172
173 //TODO: we should allow the server to define this
174 #define MAX_OBSERVE_AGE (0x2FFFFUL)
175
176 #define MILLISECONDS_PER_SECOND   (1000)
177
178 //-----------------------------------------------------------------------------
179 // Private internal function prototypes
180 //-----------------------------------------------------------------------------
181
182 /**
183  * Generate handle of OCDoResource invocation for callback management.
184  *
185  * @return Generated OCDoResource handle.
186  */
187 static OCDoHandle GenerateInvocationHandle();
188
189 /**
190  * Initialize resource data structures, variables, etc.
191  *
192  * @return ::OC_STACK_OK on success, some other value upon failure.
193  */
194 static OCStackResult initResources();
195
196 /**
197  * Add a resource to the end of the linked list of resources.
198  *
199  * @param resource Resource to be added
200  */
201 static void insertResource(OCResource *resource);
202
203 /**
204  * Find a resource in the linked list of resources.
205  *
206  * @param resource Resource to be found.
207  * @return Pointer to resource that was found in the linked list or NULL if the resource was not
208  *         found.
209  */
210 static OCResource *findResource(OCResource *resource);
211
212 /**
213  * Insert a resource type into a resource's resource type linked list.
214  * If resource type already exists, it will not be inserted and the
215  * resourceType will be free'd.
216  * resourceType->next should be null to avoid memory leaks.
217  * Function returns silently for null args.
218  *
219  * @param resource Resource where resource type is to be inserted.
220  * @param resourceType Resource type to be inserted.
221  */
222 static void insertResourceType(OCResource *resource,
223         OCResourceType *resourceType);
224
225 /**
226  * Get a resource type at the specified index within a resource.
227  *
228  * @param handle Handle of resource.
229  * @param index Index of resource type.
230  *
231  * @return Pointer to resource type if found, NULL otherwise.
232  */
233 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
234         uint8_t index);
235
236 /**
237  * Insert a resource interface into a resource's resource interface linked list.
238  * If resource interface already exists, it will not be inserted and the
239  * resourceInterface will be free'd.
240  * resourceInterface->next should be null to avoid memory leaks.
241  *
242  * @param resource Resource where resource interface is to be inserted.
243  * @param resourceInterface Resource interface to be inserted.
244  */
245 static void insertResourceInterface(OCResource *resource,
246         OCResourceInterface *resourceInterface);
247
248 /**
249  * Get a resource interface at the specified index within a resource.
250  *
251  * @param handle Handle of resource.
252  * @param index Index of resource interface.
253  *
254  * @return Pointer to resource interface if found, NULL otherwise.
255  */
256 static OCResourceInterface *findResourceInterfaceAtIndex(
257         OCResourceHandle handle, uint8_t index);
258
259 /**
260  * Delete all of the dynamically allocated elements that were created for the resource type.
261  *
262  * @param resourceType Specified resource type.
263  */
264 static void deleteResourceType(OCResourceType *resourceType);
265
266 /**
267  * Delete all of the dynamically allocated elements that were created for the resource interface.
268  *
269  * @param resourceInterface Specified resource interface.
270  */
271 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
272
273 /**
274  * Delete all of the dynamically allocated elements that were created for the resource.
275  *
276  * @param resource Specified resource.
277  */
278 static void deleteResourceElements(OCResource *resource);
279
280 /**
281  * Delete resource specified by handle.  Deletes resource and all resourcetype and resourceinterface
282  * linked lists.
283  *
284  * @param handle Handle of resource to be deleted.
285  *
286  * @return ::OC_STACK_OK on success, some other value upon failure.
287  */
288 static OCStackResult deleteResource(OCResource *resource);
289
290 /**
291  * Delete all of the resources in the resource list.
292  */
293 static void deleteAllResources();
294
295 /**
296  * Increment resource sequence number.  Handles rollover.
297  *
298  * @param resPtr Pointer to resource.
299  */
300 static void incrementSequenceNumber(OCResource * resPtr);
301
302 /*
303  * Attempts to initialize every network interface that the CA Layer might have compiled in.
304  *
305  * Note: At least one interface must succeed to initialize. If all calls to @ref CASelectNetwork
306  * return something other than @ref CA_STATUS_OK, then this function fails.
307  * @param transportType  OCTransportAdapter value to select.
308  * @return ::CA_STATUS_OK on success, some other value upon failure.
309  */
310 static CAResult_t OCSelectNetwork(OCTransportAdapter transportType);
311
312 /**
313  * Convert CAResponseResult_t to OCStackResult.
314  *
315  * @param caCode CAResponseResult_t code.
316  * @return ::OC_STACK_OK on success, some other value upon failure.
317  */
318 static OCStackResult CAResponseToOCStackResult(CAResponseResult_t caCode);
319
320 /**
321  * Convert OCTransportFlags_t to CATransportModifiers_t.
322  *
323  * @param ocConType OCTransportFlags_t input.
324  * @return CATransportFlags
325  */
326 static CATransportFlags_t OCToCATransportFlags(OCTransportFlags ocConType);
327
328 /**
329  * Convert CATransportFlags_t to OCTransportModifiers_t.
330  *
331  * @param caConType CATransportFlags_t input.
332  * @return OCTransportFlags
333  */
334 static OCTransportFlags CAToOCTransportFlags(CATransportFlags_t caConType);
335
336 /**
337  * Handle response from presence request.
338  *
339  * @param endPoint CA remote endpoint.
340  * @param responseInfo CA response info.
341  * @return ::OC_STACK_OK on success, some other value upon failure.
342  */
343 static OCStackResult HandlePresenceResponse(const CAEndpoint_t *endPoint,
344         const CAResponseInfo_t *responseInfo);
345
346 /**
347  * This function will be called back by CA layer when a response is received.
348  *
349  * @param endPoint CA remote endpoint.
350  * @param responseInfo CA response info.
351  */
352 static void HandleCAResponses(const CAEndpoint_t* endPoint,
353         const CAResponseInfo_t* responseInfo);
354
355 /**
356  * This function will be called back by CA layer when a request is received.
357  *
358  * @param endPoint CA remote endpoint.
359  * @param requestInfo CA request info.
360  */
361 static void HandleCARequests(const CAEndpoint_t* endPoint,
362         const CARequestInfo_t* requestInfo);
363
364 /**
365  * Extract query from a URI.
366  *
367  * @param uri Full URI with query.
368  * @param query Pointer to string that will contain query.
369  * @param newURI Pointer to string that will contain URI.
370  * @return ::OC_STACK_OK on success, some other value upon failure.
371  */
372 static OCStackResult getQueryFromUri(const char * uri, char** resourceType, char ** newURI);
373
374 /**
375  * Finds a resource type in an OCResourceType link-list.
376  *
377  * @param resourceTypeList The link-list to be searched through.
378  * @param resourceTypeName The key to search for.
379  *
380  * @return Resource type that matches the key (ie. resourceTypeName) or
381  *      NULL if there is either an invalid parameter or this function was unable to find the key.
382  */
383 static OCResourceType *findResourceType(OCResourceType * resourceTypeList,
384         const char * resourceTypeName);
385
386 /**
387  * Reset presence TTL for a ClientCB struct. ttlLevel will be set to 0.
388  * TTL will be set to maxAge.
389  *
390  * @param cbNode Callback Node for which presence ttl is to be reset.
391  * @param maxAge New value of ttl in seconds.
392
393  * @return ::OC_STACK_OK on success, some other value upon failure.
394  */
395 static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds);
396
397 /**
398  * Ensure the accept header option is set appropriatly before sending the requests and routing
399  * header option is updated with destination.
400  *
401  * @param object CA remote endpoint.
402  * @param requestInfo CA request info.
403  *
404  * @return ::OC_STACK_OK on success, some other value upon failure.
405  */
406 static OCStackResult OCSendRequest(const CAEndpoint_t *object, CARequestInfo_t *requestInfo);
407
408 /**
409  * default adapter state change callback method
410  *
411  * @param adapter   CA network adapter type.
412  * @param enabled   current adapter state.
413  */
414 static void OCDefaultAdapterStateChangedHandler(CATransportAdapter_t adapter, bool enabled);
415
416 /**
417  * default connection state change callback method
418  *
419  * @param info          CAEndpoint which has address, port and etc.
420  * @param isConnected   current connection state.
421  */
422 static void OCDefaultConnectionStateChangedHandler(const CAEndpoint_t *info, bool isConnected);
423
424 /**
425  * Register network monitoring callback.
426  * Network status changes are delivered these callback.
427  * @param adapterHandler        Adapter state monitoring callback.
428  * @param connectionHandler     Connection state monitoring callback.
429  */
430 static void OCSetNetworkMonitorHandler(CAAdapterStateChangedCB adapterHandler,
431                                        CAConnectionStateChangedCB connectionHandler);
432
433 //-----------------------------------------------------------------------------
434 // Internal functions
435 //-----------------------------------------------------------------------------
436
437 bool checkProxyUri(OCHeaderOption *options, uint8_t numOptions)
438 {
439     if (!options || 0 == numOptions)
440     {
441         OIC_LOG (INFO, TAG, "No options present");
442         return false;
443     }
444
445     for (uint8_t i = 0; i < numOptions; i++)
446     {
447         if (options[i].protocolID == OC_COAP_ID && options[i].optionID == OC_RSRVD_PROXY_OPTION_ID)
448         {
449             OIC_LOG(DEBUG, TAG, "Proxy URI is present");
450             return true;
451         }
452     }
453     return false;
454 }
455
456 uint32_t GetTicks(uint32_t milliSeconds)
457 {
458     coap_tick_t now;
459     coap_ticks(&now);
460
461     // Guard against overflow of uint32_t
462     if (milliSeconds <= ((UINT32_MAX - (uint32_t)now) * MILLISECONDS_PER_SECOND) /
463                              COAP_TICKS_PER_SECOND)
464     {
465         return now + (milliSeconds * COAP_TICKS_PER_SECOND)/MILLISECONDS_PER_SECOND;
466     }
467     else
468     {
469         return UINT32_MAX;
470     }
471 }
472
473 void CopyEndpointToDevAddr(const CAEndpoint_t *in, OCDevAddr *out)
474 {
475     VERIFY_NON_NULL_NR(in, FATAL);
476     VERIFY_NON_NULL_NR(out, FATAL);
477
478     out->adapter = (OCTransportAdapter)in->adapter;
479     out->flags = CAToOCTransportFlags(in->flags);
480     OICStrcpy(out->addr, sizeof(out->addr), in->addr);
481     out->port = in->port;
482     out->ifindex = in->ifindex;
483 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
484     /* This assert is to prevent accidental mismatch between address size macros defined in
485      * RI and CA and cause crash here. */
486     OC_STATIC_ASSERT(MAX_ADDR_STR_SIZE_CA == MAX_ADDR_STR_SIZE,
487                                         "Address size mismatch between RI and CA");
488     memcpy(out->routeData, in->routeData, sizeof(in->routeData));
489 #endif
490 }
491
492 void CopyDevAddrToEndpoint(const OCDevAddr *in, CAEndpoint_t *out)
493 {
494     VERIFY_NON_NULL_NR(in, FATAL);
495     VERIFY_NON_NULL_NR(out, FATAL);
496
497     out->adapter = (CATransportAdapter_t)in->adapter;
498     out->flags = OCToCATransportFlags(in->flags);
499     OICStrcpy(out->addr, sizeof(out->addr), in->addr);
500     OICStrcpy(out->remoteId, sizeof(out->remoteId), in->remoteId);
501 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
502     /* This assert is to prevent accidental mismatch between address size macros defined in
503      * RI and CA and cause crash here. */
504     OC_STATIC_ASSERT(MAX_ADDR_STR_SIZE_CA == MAX_ADDR_STR_SIZE,
505                                         "Address size mismatch between RI and CA");
506     memcpy(out->routeData, in->routeData, sizeof(in->routeData));
507 #endif
508     out->port = in->port;
509     out->ifindex = in->ifindex;
510 }
511
512 void FixUpClientResponse(OCClientResponse *cr)
513 {
514     VERIFY_NON_NULL_NR(cr, FATAL);
515
516     cr->addr = &cr->devAddr;
517     cr->connType = (OCConnectivityType)
518         ((cr->devAddr.adapter << CT_ADAPTER_SHIFT) | (cr->devAddr.flags & CT_MASK_FLAGS));
519 }
520
521 static OCStackResult OCSendRequest(const CAEndpoint_t *object, CARequestInfo_t *requestInfo)
522 {
523     VERIFY_NON_NULL(object, FATAL, OC_STACK_INVALID_PARAM);
524     VERIFY_NON_NULL(requestInfo, FATAL, OC_STACK_INVALID_PARAM);
525
526 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
527     OCStackResult rmResult = RMAddInfo(object->routeData, requestInfo, true, NULL);
528     if (OC_STACK_OK != rmResult)
529     {
530         OIC_LOG(ERROR, TAG, "Add destination option failed");
531         return rmResult;
532     }
533 #endif
534
535     uint16_t acceptVersion = OC_SPEC_VERSION_VALUE;
536     // From OCF onwards, check settings of version option.
537     if (DEFAULT_ACCEPT_VERSION_VALUE <= acceptVersion)
538     {
539         if (requestInfo->info.numOptions > 0 && requestInfo->info.options)
540         {
541             for (uint8_t i = 0; i < requestInfo->info.numOptions; i++)
542             {
543                 if (COAP_OPTION_ACCEPT_VERSION == requestInfo->info.options[i].protocolID)
544                 {
545                     acceptVersion = requestInfo->info.options[i].optionData[0];
546                     break;
547                 }
548                 else if (COAP_OPTION_CONTENT_VERSION == requestInfo->info.options[i].protocolID)
549                 {
550                     acceptVersion = requestInfo->info.options[i].optionData[0];
551                     break;
552                 }
553             }
554         }
555     }
556
557     if (DEFAULT_CONTENT_VERSION_VALUE <= acceptVersion)
558     {
559         requestInfo->info.acceptFormat = CA_FORMAT_APPLICATION_VND_OCF_CBOR;
560         requestInfo->info.acceptVersion = acceptVersion;
561     }
562     else
563     {
564       requestInfo->info.acceptFormat = CA_FORMAT_APPLICATION_CBOR;
565     }
566
567     CAResult_t result = CASendRequest(object, requestInfo);
568     if(CA_STATUS_OK != result)
569     {
570         OIC_LOG_V(ERROR, TAG, "CASendRequest failed with CA error %u", result);
571         return CAResultToOCResult(result);
572     }
573     return OC_STACK_OK;
574 }
575 //-----------------------------------------------------------------------------
576 // Internal API function
577 //-----------------------------------------------------------------------------
578
579 // This internal function is called to update the stack with the status of
580 // observers and communication failures
581 OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t status)
582 {
583     OCStackResult result = OC_STACK_ERROR;
584     ResourceObserver * observer = NULL;
585     OCEntityHandlerRequest ehRequest = {0};
586
587     switch(status)
588     {
589     case OC_OBSERVER_NOT_INTERESTED:
590         OIC_LOG(DEBUG, TAG, "observer not interested in our notifications");
591         observer = GetObserverUsingToken(token, tokenLength);
592         if (observer)
593         {
594             result = FormOCEntityHandlerRequest(&ehRequest,
595                                                 (OCRequestHandle)NULL,
596                                                 OC_REST_NOMETHOD,
597                                                 &observer->devAddr,
598                                                 (OCResourceHandle)NULL,
599                                                 NULL, PAYLOAD_TYPE_REPRESENTATION,
600                                                 NULL, 0, 0, NULL,
601                                                 OC_OBSERVE_DEREGISTER,
602                                                 observer->observeId,
603                                                 0);
604             if (result != OC_STACK_OK)
605             {
606                 return result;
607             }
608
609             if (observer->resource && observer->resource->entityHandler)
610             {
611                 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest,
612                                                   observer->resource->entityHandlerCallbackParam);
613             }
614         }
615
616         result = DeleteObserverUsingToken(token, tokenLength);
617         if (result == OC_STACK_OK)
618         {
619             OIC_LOG(DEBUG, TAG, "Removed observer successfully");
620         }
621         else
622         {
623             result = OC_STACK_OK;
624             OIC_LOG(DEBUG, TAG, "Observer Removal failed");
625         }
626         break;
627
628     case OC_OBSERVER_STILL_INTERESTED:
629         OIC_LOG(DEBUG, TAG, "observer still interested, reset the failedCount");
630         observer = GetObserverUsingToken(token, tokenLength);
631         if (observer)
632         {
633             observer->forceHighQos = 0;
634             observer->failedCommCount = 0;
635             result = OC_STACK_OK;
636         }
637         else
638         {
639             result = OC_STACK_OBSERVER_NOT_FOUND;
640         }
641         break;
642
643     case OC_OBSERVER_FAILED_COMM:
644         OIC_LOG(DEBUG, TAG, "observer is unreachable");
645         observer = GetObserverUsingToken (token, tokenLength);
646         if (observer)
647         {
648             if (observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
649             {
650                 result = FormOCEntityHandlerRequest(&ehRequest,
651                                                     (OCRequestHandle)NULL,
652                                                     OC_REST_NOMETHOD,
653                                                     &observer->devAddr,
654                                                     (OCResourceHandle)NULL,
655                                                     NULL, PAYLOAD_TYPE_REPRESENTATION,
656                                                     NULL, 0, 0, NULL,
657                                                     OC_OBSERVE_DEREGISTER,
658                                                     observer->observeId,
659                                                     0);
660                 if (result != OC_STACK_OK)
661                 {
662                     return OC_STACK_ERROR;
663                 }
664
665                 if (observer->resource && observer->resource->entityHandler)
666                 {
667                     observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest,
668                                         observer->resource->entityHandlerCallbackParam);
669                 }
670
671                 result = DeleteObserverUsingToken(token, tokenLength);
672                 if (result == OC_STACK_OK)
673                 {
674                     OIC_LOG(DEBUG, TAG, "Removed observer successfully");
675                 }
676                 else
677                 {
678                     result = OC_STACK_OK;
679                     OIC_LOG(DEBUG, TAG, "Observer Removal failed");
680                 }
681             }
682             else
683             {
684                 observer->failedCommCount++;
685                 observer->forceHighQos = 1;
686                 OIC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",
687                           observer->failedCommCount);
688                 result = OC_STACK_CONTINUE;
689             }
690         }
691         break;
692     default:
693         OIC_LOG(ERROR, TAG, "Unknown status");
694         result = OC_STACK_ERROR;
695         break;
696         }
697     return result;
698 }
699
700 OCStackResult CAResponseToOCStackResult(CAResponseResult_t caCode)
701 {
702     OCStackResult ret = OC_STACK_ERROR;
703     switch(caCode)
704     {
705         case CA_CREATED:
706             ret = OC_STACK_RESOURCE_CREATED;
707             break;
708         case CA_DELETED:
709             ret = OC_STACK_RESOURCE_DELETED;
710             break;
711         case CA_CHANGED:
712             ret = OC_STACK_RESOURCE_CHANGED;
713             break;
714         case CA_CONTENT:
715         case CA_VALID:
716             ret = OC_STACK_OK;
717             break;
718         case CA_BAD_REQ:
719             ret = OC_STACK_INVALID_QUERY;
720             break;
721         case CA_UNAUTHORIZED_REQ:
722             ret = OC_STACK_UNAUTHORIZED_REQ;
723             break;
724         case CA_BAD_OPT:
725             ret = OC_STACK_INVALID_OPTION;
726             break;
727         case CA_NOT_FOUND:
728             ret = OC_STACK_NO_RESOURCE;
729             break;
730         case CA_RETRANSMIT_TIMEOUT:
731             ret = OC_STACK_COMM_ERROR;
732             break;
733         case CA_REQUEST_ENTITY_TOO_LARGE:
734             ret = OC_STACK_TOO_LARGE_REQ;
735             break;
736         case CA_NOT_ACCEPTABLE:
737             ret = OC_STACK_NOT_ACCEPTABLE;
738             break;
739         case CA_FORBIDDEN_REQ:
740             ret = OC_STACK_FORBIDDEN_REQ;
741             break;
742         case CA_INTERNAL_SERVER_ERROR:
743             ret = OC_STACK_INTERNAL_SERVER_ERROR;
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_NOT_ACCEPTABLE:
801             ret = CA_NOT_ACCEPTABLE;
802             break;
803         case OC_STACK_UNAUTHORIZED_REQ:
804             ret = CA_UNAUTHORIZED_REQ;
805             break;
806         case OC_STACK_FORBIDDEN_REQ:
807             ret = CA_FORBIDDEN_REQ;
808             break;
809         case OC_STACK_INTERNAL_SERVER_ERROR:
810             ret = CA_INTERNAL_SERVER_ERROR;
811             break;
812         case OC_STACK_BAD_ENDPOINT:
813             ret = CA_BAD_REQ;
814         default:
815             break;
816     }
817     return ret;
818 }
819
820 CATransportFlags_t OCToCATransportFlags(OCTransportFlags ocFlags)
821 {
822     CATransportFlags_t caFlags = (CATransportFlags_t)ocFlags;
823
824     // supply default behavior.
825     if ((caFlags & (CA_IPV6|CA_IPV4)) == 0)
826     {
827         caFlags = (CATransportFlags_t)(caFlags|CA_IPV6|CA_IPV4);
828     }
829     if ((caFlags & OC_MASK_SCOPE) == 0)
830     {
831         caFlags = (CATransportFlags_t)(caFlags|OC_SCOPE_LINK);
832     }
833     return caFlags;
834 }
835
836 OCTransportFlags CAToOCTransportFlags(CATransportFlags_t caFlags)
837 {
838     return (OCTransportFlags)caFlags;
839 }
840
841 static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds)
842 {
843     uint32_t lowerBound  = 0;
844     uint32_t higherBound = 0;
845
846     if (!cbNode || !cbNode->presence || !cbNode->presence->timeOut)
847     {
848         return OC_STACK_INVALID_PARAM;
849     }
850
851     OIC_LOG_V(INFO, TAG, "Update presence TTL, time is %u", GetTicks(0));
852
853     cbNode->presence->TTL = maxAgeSeconds;
854
855     for (int index = 0; index < PresenceTimeOutSize; index++)
856     {
857         // Guard against overflow
858         if (cbNode->presence->TTL < (UINT32_MAX/(MILLISECONDS_PER_SECOND*PresenceTimeOut[index]))
859                                      * 100)
860         {
861             lowerBound = GetTicks((PresenceTimeOut[index] *
862                                   cbNode->presence->TTL *
863                                   MILLISECONDS_PER_SECOND)/100);
864         }
865         else
866         {
867             lowerBound = GetTicks(UINT32_MAX);
868         }
869
870         if (cbNode->presence->TTL < (UINT32_MAX/(MILLISECONDS_PER_SECOND*PresenceTimeOut[index+1]))
871                                      * 100)
872         {
873             higherBound = GetTicks((PresenceTimeOut[index + 1] *
874                                    cbNode->presence->TTL *
875                                    MILLISECONDS_PER_SECOND)/100);
876         }
877         else
878         {
879             higherBound = GetTicks(UINT32_MAX);
880         }
881
882         cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
883
884         OIC_LOG_V(DEBUG, TAG, "lowerBound timeout  %d", lowerBound);
885         OIC_LOG_V(DEBUG, TAG, "higherBound timeout %d", higherBound);
886         OIC_LOG_V(DEBUG, TAG, "timeOut entry  %d", cbNode->presence->timeOut[index]);
887     }
888
889     cbNode->presence->TTLlevel = 0;
890
891     OIC_LOG_V(DEBUG, TAG, "this TTL level %d", cbNode->presence->TTLlevel);
892     return OC_STACK_OK;
893 }
894
895 const char *convertTriggerEnumToString(OCPresenceTrigger trigger)
896 {
897     if (trigger == OC_PRESENCE_TRIGGER_CREATE)
898     {
899         return OC_RSRVD_TRIGGER_CREATE;
900     }
901     else if (trigger == OC_PRESENCE_TRIGGER_CHANGE)
902     {
903         return OC_RSRVD_TRIGGER_CHANGE;
904     }
905     else
906     {
907         return OC_RSRVD_TRIGGER_DELETE;
908     }
909 }
910
911 OCPresenceTrigger convertTriggerStringToEnum(const char * triggerStr)
912 {
913     if(!triggerStr)
914     {
915         return OC_PRESENCE_TRIGGER_CREATE;
916     }
917     else if(strcmp(triggerStr, OC_RSRVD_TRIGGER_CREATE) == 0)
918     {
919         return OC_PRESENCE_TRIGGER_CREATE;
920     }
921     else if(strcmp(triggerStr, OC_RSRVD_TRIGGER_CHANGE) == 0)
922     {
923         return OC_PRESENCE_TRIGGER_CHANGE;
924     }
925     else
926     {
927         return OC_PRESENCE_TRIGGER_DELETE;
928     }
929 }
930
931 OCStackResult OCEncodeAddressForRFC6874(char *outputAddress,
932                                         size_t outputSize,
933                                         const char *inputAddress)
934 {
935     VERIFY_NON_NULL(inputAddress,  FATAL, OC_STACK_INVALID_PARAM);
936     VERIFY_NON_NULL(outputAddress, FATAL, OC_STACK_INVALID_PARAM);
937
938     size_t inputLength = strnlen(inputAddress, outputSize);
939
940     // inputSize includes the null terminator
941     size_t inputSize = inputLength + 1;
942
943     if (inputSize > outputSize)
944     {
945         OIC_LOG_V(ERROR, TAG,
946                   "OCEncodeAddressForRFC6874 failed: "
947                   "outputSize (%zu) < inputSize (%zu)",
948                   outputSize, inputSize);
949
950         return OC_STACK_ERROR;
951     }
952
953     char* percentChar = strchr(inputAddress, '%');
954
955     // If there is no '%' character, then no change is required to the string.
956     if (NULL == percentChar)
957     {
958         OICStrcpy(outputAddress, outputSize, inputAddress);
959         return OC_STACK_OK;
960     }
961
962     const char* addressPart = &inputAddress[0];
963     const char* scopeIdPart = percentChar + 1;
964
965     // Sanity check to make sure this string doesn't have more '%' characters
966     if (NULL != strchr(scopeIdPart, '%'))
967     {
968         return OC_STACK_ERROR;
969     }
970
971     // If no string follows the first '%', then the input was invalid.
972     if (scopeIdPart[0] == '\0')
973     {
974         OIC_LOG(ERROR, TAG, "OCEncodeAddressForRFC6874 failed: Invalid input string: no scope ID!");
975         return OC_STACK_ERROR;
976     }
977
978     // Check to see if the string is already encoded
979     if ((scopeIdPart[0] == '2') && (scopeIdPart[1] == '5'))
980     {
981         OIC_LOG(ERROR, TAG, "OCEncodeAddressForRFC6874 failed: Input string is already encoded");
982         return OC_STACK_ERROR;
983     }
984
985     // Fail if we don't have room for encoded string's two additional chars
986     if (outputSize < (inputSize + 2))
987     {
988         OIC_LOG(ERROR, TAG, "OCEncodeAddressForRFC6874 failed: encoded output will not fit!");
989         return OC_STACK_ERROR;
990     }
991
992     // Restore the null terminator with an escaped '%' character, per RFC 6874
993     OICStrcpy(outputAddress, scopeIdPart - addressPart, addressPart);
994     strcat(outputAddress, "%25");
995     strcat(outputAddress, scopeIdPart);
996
997     return OC_STACK_OK;
998 }
999
1000 OCStackResult OCDecodeAddressForRFC6874(char *outputAddress,
1001                                         size_t outputSize,
1002                                         const char *inputAddress,
1003                                         const char *end)
1004 {
1005     VERIFY_NON_NULL(inputAddress,  FATAL, OC_STACK_INVALID_PARAM);
1006     VERIFY_NON_NULL(outputAddress, FATAL, OC_STACK_INVALID_PARAM);
1007
1008     if (NULL == end)
1009     {
1010         end = inputAddress + strlen(inputAddress);
1011     }
1012     size_t inputLength = end - inputAddress;
1013
1014     const char *percent = strchr(inputAddress, '%');
1015     if (!percent || (percent > end))
1016     {
1017         OICStrcpyPartial(outputAddress, outputSize, inputAddress, inputLength);
1018     }
1019     else
1020     {
1021         if (percent[1] != '2' || percent[2] != '5')
1022         {
1023             return OC_STACK_INVALID_URI;
1024         }
1025
1026         size_t addrlen = percent - inputAddress + 1;
1027         OICStrcpyPartial(outputAddress, outputSize, inputAddress, addrlen);
1028         OICStrcpyPartial(outputAddress + addrlen, outputSize - addrlen,
1029                          percent + 3, end - percent - 3);
1030     }
1031
1032     return OC_STACK_OK;
1033 }
1034
1035 /**
1036  * The cononical presence allows constructed URIs to be string compared.
1037  *
1038  * requestUri must be a char array of size CA_MAX_URI_LENGTH
1039  */
1040 static int FormCanonicalPresenceUri(const CAEndpoint_t *endpoint,
1041                                     char *presenceUri, bool isMulticast)
1042 {
1043     VERIFY_NON_NULL(endpoint   , FATAL, OC_STACK_INVALID_PARAM);
1044     VERIFY_NON_NULL(presenceUri, FATAL, OC_STACK_INVALID_PARAM);
1045
1046     if (isMulticast)
1047     {
1048         OIC_LOG(DEBUG, TAG, "Make Multicast Presence URI");
1049         return snprintf(presenceUri, CA_MAX_URI_LENGTH, "%s", OC_RSRVD_PRESENCE_URI);
1050     }
1051
1052     CAEndpoint_t *ep = (CAEndpoint_t *)endpoint;
1053     if (ep->adapter == CA_ADAPTER_IP)
1054     {
1055         if ((ep->flags & CA_IPV6) && !(ep->flags & CA_IPV4))
1056         {
1057             if ('\0' == ep->addr[0])  // multicast
1058             {
1059                 return snprintf(presenceUri, CA_MAX_URI_LENGTH, OC_RSRVD_PRESENCE_URI);
1060             }
1061             else
1062             {
1063                 char addressEncoded[CA_MAX_URI_LENGTH] = {0};
1064
1065                 OCStackResult result = OCEncodeAddressForRFC6874(addressEncoded,
1066                                                                  sizeof(addressEncoded),
1067                                                                  ep->addr);
1068
1069                 if (OC_STACK_OK != result)
1070                 {
1071                     return -1;
1072                 }
1073
1074                 return snprintf(presenceUri, CA_MAX_URI_LENGTH, "coap://[%s]:%u%s",
1075                         addressEncoded, ep->port, OC_RSRVD_PRESENCE_URI);
1076             }
1077         }
1078         else
1079         {
1080             if ('\0' == ep->addr[0])  // multicast
1081             {
1082                 OICStrcpy(ep->addr, sizeof(ep->addr), OC_MULTICAST_IP);
1083                 ep->port = OC_MULTICAST_PORT;
1084             }
1085             return snprintf(presenceUri, CA_MAX_URI_LENGTH, "coap://%s:%u%s",
1086                     ep->addr, ep->port, OC_RSRVD_PRESENCE_URI);
1087         }
1088     }
1089
1090     // might work for other adapters (untested, but better than nothing)
1091     return snprintf(presenceUri, CA_MAX_URI_LENGTH, "coap://%s%s", ep->addr,
1092                     OC_RSRVD_PRESENCE_URI);
1093 }
1094
1095
1096 OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint,
1097                             const CAResponseInfo_t *responseInfo)
1098 {
1099     VERIFY_NON_NULL(endpoint, FATAL, OC_STACK_INVALID_PARAM);
1100     VERIFY_NON_NULL(responseInfo, FATAL, OC_STACK_INVALID_PARAM);
1101
1102     OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
1103     ClientCB * cbNode = NULL;
1104     char *resourceTypeName = NULL;
1105     OCClientResponse *response = NULL;
1106     OCStackResult result = OC_STACK_ERROR;
1107     uint32_t maxAge = 0;
1108     int uriLen;
1109     char presenceUri[CA_MAX_URI_LENGTH];
1110
1111     int presenceSubscribe = 0;
1112     int multicastPresenceSubscribe = 0;
1113
1114     if (responseInfo->result != CA_CONTENT)
1115     {
1116         OIC_LOG_V(ERROR, TAG, "HandlePresenceResponse failed %d", responseInfo->result);
1117         return OC_STACK_ERROR;
1118     }
1119
1120     response = (OCClientResponse *)OICCalloc(1, sizeof(*response));
1121     if (!response)
1122     {
1123             OIC_LOG(ERROR, TAG, "Allocating memory for response failed");
1124             return OC_STACK_ERROR;
1125     }
1126     response->devAddr.adapter = OC_DEFAULT_ADAPTER;
1127
1128     response->payload = NULL;
1129     response->result = OC_STACK_OK;
1130
1131     CopyEndpointToDevAddr(endpoint, &response->devAddr);
1132     FixUpClientResponse(response);
1133
1134     if (responseInfo->info.payload)
1135     {
1136         result = OCParsePayload(&response->payload,
1137                 PAYLOAD_TYPE_PRESENCE,
1138                 responseInfo->info.payload,
1139                 responseInfo->info.payloadSize);
1140
1141         if(result != OC_STACK_OK)
1142         {
1143             OIC_LOG(ERROR, TAG, "Presence parse failed");
1144             goto exit;
1145         }
1146         if(!response->payload || response->payload->type != PAYLOAD_TYPE_PRESENCE)
1147         {
1148             OIC_LOG(ERROR, TAG, "Presence payload was wrong type");
1149             result = OC_STACK_ERROR;
1150             goto exit;
1151         }
1152         response->sequenceNumber = ((OCPresencePayload*)response->payload)->sequenceNumber;
1153         resourceTypeName = ((OCPresencePayload*)response->payload)->resourceType;
1154         maxAge = ((OCPresencePayload*)response->payload)->maxAge;
1155     }
1156
1157     // check for unicast presence
1158     uriLen = FormCanonicalPresenceUri(endpoint, presenceUri,
1159                                       responseInfo->isMulticast);
1160     if (uriLen < 0 || (size_t)uriLen >= sizeof (presenceUri))
1161     {
1162         result = OC_STACK_INVALID_URI;
1163         goto exit;
1164     }
1165     OIC_LOG(INFO, TAG, "check for unicast presence");
1166     cbNode = GetClientCB(NULL, 0, NULL, presenceUri);
1167     if (cbNode)
1168     {
1169         presenceSubscribe = 1;
1170     }
1171     else
1172     {
1173         // check for multicast presence
1174         OIC_LOG(INFO, TAG, "check for multicast presence");
1175         cbNode = GetClientCB(NULL, 0, NULL, OC_RSRVD_PRESENCE_URI);
1176         if (cbNode)
1177         {
1178             multicastPresenceSubscribe = 1;
1179         }
1180     }
1181
1182     if (!presenceSubscribe && !multicastPresenceSubscribe)
1183     {
1184         OIC_LOG(INFO, TAG, "Received a presence notification, "
1185                 "but need to register presence callback, ignoring");
1186         goto exit;
1187     }
1188
1189     if (presenceSubscribe)
1190     {
1191         if(cbNode->sequenceNumber == response->sequenceNumber)
1192         {
1193             OIC_LOG(INFO, TAG, "No presence change");
1194             ResetPresenceTTL(cbNode, maxAge);
1195             OIC_LOG_V(INFO, TAG, "ResetPresenceTTL - TTLlevel:%d\n", cbNode->presence->TTLlevel);
1196             goto exit;
1197         }
1198
1199         if(maxAge == 0)
1200         {
1201             OIC_LOG(INFO, TAG, "Stopping presence");
1202             response->result = OC_STACK_PRESENCE_STOPPED;
1203             if(cbNode->presence)
1204             {
1205                 OICFree(cbNode->presence->timeOut);
1206                 OICFree(cbNode->presence);
1207                 cbNode->presence = NULL;
1208             }
1209         }
1210         else
1211         {
1212             if(!cbNode->presence)
1213             {
1214                 cbNode->presence = (OCPresence *)OICMalloc(sizeof (OCPresence));
1215
1216                 if(!(cbNode->presence))
1217                 {
1218                     OIC_LOG(ERROR, TAG, "Could not allocate memory for cbNode->presence");
1219                     result = OC_STACK_NO_MEMORY;
1220                     goto exit;
1221                 }
1222
1223                 VERIFY_NON_NULL_V(cbNode->presence);
1224                 cbNode->presence->timeOut = NULL;
1225                 cbNode->presence->timeOut = (uint32_t *)
1226                         OICMalloc(PresenceTimeOutSize * sizeof(uint32_t));
1227                 if(!(cbNode->presence->timeOut)){
1228                     OIC_LOG(ERROR, TAG,
1229                                   "Could not allocate memory for cbNode->presence->timeOut");
1230                     OICFree(cbNode->presence);
1231                     result = OC_STACK_NO_MEMORY;
1232                     goto exit;
1233                 }
1234             }
1235
1236             ResetPresenceTTL(cbNode, maxAge);
1237
1238             cbNode->sequenceNumber = response->sequenceNumber;
1239         }
1240     }
1241     else
1242     {
1243         // This is the multicast case
1244         OIC_LOG(INFO, TAG, "this is the multicast presence");
1245         if (0 == maxAge)
1246         {
1247             OIC_LOG(INFO, TAG, "Stopping presence");
1248             response->result = OC_STACK_PRESENCE_STOPPED;
1249         }
1250     }
1251
1252     // Ensure that a filter is actually applied.
1253     if (resourceTypeName && cbNode->filterResourceType)
1254     {
1255         OIC_LOG_V(INFO, TAG, "find resource type : %s", resourceTypeName);
1256         if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
1257         {
1258             goto exit;
1259         }
1260     }
1261
1262     OIC_LOG(INFO, TAG, "Callback for presence");
1263
1264     cbResult = cbNode->callBack(cbNode->context, cbNode->handle, response);
1265
1266     if (cbResult == OC_STACK_DELETE_TRANSACTION)
1267     {
1268         FindAndDeleteClientCB(cbNode);
1269     }
1270
1271 exit:
1272     OCPayloadDestroy(response->payload);
1273     OICFree(response);
1274     return result;
1275 }
1276
1277 OCStackResult HandleBatchResponse(char *requestUri, OCRepPayload **payload)
1278 {
1279     if (requestUri && *payload)
1280     {
1281         char *interfaceName = NULL;
1282         char *rtTypeName = NULL;
1283         char *uriQuery = NULL;
1284         char *uriWithoutQuery = NULL;
1285         if (OC_STACK_OK == getQueryFromUri(requestUri, &uriQuery, &uriWithoutQuery))
1286         {
1287             if (OC_STACK_OK == ExtractFiltersFromQuery(uriQuery, &interfaceName, &rtTypeName))
1288             {
1289                 if (0 == strcmp(OC_RSRVD_INTERFACE_BATCH, interfaceName))
1290                 {
1291                     char *uri = (*payload)->uri;
1292                     if (uri && 0 != strcmp(uriWithoutQuery, uri))
1293                     {
1294                         OCRepPayload *newPayload = OCRepPayloadCreate();
1295                         if (newPayload)
1296                         {
1297                             OCRepPayloadSetUri(newPayload, uri);
1298                             newPayload->next = *payload;
1299                             *payload = newPayload;
1300                         }
1301                     }
1302                 }
1303             }
1304         }
1305         OICFree(interfaceName);
1306         OICFree(rtTypeName);
1307         OICFree(uriQuery);
1308         OICFree(uriWithoutQuery);
1309         return OC_STACK_OK;
1310     }
1311     return OC_STACK_INVALID_PARAM;
1312 }
1313
1314 void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
1315 {
1316     OIC_LOG(DEBUG, TAG, "Enter OCHandleResponse");
1317
1318     if(responseInfo->info.resourceUri &&
1319         strcmp(responseInfo->info.resourceUri, OC_RSRVD_PRESENCE_URI) == 0)
1320     {
1321         HandlePresenceResponse(endPoint, responseInfo);
1322         return;
1323     }
1324
1325     ClientCB *cbNode = GetClientCB(responseInfo->info.token,
1326             responseInfo->info.tokenLength, NULL, NULL);
1327
1328     ResourceObserver * observer = GetObserverUsingToken (responseInfo->info.token,
1329             responseInfo->info.tokenLength);
1330
1331     if(cbNode)
1332     {
1333         OIC_LOG(INFO, TAG, "There is a cbNode associated with the response token");
1334
1335         // check obs header option
1336         bool obsHeaderOpt = false;
1337         CAHeaderOption_t *options = responseInfo->info.options;
1338         for (uint8_t i = 0; i< responseInfo->info.numOptions; i++)
1339         {
1340             if (options && (options[i].optionID == COAP_OPTION_OBSERVE))
1341             {
1342                 obsHeaderOpt = true;
1343                 break;
1344             }
1345         }
1346
1347         if(responseInfo->result == CA_EMPTY)
1348         {
1349             OIC_LOG(INFO, TAG, "Receiving A ACK/RESET for this token");
1350             // We do not have a case for the client to receive a RESET
1351             if(responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
1352             {
1353                 //This is the case of receiving an ACK on a request to a slow resource!
1354                 OIC_LOG(INFO, TAG, "This is a pure ACK");
1355                 //TODO: should we inform the client
1356                 //      app that at least the request was received at the server?
1357             }
1358         }
1359         else if (CA_RETRANSMIT_TIMEOUT == responseInfo->result
1360                 || CA_NOT_ACCEPTABLE == responseInfo->result)
1361         {
1362             if (CA_RETRANSMIT_TIMEOUT == responseInfo->result)
1363             {
1364                 OIC_LOG(INFO, TAG, "Receiving A Timeout for this token");
1365                 OIC_LOG(INFO, TAG, "Calling into application address space");
1366             }
1367             else
1368             {
1369                 OIC_LOG(INFO, TAG, "Server doesn't support the requested payload format");
1370                 OIC_LOG(INFO, TAG, "Calling into application address space");
1371             }
1372
1373             OCClientResponse *response = NULL;
1374
1375             response = (OCClientResponse *)OICCalloc(1, sizeof(*response));
1376             if (!response)
1377             {
1378                 OIC_LOG(ERROR, TAG, "Allocating memory for response failed");
1379                 return;
1380             }
1381
1382             response->devAddr.adapter = OC_DEFAULT_ADAPTER;
1383             CopyEndpointToDevAddr(endPoint, &response->devAddr);
1384             FixUpClientResponse(response);
1385             response->resourceUri = responseInfo->info.resourceUri;
1386             memcpy(response->identity.id, responseInfo->info.identity.id,
1387                                                 sizeof (response->identity.id));
1388             response->identity.id_length = responseInfo->info.identity.id_length;
1389
1390             response->result = CAResponseToOCStackResult(responseInfo->result);
1391             cbNode->callBack(cbNode->context,
1392                     cbNode->handle, response);
1393             FindAndDeleteClientCB(cbNode);
1394             OICFree(response);
1395         }
1396         else if ((cbNode->method == OC_REST_OBSERVE || cbNode->method == OC_REST_OBSERVE_ALL)
1397                 && (responseInfo->result == CA_CONTENT) && !obsHeaderOpt)
1398         {
1399             OCClientResponse *response = NULL;
1400
1401             response = (OCClientResponse *)OICCalloc(1, sizeof(*response));
1402             if (!response)
1403             {
1404                 OIC_LOG(ERROR, TAG, "Allocating memory for response failed");
1405                 return;
1406             }
1407
1408             response->devAddr.adapter = OC_DEFAULT_ADAPTER;
1409             CopyEndpointToDevAddr(endPoint, &response->devAddr);
1410             FixUpClientResponse(response);
1411             response->resourceUri = responseInfo->info.resourceUri;
1412             memcpy(response->identity.id, responseInfo->info.identity.id,
1413                                     sizeof (response->identity.id));
1414             response->identity.id_length = responseInfo->info.identity.id_length;
1415             response->result = OC_STACK_OK;
1416
1417             OIC_LOG(DEBUG, TAG, "This is response of observer cancel or observer request fail");
1418
1419             cbNode->callBack(cbNode->context,
1420                              cbNode->handle,
1421                              response);
1422             FindAndDeleteClientCB(cbNode);
1423             OICFree(response);
1424         }
1425         else
1426         {
1427             OIC_LOG(INFO, TAG, "This is a regular response, A client call back is found");
1428             OIC_LOG(INFO, TAG, "Calling into application address space");
1429
1430             OCClientResponse *response = NULL;
1431
1432             response = (OCClientResponse *)OICCalloc(1, sizeof(*response));
1433             if (!response)
1434             {
1435                 OIC_LOG(ERROR, TAG, "Allocating memory for response failed");
1436                 return;
1437             }
1438
1439             response->devAddr.adapter = OC_DEFAULT_ADAPTER;
1440             response->sequenceNumber = MAX_SEQUENCE_NUMBER + 1;
1441             CopyEndpointToDevAddr(endPoint, &response->devAddr);
1442             FixUpClientResponse(response);
1443             response->resourceUri = responseInfo->info.resourceUri;
1444             memcpy(response->identity.id, responseInfo->info.identity.id,
1445                                                 sizeof (response->identity.id));
1446             response->identity.id_length = responseInfo->info.identity.id_length;
1447
1448             response->result = CAResponseToOCStackResult(responseInfo->result);
1449
1450             if(responseInfo->info.payload &&
1451                responseInfo->info.payloadSize)
1452             {
1453                 OCPayloadType type = PAYLOAD_TYPE_INVALID;
1454                 // check the security resource
1455                 if (SRMIsSecurityResourceURI(cbNode->requestUri))
1456                 {
1457                     type = PAYLOAD_TYPE_SECURITY;
1458                 }
1459                 else if (cbNode->method == OC_REST_DISCOVER)
1460                 {
1461                     if (strncmp(OC_RSRVD_WELL_KNOWN_URI,cbNode->requestUri,
1462                                 sizeof(OC_RSRVD_WELL_KNOWN_URI) - 1) == 0)
1463                     {
1464                         type = PAYLOAD_TYPE_DISCOVERY;
1465                     }
1466 #ifdef WITH_MQ
1467                     else if (strcmp(cbNode->requestUri, OC_RSRVD_WELL_KNOWN_MQ_URI) == 0)
1468                     {
1469                         type = PAYLOAD_TYPE_DISCOVERY;
1470                     }
1471 #endif
1472                     else if (strcmp(cbNode->requestUri, OC_RSRVD_DEVICE_URI) == 0)
1473                     {
1474                         type = PAYLOAD_TYPE_REPRESENTATION;
1475                     }
1476                     else if (strcmp(cbNode->requestUri, OC_RSRVD_PLATFORM_URI) == 0)
1477                     {
1478                         type = PAYLOAD_TYPE_REPRESENTATION;
1479                     }
1480                     else if (strcmp(cbNode->requestUri, OC_RSRVD_INTROSPECTION_URI) == 0)
1481                     {
1482                         type = PAYLOAD_TYPE_REPRESENTATION;
1483                     }
1484                     else if (strcmp(cbNode->requestUri, OC_RSRVD_INTROSPECTION_PAYLOAD_URI) == 0)
1485                     {
1486                         type = PAYLOAD_TYPE_REPRESENTATION;
1487                     }
1488 #ifdef ROUTING_GATEWAY
1489                     else if (strcmp(cbNode->requestUri, OC_RSRVD_GATEWAY_URI) == 0)
1490                     {
1491                         type = PAYLOAD_TYPE_REPRESENTATION;
1492                     }
1493 #endif
1494                     else if (strcmp(cbNode->requestUri, OC_RSRVD_RD_URI) == 0)
1495                     {
1496                         type = PAYLOAD_TYPE_REPRESENTATION;
1497                     }
1498 #ifdef TCP_ADAPTER
1499                     else if (strcmp(cbNode->requestUri, OC_RSRVD_KEEPALIVE_URI) == 0)
1500                     {
1501                         type = PAYLOAD_TYPE_REPRESENTATION;
1502                     }
1503 #endif
1504                     else
1505                     {
1506                         OIC_LOG_V(ERROR, TAG, "Unknown Payload type in Discovery: %d %s",
1507                                 cbNode->method, cbNode->requestUri);
1508                         return;
1509                     }
1510                 }
1511                 else if (cbNode->method == OC_REST_GET ||
1512                          cbNode->method == OC_REST_PUT ||
1513                          cbNode->method == OC_REST_POST ||
1514                          cbNode->method == OC_REST_OBSERVE ||
1515                          cbNode->method == OC_REST_OBSERVE_ALL ||
1516                          cbNode->method == OC_REST_DELETE)
1517                 {
1518                     if (cbNode->requestUri)
1519                     {
1520                         if (0 == strcmp(OC_RSRVD_PLATFORM_URI, cbNode->requestUri))
1521                         {
1522                             type = PAYLOAD_TYPE_REPRESENTATION;
1523                         }
1524                         else if (0 == strcmp(OC_RSRVD_DEVICE_URI, cbNode->requestUri))
1525                         {
1526                             type = PAYLOAD_TYPE_REPRESENTATION;
1527                         }
1528                         if (type == PAYLOAD_TYPE_INVALID)
1529                         {
1530                             OIC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_REPRESENTATION: %d %s",
1531                                     cbNode->method, cbNode->requestUri);
1532                             type = PAYLOAD_TYPE_REPRESENTATION;
1533                         }
1534                     }
1535                     else
1536                     {
1537                         OIC_LOG(INFO, TAG, "No Request URI, PROXY URI");
1538                         type = PAYLOAD_TYPE_REPRESENTATION;
1539                     }
1540                 }
1541                 else
1542                 {
1543                     OIC_LOG_V(ERROR, TAG, "Unknown Payload type: %d %s",
1544                             cbNode->method, cbNode->requestUri);
1545                     OICFree(response);
1546                     return;
1547                 }
1548
1549                 // In case of error, still want application to receive the error message.
1550                 if (OCResultToSuccess(response->result) || PAYLOAD_TYPE_REPRESENTATION == type)
1551                 {
1552                     if (OC_STACK_OK != OCParsePayload(&response->payload,
1553                             type,
1554                             responseInfo->info.payload,
1555                             responseInfo->info.payloadSize))
1556                     {
1557                         OIC_LOG(ERROR, TAG, "Error converting payload");
1558                         OCPayloadDestroy(response->payload);
1559                         return;
1560                     }
1561                 }
1562                 else
1563                 {
1564                     response->resourceUri = OICStrdup(cbNode->requestUri);
1565                 }
1566             }
1567
1568             response->numRcvdVendorSpecificHeaderOptions = 0;
1569             if((responseInfo->info.numOptions > 0) && (responseInfo->info.options != NULL))
1570             {
1571                 int start = 0;
1572                 //First option always with option ID is COAP_OPTION_OBSERVE if it is available.
1573                 if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
1574                 {
1575                     size_t i;
1576                     uint32_t observationOption;
1577                     uint8_t* optionData = (uint8_t*)responseInfo->info.options[0].optionData;
1578                     for (observationOption=0, i=0;
1579                             i<sizeof(uint32_t) && i<responseInfo->info.options[0].optionLength;
1580                             i++)
1581                     {
1582                         observationOption =
1583                             (observationOption << 8) | optionData[i];
1584                     }
1585                     response->sequenceNumber = observationOption;
1586                     response->numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
1587                     start = 1;
1588                 }
1589                 else
1590                 {
1591                     response->numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
1592                 }
1593
1594                 if(response->numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
1595                 {
1596                     OIC_LOG(ERROR, TAG, "#header options are more than MAX_HEADER_OPTIONS");
1597                     OCPayloadDestroy(response->payload);
1598                     OICFree(response);
1599                     return;
1600                 }
1601
1602                 for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
1603                 {
1604                     memcpy (&(response->rcvdVendorSpecificHeaderOptions[i-start]),
1605                             &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
1606                 }
1607             }
1608
1609             if (cbNode->method == OC_REST_OBSERVE &&
1610                 response->sequenceNumber > OC_OFFSET_SEQUENCE_NUMBER &&
1611                 cbNode->sequenceNumber <=  MAX_SEQUENCE_NUMBER &&
1612                 response->sequenceNumber <= cbNode->sequenceNumber)
1613             {
1614                 OIC_LOG_V(INFO, TAG, "Received stale notification. Number :%d",
1615                                                  response->sequenceNumber);
1616             }
1617             else
1618             {
1619 #ifdef RD_CLIENT
1620                 if (cbNode->requestUri)
1621                 {
1622                     // if request uri is '/oic/rd', update ins value of resource.
1623                     char *targetUri = strstr(cbNode->requestUri, OC_RSRVD_RD_URI);
1624                     if (targetUri)
1625                     {
1626                         OCUpdateResourceInsWithResponse(cbNode->requestUri, response);
1627                     }
1628                 }
1629 #endif
1630                 // set remoteID(device ID) into OCClientResponse callback parameter
1631                 if (OC_REST_DISCOVER == cbNode->method)
1632                 {
1633                     OCDiscoveryPayload *payload = (OCDiscoveryPayload*) response->payload;
1634                     // Payload can be empty in case of error message.
1635                     if (payload && payload->sid)
1636                     {
1637                         OICStrcpy(response->devAddr.remoteId, sizeof(response->devAddr.remoteId),
1638                                   payload->sid);
1639                         OIC_LOG_V(INFO, TAG, "Device ID of response : %s",
1640                                   response->devAddr.remoteId);
1641
1642 #if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
1643                         OCCMDiscoveryResource(response);
1644 #endif
1645                     }
1646                 }
1647                 if (response->payload && response->payload->type == PAYLOAD_TYPE_REPRESENTATION)
1648                 {
1649                     HandleBatchResponse(cbNode->requestUri, (OCRepPayload **)&response->payload);
1650                 }
1651
1652                 OCStackApplicationResult appFeedback = cbNode->callBack(cbNode->context,
1653                                                                         cbNode->handle,
1654                                                                         response);
1655                 cbNode->sequenceNumber = response->sequenceNumber;
1656
1657                 if (appFeedback == OC_STACK_DELETE_TRANSACTION)
1658                 {
1659                     FindAndDeleteClientCB(cbNode);
1660                 }
1661                 else
1662                 {
1663                     // To keep discovery callbacks active.
1664                     cbNode->TTL = GetTicks(MAX_CB_TIMEOUT_SECONDS *
1665                                             MILLISECONDS_PER_SECOND);
1666                 }
1667             }
1668
1669             //Need to send ACK when the response is CON
1670             if(responseInfo->info.type == CA_MSG_CONFIRM)
1671             {
1672                 SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY,
1673                         CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
1674             }
1675
1676             OCPayloadDestroy(response->payload);
1677             OICFree(response);
1678         }
1679         return;
1680     }
1681
1682     if(observer)
1683     {
1684         OIC_LOG(INFO, TAG, "There is an observer associated with the response token");
1685         if(responseInfo->result == CA_EMPTY)
1686         {
1687             OIC_LOG(INFO, TAG, "Receiving A ACK/RESET for this token");
1688             if(responseInfo->info.type == CA_MSG_RESET)
1689             {
1690                 OIC_LOG(INFO, TAG, "This is a RESET");
1691                 OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
1692                         OC_OBSERVER_NOT_INTERESTED);
1693             }
1694             else if(responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
1695             {
1696                 OIC_LOG(INFO, TAG, "This is a pure ACK");
1697                 OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
1698                         OC_OBSERVER_STILL_INTERESTED);
1699             }
1700         }
1701         else if(responseInfo->result == CA_RETRANSMIT_TIMEOUT)
1702         {
1703             OIC_LOG(INFO, TAG, "Receiving Time Out for an observer");
1704             OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
1705                     OC_OBSERVER_FAILED_COMM);
1706         }
1707         return;
1708     }
1709
1710     if(!cbNode && !observer)
1711     {
1712         if(myStackMode == OC_CLIENT || myStackMode == OC_CLIENT_SERVER
1713            || myStackMode == OC_GATEWAY)
1714         {
1715             OIC_LOG(INFO, TAG, "This is a client, but no cbNode was found for token");
1716             if(responseInfo->result == CA_EMPTY)
1717             {
1718                 OIC_LOG(INFO, TAG, "Receiving CA_EMPTY in the ocstack");
1719             }
1720             else
1721             {
1722                 OIC_LOG(INFO, TAG, "Received a message without callbacks. Sending RESET");
1723                 SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY,
1724                                         CA_MSG_RESET, 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
1725             }
1726         }
1727
1728         if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER
1729            || myStackMode == OC_GATEWAY)
1730         {
1731             OIC_LOG(INFO, TAG, "This is a server, but no observer was found for token");
1732             if (responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
1733             {
1734                 OIC_LOG_V(INFO, TAG, "Received ACK at server for messageId : %d",
1735                                             responseInfo->info.messageId);
1736             }
1737             if (responseInfo->info.type == CA_MSG_RESET)
1738             {
1739                 OIC_LOG_V(INFO, TAG, "Received RESET at server for messageId : %d",
1740                                             responseInfo->info.messageId);
1741             }
1742         }
1743
1744         return;
1745     }
1746 }
1747
1748 void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
1749 {
1750     VERIFY_NON_NULL_NR(endPoint, FATAL);
1751     VERIFY_NON_NULL_NR(responseInfo, FATAL);
1752
1753     OIC_LOG(INFO, TAG, "Enter HandleCAResponses");
1754     OIC_TRACE_BEGIN(%s:HandleCAResponses, TAG);
1755 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
1756 #ifdef ROUTING_GATEWAY
1757     bool needRIHandling = false;
1758     /*
1759      * Routing manager is going to update either of endpoint or response or both.
1760      * This typecasting is done to avoid unnecessary duplication of Endpoint and responseInfo
1761      * RM can update "routeData" option in endPoint so that future RI requests can be sent to proper
1762      * destination.
1763      */
1764     OCStackResult ret = RMHandleResponse((CAResponseInfo_t *)responseInfo, (CAEndpoint_t *)endPoint,
1765                                          &needRIHandling);
1766     if(ret != OC_STACK_OK || !needRIHandling)
1767     {
1768         OIC_LOG_V(INFO, TAG, "Routing status![%d]. Not forwarding to RI", ret);
1769         OIC_TRACE_END();
1770         return;
1771     }
1772 #endif
1773
1774     /*
1775      * Put source in sender endpoint so that the next packet from application can be routed to
1776      * proper destination and remove "RM" coap header option before passing request / response to
1777      * RI as this option will make no sense to either RI or application.
1778      */
1779     RMUpdateInfo((CAHeaderOption_t **) &(responseInfo->info.options),
1780                  (uint8_t *) &(responseInfo->info.numOptions),
1781                  (CAEndpoint_t *) endPoint);
1782 #endif
1783
1784     OCHandleResponse(endPoint, responseInfo);
1785
1786     OIC_LOG(INFO, TAG, "Exit HandleCAResponses");
1787     OIC_TRACE_END();
1788 }
1789
1790 /*
1791  * This function handles error response from CA
1792  * code shall be added to handle the errors
1793  */
1794 void HandleCAErrorResponse(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo)
1795 {
1796     VERIFY_NON_NULL_NR(endPoint, FATAL);
1797     VERIFY_NON_NULL_NR(errorInfo, FATAL);
1798
1799     OIC_LOG(INFO, TAG, "Enter HandleCAErrorResponse");
1800     OIC_TRACE_BEGIN(%s:HandleCAErrorResponse, TAG);
1801
1802     ClientCB *cbNode = GetClientCB(errorInfo->info.token,
1803                                    errorInfo->info.tokenLength, NULL, NULL);
1804     if (cbNode)
1805     {
1806         OCClientResponse *response = NULL;
1807
1808         response = (OCClientResponse *)OICCalloc(1, sizeof(*response));
1809         if (!response)
1810         {
1811             OIC_LOG(ERROR, TAG, "Allocating memory for response failed");
1812             return;
1813         }
1814
1815         response->devAddr.adapter = OC_DEFAULT_ADAPTER;
1816         CopyEndpointToDevAddr(endPoint, &response->devAddr);
1817         FixUpClientResponse(response);
1818         response->resourceUri = errorInfo->info.resourceUri;
1819         memcpy(response->identity.id, errorInfo->info.identity.id,
1820                sizeof (response->identity.id));
1821         response->identity.id_length = errorInfo->info.identity.id_length;
1822         response->result = CAResultToOCResult(errorInfo->result);
1823
1824         cbNode->callBack(cbNode->context, cbNode->handle, response);
1825         OICFree(response);
1826     }
1827
1828     ResourceObserver *observer = GetObserverUsingToken(errorInfo->info.token,
1829                                                        errorInfo->info.tokenLength);
1830     if (observer)
1831     {
1832         OIC_LOG(INFO, TAG, "Receiving communication error for an observer");
1833         OCStackResult result = CAResultToOCResult(errorInfo->result);
1834         if (OC_STACK_COMM_ERROR == result)
1835         {
1836             OCStackFeedBack(errorInfo->info.token, errorInfo->info.tokenLength,
1837                             OC_OBSERVER_FAILED_COMM);
1838         }
1839     }
1840
1841     OIC_LOG(INFO, TAG, "Exit HandleCAErrorResponse");
1842     OIC_TRACE_END();
1843 }
1844
1845 /*
1846  * This function sends out Direct Stack Responses. These are responses that are not coming
1847  * from the application entity handler. These responses have no payload and are usually ACKs,
1848  * RESETs or some error conditions that were caught by the stack.
1849  */
1850 OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16_t coapID,
1851         const CAResponseResult_t responseResult, const CAMessageType_t type,
1852         const uint8_t numOptions, const CAHeaderOption_t *options,
1853         CAToken_t token, uint8_t tokenLength, const char *resourceUri,
1854         CADataType_t dataType)
1855 {
1856     OIC_LOG(DEBUG, TAG, "Entering SendDirectStackResponse");
1857     CAResponseInfo_t respInfo = {
1858         .result = responseResult
1859     };
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->acceptVersion, &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_LOG(DEBUG, TAG, "Enter OCHandleRequests");
2020     OIC_LOG_V(INFO, TAG, "Endpoint URI : %s", requestInfo->info.resourceUri);
2021
2022     if (myStackMode == OC_CLIENT)
2023     {
2024         //TODO: should the client be responding to requests?
2025         return;
2026     }
2027
2028     // If the request message is Confirmable,
2029     // then the response SHOULD be returned in an Acknowledgement message.
2030     CAMessageType_t directResponseType = requestInfo->info.type;
2031     directResponseType = (directResponseType == CA_MSG_CONFIRM)
2032             ? CA_MSG_ACKNOWLEDGE : CA_MSG_NONCONFIRM;
2033
2034     char * uriWithoutQuery = NULL;
2035     char * query = NULL;
2036     OCStackResult requestResult = OC_STACK_ERROR;
2037
2038     requestResult = getQueryFromUri(requestInfo->info.resourceUri, &query, &uriWithoutQuery);
2039
2040     if (requestResult != OC_STACK_OK || !uriWithoutQuery)
2041     {
2042         OIC_LOG_V(ERROR, TAG, "getQueryFromUri() failed with OC error code %d\n", requestResult);
2043         return;
2044     }
2045     OIC_LOG_V(INFO, TAG, "URI without query: %s", uriWithoutQuery);
2046     OIC_LOG_V(INFO, TAG, "Query : %s", query);
2047
2048     OCServerProtocolRequest serverRequest = { 0 };
2049     if (strlen(uriWithoutQuery) < MAX_URI_LENGTH)
2050     {
2051         OICStrcpy(serverRequest.resourceUrl, sizeof(serverRequest.resourceUrl), uriWithoutQuery);
2052         OICFree(uriWithoutQuery);
2053     }
2054     else
2055     {
2056         OIC_LOG(ERROR, TAG, "URI length exceeds MAX_URI_LENGTH.");
2057         OICFree(uriWithoutQuery);
2058         OICFree(query);
2059         return;
2060     }
2061
2062     if (query)
2063     {
2064         if (strlen(query) < MAX_QUERY_LENGTH)
2065         {
2066             OICStrcpy(serverRequest.query, sizeof(serverRequest.query), query);
2067             OICFree(query);
2068         }
2069         else
2070         {
2071             OIC_LOG(ERROR, TAG, "Query length exceeds MAX_QUERY_LENGTH.");
2072             OICFree(query);
2073             return;
2074         }
2075     }
2076
2077     if ((requestInfo->info.payload) && (0 < requestInfo->info.payloadSize))
2078     {
2079         serverRequest.reqTotalSize = requestInfo->info.payloadSize;
2080         serverRequest.payload = (uint8_t *) OICMalloc(requestInfo->info.payloadSize);
2081         if (!serverRequest.payload)
2082         {
2083             OIC_LOG(ERROR, TAG, "Allocation for payload failed.");
2084             return;
2085         }
2086         memcpy (serverRequest.payload, requestInfo->info.payload,
2087                 requestInfo->info.payloadSize);
2088     }
2089     else
2090     {
2091         serverRequest.reqTotalSize = 0;
2092     }
2093
2094     switch (requestInfo->method)
2095     {
2096         case CA_GET:
2097             serverRequest.method = OC_REST_GET;
2098             break;
2099         case CA_PUT:
2100             serverRequest.method = OC_REST_PUT;
2101             break;
2102         case CA_POST:
2103             serverRequest.method = OC_REST_POST;
2104             break;
2105         case CA_DELETE:
2106             serverRequest.method = OC_REST_DELETE;
2107             break;
2108         default:
2109             OIC_LOG_V(ERROR, TAG, "Received CA method %d not supported", requestInfo->method);
2110             SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_REQ,
2111                                     directResponseType, requestInfo->info.numOptions,
2112                                     requestInfo->info.options, requestInfo->info.token,
2113                                     requestInfo->info.tokenLength, requestInfo->info.resourceUri,
2114                                     CA_RESPONSE_DATA);
2115             OICFree(serverRequest.payload);
2116             return;
2117     }
2118
2119     OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)requestInfo->info.token,
2120                    requestInfo->info.tokenLength);
2121
2122     serverRequest.tokenLength = requestInfo->info.tokenLength;
2123     if (serverRequest.tokenLength)
2124     {
2125         // Non empty token
2126         serverRequest.requestToken = (CAToken_t)OICMalloc(requestInfo->info.tokenLength);
2127
2128         if (!serverRequest.requestToken)
2129         {
2130             OIC_LOG(FATAL, TAG, "Allocation for token failed.");
2131             SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_INTERNAL_SERVER_ERROR,
2132                                     directResponseType, requestInfo->info.numOptions,
2133                                     requestInfo->info.options, requestInfo->info.token,
2134                                     requestInfo->info.tokenLength, requestInfo->info.resourceUri,
2135                                     CA_RESPONSE_DATA);
2136             OICFree(serverRequest.payload);
2137             return;
2138         }
2139         memcpy(serverRequest.requestToken, requestInfo->info.token, requestInfo->info.tokenLength);
2140     }
2141
2142     switch (requestInfo->info.acceptFormat)
2143     {
2144         case CA_FORMAT_APPLICATION_CBOR:
2145             serverRequest.acceptFormat = OC_FORMAT_CBOR;
2146             break;
2147         case CA_FORMAT_APPLICATION_VND_OCF_CBOR:
2148             serverRequest.acceptFormat = OC_FORMAT_VND_OCF_CBOR;
2149             break;
2150         case CA_FORMAT_UNDEFINED:
2151             serverRequest.acceptFormat = OC_FORMAT_UNDEFINED;
2152             break;
2153         default:
2154             serverRequest.acceptFormat = OC_FORMAT_UNSUPPORTED;
2155     }
2156
2157     if (requestInfo->info.type == CA_MSG_CONFIRM)
2158     {
2159         serverRequest.qos = OC_HIGH_QOS;
2160     }
2161     else
2162     {
2163         serverRequest.qos = OC_LOW_QOS;
2164     }
2165     // CA does not need the following field
2166     // Are we sure CA does not need them? how is it responding to multicast
2167     serverRequest.delayedResNeeded = 0;
2168
2169     serverRequest.coapID = requestInfo->info.messageId;
2170
2171     CopyEndpointToDevAddr(endPoint, &serverRequest.devAddr);
2172
2173     // copy vendor specific header options
2174     uint8_t tempNum = (requestInfo->info.numOptions);
2175
2176     // Assume no observation requested and it is a pure GET.
2177     // If obs registration/de-registration requested it'll be fetched from the
2178     // options in GetObserveHeaderOption()
2179     serverRequest.observationOption = OC_OBSERVE_NO_OPTION;
2180
2181     GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &tempNum);
2182     if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
2183     {
2184         OIC_LOG(ERROR, TAG,
2185                 "The request info numOptions is greater than MAX_HEADER_OPTIONS");
2186         SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_OPT,
2187                                 directResponseType, requestInfo->info.numOptions,
2188                                 requestInfo->info.options, requestInfo->info.token,
2189                                 requestInfo->info.tokenLength, requestInfo->info.resourceUri,
2190                                 CA_RESPONSE_DATA);
2191         OICFree(serverRequest.payload);
2192         OICFree(serverRequest.requestToken);
2193         return;
2194     }
2195     serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
2196     if (serverRequest.numRcvdVendorSpecificHeaderOptions && requestInfo->info.options)
2197     {
2198         memcpy(&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
2199                sizeof(CAHeaderOption_t) * tempNum);
2200     }
2201
2202     requestResult = HandleStackRequests (&serverRequest);
2203
2204     if (requestResult == OC_STACK_SLOW_RESOURCE)
2205     {
2206         // Send ACK to client as precursor to slow response
2207         if (requestInfo->info.type == CA_MSG_CONFIRM)
2208         {
2209             SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_EMPTY,
2210                                     CA_MSG_ACKNOWLEDGE,0, NULL, NULL, 0, NULL,
2211                                     CA_RESPONSE_DATA);
2212         }
2213     }
2214     if (requestResult == OC_STACK_RESOURCE_ERROR
2215             && serverRequest.observationOption == OC_OBSERVE_REGISTER)
2216     {
2217         OIC_LOG_V(ERROR, TAG, "Observe Registration failed due to resource error");
2218     }
2219     else if (!OCResultToSuccess(requestResult))
2220     {
2221         OIC_LOG_V(ERROR, TAG, "HandleStackRequests failed. error: %d", requestResult);
2222
2223         CAResponseResult_t stackResponse = OCToCAStackResult(requestResult, serverRequest.method);
2224
2225         SendDirectStackResponse(endPoint, requestInfo->info.messageId, stackResponse,
2226                                 directResponseType, requestInfo->info.numOptions,
2227                                 requestInfo->info.options, requestInfo->info.token,
2228                                 requestInfo->info.tokenLength, requestInfo->info.resourceUri,
2229                                 CA_RESPONSE_DATA);
2230     }
2231     // requestToken is fed to HandleStackRequests, which then goes to AddServerRequest.
2232     // The token is copied in there, and is thus still owned by this function.
2233     OICFree(serverRequest.payload);
2234     OICFree(serverRequest.requestToken);
2235     OIC_LOG(INFO, TAG, "Exit OCHandleRequests");
2236 }
2237
2238 //This function will be called back by CA layer when a request is received
2239 void HandleCARequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
2240 {
2241     OIC_LOG(INFO, TAG, "Enter HandleCARequests");
2242     OIC_TRACE_BEGIN(%s:HandleCARequests, TAG);
2243     if (!endPoint)
2244     {
2245         OIC_LOG(ERROR, TAG, "endPoint is NULL");
2246         OIC_TRACE_END();
2247         return;
2248     }
2249
2250     if (!requestInfo)
2251     {
2252         OIC_LOG(ERROR, TAG, "requestInfo is NULL");
2253         OIC_TRACE_END();
2254         return;
2255     }
2256
2257 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
2258 #ifdef ROUTING_GATEWAY
2259     bool needRIHandling = false;
2260     bool isEmptyMsg = false;
2261     /*
2262      * Routing manager is going to update either of endpoint or request or both.
2263      * This typecasting is done to avoid unnecessary duplication of Endpoint and requestInfo
2264      * RM can update "routeData" option in endPoint so that future RI requests can be sent to proper
2265      * destination. It can also remove "RM" coap header option before passing request / response to
2266      * RI as this option will make no sense to either RI or application.
2267      */
2268     OCStackResult ret = RMHandleRequest((CARequestInfo_t *)requestInfo, (CAEndpoint_t *)endPoint,
2269                                         &needRIHandling, &isEmptyMsg);
2270     if (OC_STACK_OK != ret || !needRIHandling)
2271     {
2272         OIC_LOG_V(INFO, TAG, "Routing status![%d]. Not forwarding to RI", ret);
2273         OIC_TRACE_END();
2274         return;
2275     }
2276 #endif
2277
2278     /*
2279      * Put source in sender endpoint so that the next packet from application can be routed to
2280      * proper destination and remove RM header option.
2281      */
2282     RMUpdateInfo((CAHeaderOption_t **) &(requestInfo->info.options),
2283                  (uint8_t *) &(requestInfo->info.numOptions),
2284                  (CAEndpoint_t *) endPoint);
2285
2286 #ifdef ROUTING_GATEWAY
2287     if (isEmptyMsg)
2288     {
2289         /*
2290          * In Gateways, the MSGType in route option is used to check if the actual
2291          * response is EMPTY message(4 bytes CoAP Header).  In case of Client, the
2292          * EMPTY response is sent in the form of POST request which need to be changed
2293          * to a EMPTY response by RM.  This translation is done in this part of the code.
2294          */
2295         OIC_LOG(INFO, TAG, "This is a Empty response from the Client");
2296         CAResponseInfo_t respInfo = {.result = CA_EMPTY,
2297                                      .info.messageId = requestInfo->info.messageId,
2298                                      .info.type = CA_MSG_ACKNOWLEDGE};
2299         OCHandleResponse(endPoint, &respInfo);
2300     }
2301     else
2302 #endif
2303 #endif
2304     {
2305         // Normal handling of the packet
2306         OCHandleRequests(endPoint, requestInfo);
2307     }
2308     OIC_LOG(INFO, TAG, "Exit HandleCARequests");
2309     OIC_TRACE_END();
2310 }
2311
2312 //-----------------------------------------------------------------------------
2313 // Public APIs
2314 //-----------------------------------------------------------------------------
2315 #ifdef RA_ADAPTER
2316 OCStackResult OCSetRAInfo(const OCRAInfo_t *raInfo)
2317 {
2318     if (!raInfo           ||
2319         !raInfo->username ||
2320         !raInfo->hostname ||
2321         !raInfo->xmpp_domain)
2322     {
2323
2324         return OC_STACK_INVALID_PARAM;
2325     }
2326     OCStackResult result = CAResultToOCResult(CASetRAInfo((const CARAInfo_t *) raInfo));
2327     gRASetInfo = (result == OC_STACK_OK)? true : false;
2328
2329     return result;
2330 }
2331 #endif
2332
2333 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
2334 {
2335     (void) ipAddr;
2336     (void) port;
2337     return OCInit1(mode, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS);
2338 }
2339
2340 OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlags clientFlags)
2341 {
2342     OIC_LOG(DEBUG, TAG, "call OCInit1");
2343     return OCInit2(mode, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS, OC_DEFAULT_ADAPTER);
2344 }
2345
2346 OCStackResult OCInit2(OCMode mode, OCTransportFlags serverFlags, OCTransportFlags clientFlags,
2347                       OCTransportAdapter transportType)
2348 {
2349     if(stackState == OC_STACK_INITIALIZED)
2350     {
2351         OIC_LOG(INFO, TAG, "Subsequent calls to OCInit() without calling \
2352                 OCStop() between them are ignored.");
2353         return OC_STACK_OK;
2354     }
2355
2356 #ifndef ROUTING_GATEWAY
2357     if (OC_GATEWAY == mode)
2358     {
2359         OIC_LOG(ERROR, TAG, "Routing Manager not supported");
2360         return OC_STACK_INVALID_PARAM;
2361     }
2362 #endif
2363
2364 #ifdef RA_ADAPTER
2365     if(!gRASetInfo)
2366     {
2367         OIC_LOG(ERROR, TAG, "Need to call OCSetRAInfo before calling OCInit");
2368         return OC_STACK_ERROR;
2369     }
2370 #endif
2371
2372     OCStackResult result = OC_STACK_ERROR;
2373     OIC_LOG(INFO, TAG, "Entering OCInit");
2374
2375     // Validate mode
2376     if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)
2377         || (mode == OC_GATEWAY)))
2378     {
2379         OIC_LOG(ERROR, TAG, "Invalid mode");
2380         return OC_STACK_ERROR;
2381     }
2382     myStackMode = mode;
2383
2384     if (mode == OC_CLIENT || mode == OC_CLIENT_SERVER || mode == OC_GATEWAY)
2385     {
2386         caglobals.client = true;
2387     }
2388     if (mode == OC_SERVER || mode == OC_CLIENT_SERVER || mode == OC_GATEWAY)
2389     {
2390         caglobals.server = true;
2391     }
2392
2393     caglobals.serverFlags = (CATransportFlags_t)serverFlags;
2394     if (!(caglobals.serverFlags & CA_IPFAMILY_MASK))
2395     {
2396         caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4|CA_IPV6);
2397     }
2398     caglobals.clientFlags = (CATransportFlags_t)clientFlags;
2399     if (!(caglobals.clientFlags & CA_IPFAMILY_MASK))
2400     {
2401         caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4|CA_IPV6);
2402     }
2403
2404     defaultDeviceHandler = NULL;
2405     defaultDeviceHandlerCallbackParameter = NULL;
2406
2407     result = InitializeScheduleResourceList();
2408     VERIFY_SUCCESS(result, OC_STACK_OK);
2409
2410     result = CAResultToOCResult(CAInitialize((CATransportAdapter_t)transportType));
2411     VERIFY_SUCCESS(result, OC_STACK_OK);
2412
2413     result = CAResultToOCResult(OCSelectNetwork(transportType));
2414     VERIFY_SUCCESS(result, OC_STACK_OK);
2415
2416     result = CAResultToOCResult(CARegisterNetworkMonitorHandler(
2417       OCDefaultAdapterStateChangedHandler, OCDefaultConnectionStateChangedHandler));
2418     VERIFY_SUCCESS(result, OC_STACK_OK);
2419
2420     switch (myStackMode)
2421     {
2422         case OC_CLIENT:
2423             CARegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
2424             result = CAResultToOCResult(CAStartDiscoveryServer());
2425             OIC_LOG(INFO, TAG, "Client mode: CAStartDiscoveryServer");
2426             break;
2427         case OC_SERVER:
2428             SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
2429             result = CAResultToOCResult(CAStartListeningServer());
2430             OIC_LOG(INFO, TAG, "Server mode: CAStartListeningServer");
2431             break;
2432         case OC_CLIENT_SERVER:
2433         case OC_GATEWAY:
2434             SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
2435             result = CAResultToOCResult(CAStartListeningServer());
2436             if(result == OC_STACK_OK)
2437             {
2438                 result = CAResultToOCResult(CAStartDiscoveryServer());
2439             }
2440             break;
2441     }
2442     VERIFY_SUCCESS(result, OC_STACK_OK);
2443
2444 #ifdef TCP_ADAPTER
2445     CARegisterKeepAliveHandler(HandleKeepAliveConnCB);
2446 #endif
2447
2448 #ifdef WITH_PRESENCE
2449     PresenceTimeOutSize = sizeof (PresenceTimeOut) / sizeof (PresenceTimeOut[0]) - 1;
2450 #endif // WITH_PRESENCE
2451
2452     //Update Stack state to initialized
2453     stackState = OC_STACK_INITIALIZED;
2454
2455     // Initialize resource
2456     if(myStackMode != OC_CLIENT)
2457     {
2458         result = initResources();
2459     }
2460
2461 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
2462     RMSetStackMode(mode);
2463 #ifdef ROUTING_GATEWAY
2464     if (OC_GATEWAY == myStackMode)
2465     {
2466         result = RMInitialize();
2467     }
2468 #endif
2469 #endif
2470
2471 #ifdef TCP_ADAPTER
2472     if (result == OC_STACK_OK)
2473     {
2474         result = InitializeKeepAlive(myStackMode);
2475     }
2476 #endif
2477
2478 #if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
2479     // Initialize the Connection Manager
2480     if (result == OC_STACK_OK)
2481     {
2482         result = OCCMInitialize();
2483     }
2484 #endif
2485
2486 exit:
2487     if(result != OC_STACK_OK)
2488     {
2489         OIC_LOG(ERROR, TAG, "Stack initialization error");
2490         TerminateScheduleResourceList();
2491         deleteAllResources();
2492         CATerminate();
2493         stackState = OC_STACK_UNINITIALIZED;
2494     }
2495     return result;
2496 }
2497
2498 OCStackResult OCStop()
2499 {
2500     OIC_LOG(INFO, TAG, "Entering OCStop");
2501
2502     if (stackState == OC_STACK_UNINIT_IN_PROGRESS)
2503     {
2504         OIC_LOG(DEBUG, TAG, "Stack already stopping, exiting");
2505         return OC_STACK_OK;
2506     }
2507     else if (stackState != OC_STACK_INITIALIZED)
2508     {
2509         OIC_LOG(INFO, TAG, "Stack not initialized");
2510         return OC_STACK_ERROR;
2511     }
2512
2513     // unset cautil config
2514     CAUtilConfig_t configs = {(CATransportBTFlags_t)CA_DEFAULT_BT_FLAGS};
2515     CAUtilSetBTConfigure(configs);
2516
2517     stackState = OC_STACK_UNINIT_IN_PROGRESS;
2518
2519 #ifdef WITH_PRESENCE
2520     // Ensure that the TTL associated with ANY and ALL presence notifications originating from
2521     // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
2522     presenceResource.presenceTTL = 0;
2523 #endif // WITH_PRESENCE
2524
2525 #ifdef ROUTING_GATEWAY
2526     if (OC_GATEWAY == myStackMode)
2527     {
2528         RMTerminate();
2529     }
2530 #endif
2531
2532 #ifdef TCP_ADAPTER
2533     TerminateKeepAlive(myStackMode);
2534 #endif
2535
2536     OCStackResult result = CAResultToOCResult(
2537             CAUnregisterNetworkMonitorHandler(OCDefaultAdapterStateChangedHandler,
2538                                               OCDefaultConnectionStateChangedHandler));
2539     if (OC_STACK_OK != result)
2540     {
2541         OIC_LOG(ERROR, TAG, "CAUnregisterNetworkMonitorHandler has failed");
2542     }
2543
2544     TerminateScheduleResourceList();
2545     // Remove all observers
2546     DeleteObserverList();
2547     // Free memory dynamically allocated for resources
2548     deleteAllResources();
2549     // Remove all the client callbacks
2550     DeleteClientCBList();
2551     // Terminate connectivity-abstraction layer.
2552     CATerminate();
2553
2554 #if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
2555     // Terminate the Connection Manager
2556     OCCMTerminate();
2557 #endif
2558
2559     stackState = OC_STACK_UNINITIALIZED;
2560     return OC_STACK_OK;
2561 }
2562
2563 OCStackResult OCStartMulticastServer()
2564 {
2565     if(stackState != OC_STACK_INITIALIZED)
2566     {
2567         OIC_LOG(ERROR, TAG, "OCStack is not initalized. Cannot start multicast server.");
2568         return OC_STACK_ERROR;
2569     }
2570     CAResult_t ret = CAStartListeningServer();
2571     if (CA_STATUS_OK != ret)
2572     {
2573         OIC_LOG_V(ERROR, TAG, "Failed starting listening server: %d", ret);
2574         return OC_STACK_ERROR;
2575     }
2576     return OC_STACK_OK;
2577 }
2578
2579 OCStackResult OCStopMulticastServer()
2580 {
2581     CAResult_t ret = CAStopListeningServer();
2582     if (CA_STATUS_OK != ret)
2583     {
2584         OIC_LOG_V(ERROR, TAG, "Failed stopping listening server: %d", ret);
2585         return OC_STACK_ERROR;
2586     }
2587     return OC_STACK_OK;
2588 }
2589
2590 CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
2591 {
2592     switch (qos)
2593     {
2594         case OC_HIGH_QOS:
2595             return CA_MSG_CONFIRM;
2596         case OC_LOW_QOS:
2597         case OC_MEDIUM_QOS:
2598         case OC_NA_QOS:
2599         default:
2600             return CA_MSG_NONCONFIRM;
2601     }
2602 }
2603
2604 /**
2605  *  A request uri consists of the following components in order:
2606  *                              example
2607  *  optionally one of
2608  *      CoAP over UDP prefix    "coap://"
2609  *      CoAP over TCP prefix    "coap+tcp://"
2610  *      CoAP over DTLS prefix   "coaps://"
2611  *      CoAP over TLS prefix    "coaps+tcp://"
2612  *  optionally one of
2613  *      IPv6 address            "[1234::5678]"
2614  *      IPv4 address            "192.168.1.1"
2615  *  optional port               ":5683"
2616  *  resource uri                "/oc/core..."
2617  *
2618  *  for PRESENCE requests, extract resource type.
2619  */
2620 static OCStackResult ParseRequestUri(const char *fullUri,
2621                                         OCTransportAdapter adapter,
2622                                         OCTransportFlags flags,
2623                                         OCDevAddr **devAddr,
2624                                         char **resourceUri,
2625                                         char **resourceType)
2626 {
2627     VERIFY_NON_NULL(fullUri, FATAL, OC_STACK_INVALID_CALLBACK);
2628
2629     OCStackResult result = OC_STACK_OK;
2630     OCDevAddr *da = NULL;
2631     char *colon = NULL;
2632     char *end;
2633
2634     // provide defaults for all returned values
2635     if (devAddr)
2636     {
2637         *devAddr = NULL;
2638     }
2639     if (resourceUri)
2640     {
2641         *resourceUri = NULL;
2642     }
2643     if (resourceType)
2644     {
2645         *resourceType = NULL;
2646     }
2647
2648     // delimit url prefix, if any
2649     const char *start = fullUri;
2650     char *slash2 = strstr(start, "//");
2651     if (slash2)
2652     {
2653         start = slash2 + 2;
2654     }
2655     char *slash = strchr(start, '/');
2656     if (!slash)
2657     {
2658         return OC_STACK_INVALID_URI;
2659     }
2660
2661     // process url scheme
2662     size_t prefixLen = slash2 - fullUri;
2663     bool istcp = false;
2664     if (prefixLen)
2665     {
2666         if (((prefixLen == sizeof(COAP_TCP_SCHEME) - 1) && (!strncmp(fullUri, COAP_TCP_SCHEME, prefixLen)))
2667         || ((prefixLen == sizeof(COAPS_TCP_SCHEME) - 1) && (!strncmp(fullUri, COAPS_TCP_SCHEME, prefixLen))))
2668         {
2669             istcp = true;
2670         }
2671     }
2672
2673     // TODO: this logic should come in with unit tests exercising the various strings
2674     // processs url prefix, if any
2675     size_t urlLen = slash - start;
2676     // port
2677     uint16_t port = 0;
2678     size_t len = 0;
2679     if (urlLen && devAddr)
2680     {   // construct OCDevAddr
2681         if (start[0] == '[')
2682         {   // ipv6 address
2683             char *close = strchr(++start, ']');
2684             if (!close || close > slash)
2685             {
2686                 return OC_STACK_INVALID_URI;
2687             }
2688             end = close;
2689             if (close[1] == ':')
2690             {
2691                 colon = close + 1;
2692             }
2693
2694             if (istcp)
2695             {
2696                 adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_TCP);
2697             }
2698             else
2699             {
2700                 adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
2701             }
2702             flags = (OCTransportFlags)(flags | OC_IP_USE_V6);
2703         }
2704         else
2705         {
2706             char *dot = strchr(start, '.');
2707             if (dot && dot < slash)
2708             {   // ipv4 address
2709                 colon = strchr(start, ':');
2710                 end = (colon && colon < slash) ? colon : slash;
2711
2712                 if (istcp)
2713                 {
2714                     // coap over tcp
2715                     adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_TCP);
2716                 }
2717                 else
2718                 {
2719                     adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
2720                 }
2721                 flags = (OCTransportFlags)(flags | OC_IP_USE_V4);
2722             }
2723             else
2724             {   // MAC address
2725                 end = slash;
2726             }
2727         }
2728         len = end - start;
2729         if (len >= sizeof(da->addr))
2730         {
2731             return OC_STACK_INVALID_URI;
2732         }
2733         // collect port, if any
2734         if (colon && colon < slash)
2735         {
2736             for (colon++; colon < slash; colon++)
2737             {
2738                 char c = colon[0];
2739                 if (c < '0' || c > '9')
2740                 {
2741                     return OC_STACK_INVALID_URI;
2742                 }
2743                 port = 10 * port + c - '0';
2744             }
2745         }
2746
2747         len = end - start;
2748         if (len >= sizeof(da->addr))
2749         {
2750             return OC_STACK_INVALID_URI;
2751         }
2752
2753         da = (OCDevAddr *)OICCalloc(sizeof (OCDevAddr), 1);
2754         if (!da)
2755         {
2756             return OC_STACK_NO_MEMORY;
2757         }
2758
2759         // Decode address per RFC 6874.
2760         result = OCDecodeAddressForRFC6874(da->addr, sizeof(da->addr), start, end);
2761         if (result != OC_STACK_OK)
2762         {
2763              OICFree(*devAddr);
2764              return result;
2765         }
2766
2767         da->port = port;
2768         da->adapter = adapter;
2769         da->flags = flags;
2770         if (!strncmp(fullUri, "coaps", 5))
2771         {
2772             da->flags = (OCTransportFlags)(da->flags|CA_SECURE);
2773         }
2774         *devAddr = da;
2775     }
2776
2777     // process resource uri, if any
2778     if (slash)
2779     {   // request uri and query
2780         size_t ulen = strlen(slash); // resource uri length
2781         size_t tlen = 0;      // resource type length
2782         char *type = NULL;
2783
2784         static const char strPresence[] = "/oic/ad?rt=";
2785         static const size_t lenPresence = sizeof(strPresence) - 1;
2786         if (!strncmp(slash, strPresence, lenPresence))
2787         {
2788             type = slash + lenPresence;
2789             tlen = ulen - lenPresence;
2790         }
2791         // resource uri
2792         if (resourceUri)
2793         {
2794             *resourceUri = (char *)OICMalloc(ulen + 1);
2795             if (!*resourceUri)
2796             {
2797                 result = OC_STACK_NO_MEMORY;
2798                 goto error;
2799             }
2800             strcpy(*resourceUri, slash);
2801         }
2802         // resource type
2803         if (type && resourceType)
2804         {
2805             *resourceType = (char *)OICMalloc(tlen + 1);
2806             if (!*resourceType)
2807             {
2808                 result = OC_STACK_NO_MEMORY;
2809                 goto error;
2810             }
2811
2812             OICStrcpy(*resourceType, (tlen+1), type);
2813         }
2814     }
2815
2816     return OC_STACK_OK;
2817
2818 error:
2819     // free all returned values
2820     if (devAddr)
2821     {
2822         OICFree(*devAddr);
2823     }
2824     if (resourceUri)
2825     {
2826         OICFree(*resourceUri);
2827     }
2828     if (resourceType)
2829     {
2830         OICFree(*resourceType);
2831     }
2832     return result;
2833 }
2834
2835 static OCStackResult OCPreparePresence(CAEndpoint_t *endpoint,
2836                                        char **requestUri,
2837                                        bool isMulticast)
2838 {
2839     char uri[CA_MAX_URI_LENGTH];
2840
2841     FormCanonicalPresenceUri(endpoint, uri, isMulticast);
2842
2843     *requestUri = OICStrdup(uri);
2844     if (!*requestUri)
2845     {
2846         return OC_STACK_NO_MEMORY;
2847     }
2848
2849     return OC_STACK_OK;
2850 }
2851
2852 /**
2853  * Discover or Perform requests on a specified resource
2854  */
2855 OCStackResult OCDoResource(OCDoHandle *handle,
2856                             OCMethod method,
2857                             const char *requestUri,
2858                             const OCDevAddr *destination,
2859                             OCPayload* payload,
2860                             OCConnectivityType connectivityType,
2861                             OCQualityOfService qos,
2862                             OCCallbackData *cbData,
2863                             OCHeaderOption *options,
2864                             uint8_t numOptions)
2865 {
2866     OCStackResult ret = OCDoRequest(handle, method, requestUri,destination, payload,
2867                 connectivityType, qos, cbData, options, numOptions);
2868
2869     // This is the owner of the payload object, so we free it
2870     OCPayloadDestroy(payload);
2871     return ret;
2872 }
2873
2874 /**
2875  * Discover or Perform requests on a specified resource
2876  */
2877 OCStackResult OCDoRequest(OCDoHandle *handle,
2878                             OCMethod method,
2879                             const char *requestUri,
2880                             const OCDevAddr *destination,
2881                             OCPayload* payload,
2882                             OCConnectivityType connectivityType,
2883                             OCQualityOfService qos,
2884                             OCCallbackData *cbData,
2885                             OCHeaderOption *options,
2886                             uint8_t numOptions)
2887 {
2888     OIC_LOG(INFO, TAG, "Entering OCDoResource");
2889
2890     // Validate input parameters
2891     VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
2892     VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
2893
2894     OCStackResult result = OC_STACK_ERROR;
2895     CAResult_t caResult;
2896     CAToken_t token = NULL;
2897     uint8_t tokenLength = CA_MAX_TOKEN_LEN;
2898     ClientCB *clientCB = NULL;
2899     OCDoHandle resHandle = NULL;
2900     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2901     OCDevAddr tmpDevAddr = { OC_DEFAULT_ADAPTER };
2902     uint32_t ttl = 0;
2903     OCTransportAdapter adapter;
2904     OCTransportFlags flags;
2905     // the request contents are put here
2906     CARequestInfo_t requestInfo = {.method = CA_GET};
2907     // requestUri  will be parsed into the following three variables
2908     OCDevAddr *devAddr = NULL;
2909     char *resourceUri = NULL;
2910     char *resourceType = NULL;
2911
2912     /*
2913      * Support original behavior with address on resourceUri argument.
2914      */
2915     adapter = (OCTransportAdapter)(connectivityType >> CT_ADAPTER_SHIFT);
2916     flags = (OCTransportFlags)(connectivityType & CT_MASK_FLAGS);
2917
2918     if (requestUri)
2919     {
2920         result = ParseRequestUri(requestUri, adapter, flags, &devAddr, &resourceUri, &resourceType);
2921         if (result != OC_STACK_OK)
2922         {
2923             OIC_LOG_V(DEBUG, TAG, "Unable to parse uri: %s", requestUri);
2924             goto exit;
2925         }
2926     }
2927     else if (!checkProxyUri(options, numOptions))
2928     {
2929         OIC_LOG(ERROR, TAG, "Request doesn't contain RequestURI/Proxy URI");
2930         goto exit;
2931     }
2932
2933     switch (method)
2934     {
2935     case OC_REST_GET:
2936     case OC_REST_OBSERVE:
2937     case OC_REST_OBSERVE_ALL:
2938         requestInfo.method = CA_GET;
2939         break;
2940     case OC_REST_PUT:
2941         requestInfo.method = CA_PUT;
2942         break;
2943     case OC_REST_POST:
2944         requestInfo.method = CA_POST;
2945         break;
2946     case OC_REST_DELETE:
2947         requestInfo.method = CA_DELETE;
2948         break;
2949     case OC_REST_DISCOVER:
2950         // intentional fall through don't add break
2951 #ifdef WITH_PRESENCE
2952     case OC_REST_PRESENCE:
2953 #endif
2954         if (destination || devAddr)
2955         {
2956             requestInfo.isMulticast = false;
2957         }
2958         else
2959         {
2960             tmpDevAddr.adapter = adapter;
2961             tmpDevAddr.flags = flags;
2962             destination = &tmpDevAddr;
2963             requestInfo.isMulticast = true;
2964             qos = OC_LOW_QOS;
2965         }
2966         // OC_REST_DISCOVER: CA_DISCOVER will become GET and isMulticast.
2967         // OC_REST_PRESENCE: Since "presence" is a stack layer only implementation.
2968         //                   replacing method type with GET.
2969         requestInfo.method = CA_GET;
2970         break;
2971     default:
2972         result = OC_STACK_INVALID_METHOD;
2973         goto exit;
2974     }
2975
2976     if (!devAddr && !destination)
2977     {
2978         OIC_LOG(DEBUG, TAG, "no devAddr and no destination");
2979         result = OC_STACK_INVALID_PARAM;
2980         goto exit;
2981     }
2982
2983     /* If not original behavior, use destination argument */
2984     if (destination && !devAddr)
2985     {
2986         devAddr = (OCDevAddr *)OICMalloc(sizeof (OCDevAddr));
2987         if (!devAddr)
2988         {
2989             result = OC_STACK_NO_MEMORY;
2990             goto exit;
2991         }
2992         OIC_LOG(DEBUG, TAG, "devAddr is set as destination");
2993         *devAddr = *destination;
2994     }
2995
2996     if (devAddr)
2997     {
2998         OIC_LOG_V(DEBUG, TAG, "remoteId of devAddr : %s", devAddr->remoteId);
2999     }
3000
3001     resHandle = GenerateInvocationHandle();
3002     if (!resHandle)
3003     {
3004         result = OC_STACK_NO_MEMORY;
3005         goto exit;
3006     }
3007
3008     caResult = CAGenerateToken(&token, tokenLength);
3009     if (caResult != CA_STATUS_OK)
3010     {
3011         OIC_LOG(ERROR, TAG, "CAGenerateToken error");
3012         result= OC_STACK_ERROR;
3013         goto exit;
3014     }
3015
3016     // fill in request data
3017     requestInfo.info.type = qualityOfServiceToMessageType(qos);
3018     requestInfo.info.token = token;
3019     requestInfo.info.tokenLength = tokenLength;
3020
3021     if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
3022     {
3023         result = CreateObserveHeaderOption (&(requestInfo.info.options),
3024                                     options, numOptions, OC_OBSERVE_REGISTER);
3025         if (result != OC_STACK_OK)
3026         {
3027             goto exit;
3028         }
3029         requestInfo.info.numOptions = numOptions + 1;
3030     }
3031     else
3032     {
3033         requestInfo.info.numOptions = numOptions;
3034         requestInfo.info.options =
3035             (CAHeaderOption_t*) OICCalloc(numOptions, sizeof(CAHeaderOption_t));
3036         memcpy(requestInfo.info.options, (CAHeaderOption_t*)options,
3037                numOptions * sizeof(CAHeaderOption_t));
3038     }
3039
3040     CopyDevAddrToEndpoint(devAddr, &endpoint);
3041
3042     if (payload)
3043     {
3044         if((result =
3045             OCConvertPayload(payload, &requestInfo.info.payload, &requestInfo.info.payloadSize))
3046                 != OC_STACK_OK)
3047         {
3048             OIC_LOG(ERROR, TAG, "Failed to create CBOR Payload");
3049             goto exit;
3050         }
3051
3052         uint16_t payloadVersion = OC_SPEC_VERSION_VALUE;
3053         // From OCF onwards, check version option settings
3054         if (DEFAULT_CONTENT_VERSION_VALUE <= payloadVersion)
3055         {
3056             if (numOptions > 0 && options)
3057             {
3058                 for (uint8_t i = 0; i < numOptions; i++)
3059                 {
3060                     if (COAP_OPTION_CONTENT_VERSION == options[i].optionID)
3061                     {
3062                         payloadVersion = options[i].optionData[0];
3063                         break;
3064                     }
3065                     else if (COAP_OPTION_ACCEPT_VERSION == options[i].optionID)
3066                     {
3067                         payloadVersion = options[i].optionData[0];
3068                         break;
3069                     }
3070                 }
3071             }
3072         }
3073
3074         if (DEFAULT_CONTENT_VERSION_VALUE <= payloadVersion)
3075         {
3076             requestInfo.info.payloadFormat = CA_FORMAT_APPLICATION_VND_OCF_CBOR;
3077             requestInfo.info.payloadVersion = payloadVersion;
3078         }
3079         else
3080         {
3081             requestInfo.info.payloadFormat = CA_FORMAT_APPLICATION_CBOR;
3082         }
3083     }
3084     else
3085     {
3086         requestInfo.info.payload = NULL;
3087         requestInfo.info.payloadSize = 0;
3088         requestInfo.info.payloadFormat = CA_FORMAT_UNDEFINED;
3089     }
3090
3091     // prepare for response
3092 #ifdef WITH_PRESENCE
3093     if (method == OC_REST_PRESENCE)
3094     {
3095         char *presenceUri = NULL;
3096         result = OCPreparePresence(&endpoint, &presenceUri,
3097                                    requestInfo.isMulticast);
3098         if (OC_STACK_OK != result)
3099         {
3100             goto exit;
3101         }
3102
3103         // Assign full presence uri as coap://ip:port/oic/ad to add to callback list.
3104         // Presence notification will form a canonical uri to
3105         // look for callbacks into the application.
3106         if (resourceUri)
3107         {
3108             OICFree(resourceUri);
3109         }
3110         resourceUri = presenceUri;
3111     }
3112 #endif
3113
3114     // update resourceUri onto requestInfo after check presence uri
3115     requestInfo.info.resourceUri = resourceUri;
3116
3117     ttl = GetTicks(MAX_CB_TIMEOUT_SECONDS * MILLISECONDS_PER_SECOND);
3118     result = AddClientCB(&clientCB, cbData, token, tokenLength, &resHandle,
3119                             method, devAddr, resourceUri, resourceType, ttl);
3120     if (OC_STACK_OK != result)
3121     {
3122         goto exit;
3123     }
3124
3125     devAddr = NULL;       // Client CB list entry now owns it
3126     resourceUri = NULL;   // Client CB list entry now owns it
3127     resourceType = NULL;  // Client CB list entry now owns it
3128
3129 #ifdef WITH_PRESENCE
3130     if (method == OC_REST_PRESENCE)
3131     {
3132         OIC_LOG(ERROR, TAG, "AddClientCB for presence done.");
3133
3134         if (handle)
3135         {
3136             *handle = resHandle;
3137         }
3138
3139         goto exit;
3140     }
3141 #endif
3142
3143     // send request
3144     result = OCSendRequest(&endpoint, &requestInfo);
3145     if (OC_STACK_OK != result)
3146     {
3147         goto exit;
3148     }
3149
3150     if (handle)
3151     {
3152         *handle = resHandle;
3153     }
3154
3155 exit:
3156     if (result != OC_STACK_OK)
3157     {
3158         OIC_LOG(ERROR, TAG, "OCDoResource error");
3159         FindAndDeleteClientCB(clientCB);
3160         CADestroyToken(token);
3161         if (handle)
3162         {
3163             *handle = NULL;
3164         }
3165         OICFree(resHandle);
3166     }
3167
3168     OICFree(requestInfo.info.payload);
3169     OICFree(devAddr);
3170     OICFree(resourceUri);
3171     OICFree(resourceType);
3172     OICFree(requestInfo.info.options);
3173     return result;
3174 }
3175
3176 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
3177         uint8_t numOptions)
3178 {
3179     /*
3180      * This ftn is implemented one of two ways in the case of observation:
3181      *
3182      * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
3183      *      Remove the callback associated on client side.
3184      *      When the next notification comes in from server,
3185      *      reply with RESET message to server.
3186      *      Keep in mind that the server will react to RESET only
3187      *      if the last notification was sent as CON
3188      *
3189      * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
3190      *      and it is associated with an observe request
3191      *      (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
3192      *      Send CON Observe request to server with
3193      *      observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
3194      *      Remove the callback associated on client side.
3195      */
3196     OCStackResult ret = OC_STACK_OK;
3197     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
3198     CARequestInfo_t requestInfo = {.method = CA_GET};
3199
3200     if(!handle)
3201     {
3202         return OC_STACK_INVALID_PARAM;
3203     }
3204
3205     ClientCB *clientCB = GetClientCB(NULL, 0, handle, NULL);
3206     if (!clientCB)
3207     {
3208         OIC_LOG(ERROR, TAG, "Callback not found. Called OCCancel on same resource twice?");
3209         return OC_STACK_ERROR;
3210     }
3211
3212     switch (clientCB->method)
3213     {
3214         case OC_REST_OBSERVE:
3215         case OC_REST_OBSERVE_ALL:
3216
3217             OIC_LOG_V(INFO, TAG, "Canceling observation for resource %s", clientCB->requestUri);
3218
3219             CopyDevAddrToEndpoint(clientCB->devAddr, &endpoint);
3220
3221             if ((endpoint.adapter & CA_ADAPTER_IP) && qos != OC_HIGH_QOS)
3222             {
3223                 FindAndDeleteClientCB(clientCB);
3224                 break;
3225             }
3226
3227             OIC_LOG(INFO, TAG, "Cancelling observation as CONFIRMABLE");
3228
3229             requestInfo.info.type = qualityOfServiceToMessageType(qos);
3230             requestInfo.info.token = clientCB->token;
3231             requestInfo.info.tokenLength = clientCB->tokenLength;
3232
3233             if (CreateObserveHeaderOption (&(requestInfo.info.options),
3234                     options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
3235             {
3236                 return OC_STACK_ERROR;
3237             }
3238             requestInfo.info.numOptions = numOptions + 1;
3239             requestInfo.info.resourceUri = OICStrdup (clientCB->requestUri);
3240
3241
3242             ret = OCSendRequest(&endpoint, &requestInfo);
3243
3244             if (requestInfo.info.options)
3245             {
3246                 OICFree (requestInfo.info.options);
3247             }
3248             if (requestInfo.info.resourceUri)
3249             {
3250                 OICFree (requestInfo.info.resourceUri);
3251             }
3252
3253             break;
3254
3255         case OC_REST_DISCOVER:
3256             OIC_LOG_V(INFO, TAG, "Cancelling discovery callback for resource %s",
3257                                            clientCB->requestUri);
3258             FindAndDeleteClientCB(clientCB);
3259             break;
3260
3261 #ifdef WITH_PRESENCE
3262         case OC_REST_PRESENCE:
3263             FindAndDeleteClientCB(clientCB);
3264             break;
3265 #endif
3266
3267         default:
3268             ret = OC_STACK_INVALID_METHOD;
3269             break;
3270     }
3271
3272     return ret;
3273 }
3274
3275 /**
3276  * @brief   Register Persistent storage callback.
3277  * @param   persistentStorageHandler [IN] Pointers to open, read, write, close & unlink handlers.
3278  * @return
3279  *     OC_STACK_OK    - No errors; Success
3280  *     OC_STACK_INVALID_PARAM - Invalid parameter
3281  */
3282 OCStackResult OCRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
3283 {
3284     OIC_LOG(INFO, TAG, "RegisterPersistentStorageHandler !!");
3285     if(!persistentStorageHandler)
3286     {
3287         OIC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
3288         return OC_STACK_INVALID_PARAM;
3289     }
3290     else
3291     {
3292         if( !persistentStorageHandler->open ||
3293                 !persistentStorageHandler->close ||
3294                 !persistentStorageHandler->read ||
3295                 !persistentStorageHandler->unlink ||