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