IOT-2258: Allow secure and nonsecure endpoints with OCCreateResource.
[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                 }
1608                 else
1609                 {
1610                     requestData.options = (CAHeaderOption_t *) OICCalloc(cbNode->numOptions,
1611                             sizeof(CAHeaderOption_t));
1612                     if (!requestData.options)
1613                     {
1614                         OIC_LOG(ERROR, TAG, "Out of memory");
1615                         OICFree(requestData.token);
1616                         goto proceed;
1617                     }
1618                     memcpy(requestData.options, cbNode->options,
1619                             sizeof(CAHeaderOption_t) * cbNode->numOptions);
1620
1621                     requestData.numOptions = cbNode->numOptions;
1622                 }
1623                 if (!cbNode->payload || !cbNode->payloadSize)
1624                 {
1625                     OIC_LOG (INFO, TAG, "No payload present in cbNode");
1626                 }
1627                 else
1628                 {
1629                     requestData.payload = (CAPayload_t) OICCalloc(1, cbNode->payloadSize);
1630                     if (!requestData.payload)
1631                     {
1632                         OIC_LOG(ERROR, TAG, "out of memory");
1633                         OICFree(requestData.token);
1634                         OICFree(requestData.options);
1635                         goto proceed;
1636                     }
1637                     memcpy(requestData.payload, cbNode->payload, cbNode->payloadSize);
1638                     requestData.payloadSize = cbNode->payloadSize;
1639                 }
1640                 requestData.payloadFormat = CA_FORMAT_APPLICATION_CBOR;
1641                 requestData.acceptFormat = CA_FORMAT_APPLICATION_CBOR; //?
1642                 requestData.resourceUri = OICStrdup(cbNode->requestUri);
1643
1644                 requestInfo.info = requestData;
1645  
1646                 // send request
1647                 OCStackResult result = OCSendRequest(endPoint, &requestInfo);
1648                 if (OC_STACK_OK == result)
1649                 {
1650                     return;
1651                 }
1652                 else
1653                 {
1654                     OIC_LOG(ERROR, TAG, "Re-send request failed");
1655                     OICFree(requestData.token);
1656                     OICFree(requestData.options);
1657                     OICFree(requestData.payload);
1658                 }
1659             }
1660
1661         proceed:;
1662             OCClientResponse *response = (OCClientResponse *) OICCalloc(1, sizeof(*response));
1663             if (!response)
1664             {
1665                 OIC_LOG(ERROR, TAG, "Allocating memory for response failed");
1666                 return;
1667             }
1668
1669             response->devAddr.adapter = OC_DEFAULT_ADAPTER;
1670             CopyEndpointToDevAddr(endPoint, &response->devAddr);
1671             FixUpClientResponse(response);
1672             response->resourceUri = responseInfo->info.resourceUri;
1673             memcpy(response->identity.id, responseInfo->info.identity.id,
1674                     sizeof(response->identity.id));
1675             response->identity.id_length = responseInfo->info.identity.id_length;
1676
1677             response->result = CAResponseToOCStackResult(responseInfo->result);
1678             cbNode->callBack(cbNode->context,
1679                     cbNode->handle, response);
1680             FindAndDeleteClientCB(cbNode);
1681             OICFree(response);
1682         }
1683         else if ((cbNode->method == OC_REST_OBSERVE || cbNode->method == OC_REST_OBSERVE_ALL)
1684                 && (responseInfo->result == CA_CONTENT) && !obsHeaderOpt)
1685         {
1686             OCClientResponse *response = NULL;
1687
1688             response = (OCClientResponse *)OICCalloc(1, sizeof(*response));
1689             if (!response)
1690             {
1691                 OIC_LOG(ERROR, TAG, "Allocating memory for response failed");
1692                 return;
1693             }
1694
1695             response->devAddr.adapter = OC_DEFAULT_ADAPTER;
1696             response->sequenceNumber = MAX_SEQUENCE_NUMBER + 1;
1697             CopyEndpointToDevAddr(endPoint, &response->devAddr);
1698             FixUpClientResponse(response);
1699             response->resourceUri = responseInfo->info.resourceUri;
1700             memcpy(response->identity.id, responseInfo->info.identity.id,
1701                                     sizeof (response->identity.id));
1702             response->identity.id_length = responseInfo->info.identity.id_length;
1703             response->result = OC_STACK_OK;
1704
1705             OIC_LOG(DEBUG, TAG, "This is response of observer cancel or observer request fail");
1706
1707             cbNode->callBack(cbNode->context,
1708                              cbNode->handle,
1709                              response);
1710             FindAndDeleteClientCB(cbNode);
1711             OICFree(response);
1712         }
1713         else
1714         {
1715             OIC_LOG(INFO, TAG, "This is a regular response, A client call back is found");
1716             OIC_LOG(INFO, TAG, "Calling into application address space");
1717
1718             OCClientResponse *response = NULL;
1719             OCPayloadType type = PAYLOAD_TYPE_INVALID;
1720
1721             response = (OCClientResponse *)OICCalloc(1, sizeof(*response));
1722             if (!response)
1723             {
1724                 OIC_LOG(ERROR, TAG, "Allocating memory for response failed");
1725                 return;
1726             }
1727
1728             response->devAddr.adapter = OC_DEFAULT_ADAPTER;
1729             response->sequenceNumber = MAX_SEQUENCE_NUMBER + 1;
1730             CopyEndpointToDevAddr(endPoint, &response->devAddr);
1731             FixUpClientResponse(response);
1732             response->resourceUri = responseInfo->info.resourceUri;
1733             memcpy(response->identity.id, responseInfo->info.identity.id,
1734                                                 sizeof (response->identity.id));
1735             response->identity.id_length = responseInfo->info.identity.id_length;
1736
1737             response->result = CAResponseToOCStackResult(responseInfo->result);
1738
1739             if(responseInfo->info.payload &&
1740                responseInfo->info.payloadSize)
1741             {
1742                 // check the security resource
1743                 if (SRMIsSecurityResourceURI(cbNode->requestUri))
1744                 {
1745                     type = PAYLOAD_TYPE_SECURITY;
1746                 }
1747                 else if (cbNode->method == OC_REST_DISCOVER)
1748                 {
1749                     if (strncmp(OC_RSRVD_WELL_KNOWN_URI,cbNode->requestUri,
1750                                 sizeof(OC_RSRVD_WELL_KNOWN_URI) - 1) == 0)
1751                     {
1752                         type = PAYLOAD_TYPE_DISCOVERY;
1753                     }
1754 #ifdef WITH_MQ
1755                     else if (strcmp(cbNode->requestUri, OC_RSRVD_WELL_KNOWN_MQ_URI) == 0)
1756                     {
1757                         type = PAYLOAD_TYPE_DISCOVERY;
1758                     }
1759 #endif
1760                     else if (strcmp(cbNode->requestUri, OC_RSRVD_DEVICE_URI) == 0)
1761                     {
1762                         type = PAYLOAD_TYPE_REPRESENTATION;
1763                     }
1764                     else if (strcmp(cbNode->requestUri, OC_RSRVD_PLATFORM_URI) == 0)
1765                     {
1766                         type = PAYLOAD_TYPE_REPRESENTATION;
1767                     }
1768 #ifdef ROUTING_GATEWAY
1769                     else if (strcmp(cbNode->requestUri, OC_RSRVD_GATEWAY_URI) == 0)
1770                     {
1771                         type = PAYLOAD_TYPE_REPRESENTATION;
1772                     }
1773 #endif
1774                     else if (strcmp(cbNode->requestUri, OC_RSRVD_RD_URI) == 0)
1775                     {
1776                         type = PAYLOAD_TYPE_REPRESENTATION;
1777                     }
1778 #ifdef TCP_ADAPTER
1779                     else if (strcmp(cbNode->requestUri, OC_RSRVD_KEEPALIVE_URI) == 0)
1780                     {
1781                         type = PAYLOAD_TYPE_REPRESENTATION;
1782                     }
1783 #endif
1784                     else
1785                     {
1786                         OIC_LOG_V(ERROR, TAG, "Unknown Payload type in Discovery: %d %s",
1787                                 cbNode->method, cbNode->requestUri);
1788                         OICFree(response);
1789                         return;
1790                     }
1791                 }
1792                 else if (cbNode->method == OC_REST_GET ||
1793                          cbNode->method == OC_REST_PUT ||
1794                          cbNode->method == OC_REST_POST ||
1795                          cbNode->method == OC_REST_OBSERVE ||
1796                          cbNode->method == OC_REST_OBSERVE_ALL ||
1797                          cbNode->method == OC_REST_DELETE)
1798                 {
1799                     if (cbNode->requestUri)
1800                     {
1801                         if (0 == strcmp(OC_RSRVD_PLATFORM_URI, cbNode->requestUri))
1802                         {
1803                             type = PAYLOAD_TYPE_REPRESENTATION;
1804                         }
1805                         else if (0 == strcmp(OC_RSRVD_DEVICE_URI, cbNode->requestUri))
1806                         {
1807                             type = PAYLOAD_TYPE_REPRESENTATION;
1808                         }
1809                         if (type == PAYLOAD_TYPE_INVALID)
1810                         {
1811                             if (responseInfo->info.payloadFormat == CA_FORMAT_UNDEFINED)
1812                             {
1813                                 OIC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_DIAGNOSTIC: %d %s",
1814                                         cbNode->method, cbNode->requestUri);
1815                                 type = PAYLOAD_TYPE_DIAGNOSTIC;
1816                             }
1817                             else
1818                             {
1819                                 OIC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_REPRESENTATION: %d %s",
1820                                         cbNode->method, cbNode->requestUri);
1821                                 type = PAYLOAD_TYPE_REPRESENTATION;
1822                             }
1823                         }
1824                     }
1825                     else
1826                     {
1827                         OIC_LOG(INFO, TAG, "No Request URI, PROXY URI");
1828                         type = PAYLOAD_TYPE_REPRESENTATION;
1829                     }
1830                 }
1831                 else
1832                 {
1833                     OIC_LOG_V(ERROR, TAG, "Unknown Payload type: %d %s",
1834                             cbNode->method, cbNode->requestUri);
1835                     OICFree(response);
1836                     return;
1837                 }
1838
1839                 // In case of error, still want application to receive the error message.
1840                 if (OCResultToSuccess(response->result) || PAYLOAD_TYPE_REPRESENTATION == type ||
1841                         PAYLOAD_TYPE_DIAGNOSTIC == type)
1842                 {
1843                     if (OC_STACK_OK != OCParsePayload(&response->payload,
1844                             CAToOCPayloadFormat(responseInfo->info.payloadFormat),
1845                             type,
1846                             responseInfo->info.payload,
1847                             responseInfo->info.payloadSize))
1848                     {
1849                         OIC_LOG(ERROR, TAG, "Error converting payload");
1850                         OCPayloadDestroy(response->payload);
1851                         OICFree(response);
1852                         return;
1853                     }
1854
1855                     // Check endpoints has link-local ipv6 address.
1856                     // if there is, map zone-id which parsed from ifindex
1857 #if defined (IP_ADAPTER) && !defined (WITH_ARDUINO)
1858                     if (PAYLOAD_TYPE_DISCOVERY == response->payload->type)
1859                     {
1860                         OCDiscoveryPayload *disPayload = (OCDiscoveryPayload*)(response->payload);
1861                         if (OC_STACK_OK !=
1862                             OCMapZoneIdToLinkLocalEndpoint(disPayload, response->devAddr.ifindex))
1863                         {
1864                             OIC_LOG(ERROR, TAG, "failed at map zone-id for link-local address");
1865                             OCPayloadDestroy(response->payload);
1866                             OICFree(response);
1867                             return;
1868                         }
1869                     }
1870 #endif
1871                 }
1872                 else
1873                 {
1874                     response->resourceUri = OICStrdup(cbNode->requestUri);
1875                 }
1876             }
1877
1878             response->numRcvdVendorSpecificHeaderOptions = 0;
1879             if((responseInfo->info.numOptions > 0) && (responseInfo->info.options != NULL))
1880             {
1881                 uint8_t start = 0;
1882                 //First option always with option ID is COAP_OPTION_OBSERVE if it is available.
1883                 if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
1884                 {
1885                     size_t i;
1886                     uint32_t observationOption;
1887                     uint8_t* optionData = (uint8_t*)responseInfo->info.options[0].optionData;
1888                     for (observationOption=0, i=0;
1889                             i<sizeof(uint32_t) && i<responseInfo->info.options[0].optionLength;
1890                             i++)
1891                     {
1892                         observationOption =
1893                             (observationOption << 8) | optionData[i];
1894                     }
1895                     response->sequenceNumber = observationOption;
1896                     response->numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions - 1;
1897                     start = 1;
1898                 }
1899                 else
1900                 {
1901                     response->numRcvdVendorSpecificHeaderOptions = responseInfo->info.numOptions;
1902                 }
1903
1904                 if(response->numRcvdVendorSpecificHeaderOptions > MAX_HEADER_OPTIONS)
1905                 {
1906                     OIC_LOG(ERROR, TAG, "#header options are more than MAX_HEADER_OPTIONS");
1907                     OCPayloadDestroy(response->payload);
1908                     OICFree(response);
1909                     return;
1910                 }
1911
1912                 for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
1913                 {
1914                     memcpy (&(response->rcvdVendorSpecificHeaderOptions[i - start]),
1915                             &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
1916                 }
1917             }
1918
1919             if (cbNode->method == OC_REST_OBSERVE &&
1920                 response->sequenceNumber > OC_OFFSET_SEQUENCE_NUMBER &&
1921                 cbNode->sequenceNumber <=  MAX_SEQUENCE_NUMBER &&
1922                 response->sequenceNumber <= cbNode->sequenceNumber)
1923             {
1924                 OIC_LOG_V(INFO, TAG, "Received stale notification. Number :%d",
1925                                                  response->sequenceNumber);
1926             }
1927             else
1928             {
1929 #ifdef RD_CLIENT
1930                 if (cbNode->requestUri)
1931                 {
1932                     // if request uri is '/oic/rd', update ins value of resource.
1933                     char *targetUri = strstr(cbNode->requestUri, OC_RSRVD_RD_URI);
1934                     if (targetUri)
1935                     {
1936                         OCUpdateResourceInsWithResponse(cbNode->requestUri, response);
1937                     }
1938                 }
1939 #endif
1940                 // set remoteID(device ID) into OCClientResponse callback parameter
1941                 if (OC_REST_DISCOVER == cbNode->method && PAYLOAD_TYPE_DISCOVERY == type)
1942                 {
1943                     OCDiscoveryPayload *payload = (OCDiscoveryPayload*) response->payload;
1944                     // Payload can be empty in case of error message.
1945                     if (payload && payload->sid)
1946                     {
1947                         OICStrcpy(response->devAddr.remoteId, sizeof(response->devAddr.remoteId),
1948                                   payload->sid);
1949                         OIC_LOG_V(INFO, TAG, "Device ID of response : %s",
1950                                   response->devAddr.remoteId);
1951
1952 #if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
1953                         CAConnectUserPref_t connPrefer = CA_USER_PREF_CLOUD;
1954                         CAResult_t ret = CAUtilCMGetConnectionUserConfig(&connPrefer);
1955                         if (ret == CA_STATUS_OK && connPrefer != CA_USER_PREF_CLOUD)
1956                         {
1957                             OCCMDiscoveryResource(response);
1958                         }
1959 #endif
1960                     }
1961                 }
1962                 if (response->payload && response->payload->type == PAYLOAD_TYPE_REPRESENTATION)
1963                 {
1964                     HandleBatchResponse(cbNode->requestUri, (OCRepPayload **)&response->payload);
1965                 }
1966
1967                 OCStackApplicationResult appFeedback = cbNode->callBack(cbNode->context,
1968                                                                         cbNode->handle,
1969                                                                         response);
1970                 cbNode->sequenceNumber = response->sequenceNumber;
1971
1972                 if (appFeedback == OC_STACK_DELETE_TRANSACTION)
1973                 {
1974                     FindAndDeleteClientCB(cbNode);
1975                 }
1976                 else
1977                 {
1978                     // To keep discovery callbacks active.
1979                     cbNode->TTL = GetTicks(MAX_CB_TIMEOUT_SECONDS *
1980                                             MILLISECONDS_PER_SECOND);
1981                 }
1982             }
1983
1984             //Need to send ACK when the response is CON
1985             if(responseInfo->info.type == CA_MSG_CONFIRM)
1986             {
1987                 SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY,
1988                         CA_MSG_ACKNOWLEDGE, 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
1989             }
1990
1991             OCPayloadDestroy(response->payload);
1992             OICFree(response);
1993         }
1994         return;
1995     }
1996
1997     if(observer)
1998     {
1999         OIC_LOG(INFO, TAG, "There is an observer associated with the response token");
2000         if(responseInfo->result == CA_EMPTY)
2001         {
2002             OIC_LOG(INFO, TAG, "Receiving A ACK/RESET for this token");
2003             if(responseInfo->info.type == CA_MSG_RESET)
2004             {
2005                 OIC_LOG(INFO, TAG, "This is a RESET");
2006                 OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
2007                         OC_OBSERVER_NOT_INTERESTED);
2008             }
2009             else if(responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
2010             {
2011                 OIC_LOG(INFO, TAG, "This is a pure ACK");
2012                 OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
2013                         OC_OBSERVER_STILL_INTERESTED);
2014             }
2015         }
2016         else if(responseInfo->result == CA_RETRANSMIT_TIMEOUT)
2017         {
2018             OIC_LOG(INFO, TAG, "Receiving Time Out for an observer");
2019             OCStackFeedBack(responseInfo->info.token, responseInfo->info.tokenLength,
2020                     OC_OBSERVER_FAILED_COMM);
2021         }
2022         return;
2023     }
2024
2025     if(!cbNode && !observer)
2026     {
2027         if(myStackMode == OC_CLIENT || myStackMode == OC_CLIENT_SERVER
2028            || myStackMode == OC_GATEWAY)
2029         {
2030             OIC_LOG(INFO, TAG, "This is a client, but no cbNode was found for token");
2031             if(responseInfo->result == CA_EMPTY)
2032             {
2033                 OIC_LOG(INFO, TAG, "Receiving CA_EMPTY in the ocstack");
2034             }
2035             else
2036             {
2037                 OIC_LOG(INFO, TAG, "Received a message without callbacks. Sending RESET");
2038                 SendDirectStackResponse(endPoint, responseInfo->info.messageId, CA_EMPTY,
2039                                         CA_MSG_RESET, 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
2040             }
2041         }
2042
2043         if(myStackMode == OC_SERVER || myStackMode == OC_CLIENT_SERVER
2044            || myStackMode == OC_GATEWAY)
2045         {
2046             OIC_LOG(INFO, TAG, "This is a server, but no observer was found for token");
2047             if (responseInfo->info.type == CA_MSG_ACKNOWLEDGE)
2048             {
2049                 OIC_LOG_V(INFO, TAG, "Received ACK at server for messageId : %d",
2050                                             responseInfo->info.messageId);
2051             }
2052             if (responseInfo->info.type == CA_MSG_RESET)
2053             {
2054                 OIC_LOG_V(INFO, TAG, "Received RESET at server for messageId : %d",
2055                                             responseInfo->info.messageId);
2056             }
2057         }
2058
2059         return;
2060     }
2061 }
2062
2063 void HandleCAResponses(const CAEndpoint_t* endPoint, const CAResponseInfo_t* responseInfo)
2064 {
2065     VERIFY_NON_NULL_NR(endPoint, FATAL);
2066     VERIFY_NON_NULL_NR(responseInfo, FATAL);
2067
2068     OIC_LOG(INFO, TAG, "Enter HandleCAResponses");
2069     OIC_TRACE_BEGIN(%s:HandleCAResponses, TAG);
2070 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
2071 #ifdef ROUTING_GATEWAY
2072     bool needRIHandling = false;
2073     /*
2074      * Routing manager is going to update either of endpoint or response or both.
2075      * This typecasting is done to avoid unnecessary duplication of Endpoint and responseInfo
2076      * RM can update "routeData" option in endPoint so that future RI requests can be sent to proper
2077      * destination.
2078      */
2079     OCStackResult ret = RMHandleResponse((CAResponseInfo_t *)responseInfo, (CAEndpoint_t *)endPoint,
2080                                          &needRIHandling);
2081     if(ret != OC_STACK_OK || !needRIHandling)
2082     {
2083         OIC_LOG_V(INFO, TAG, "Routing status![%d]. Not forwarding to RI", ret);
2084         OIC_TRACE_END();
2085         return;
2086     }
2087 #endif
2088
2089     /*
2090      * Put source in sender endpoint so that the next packet from application can be routed to
2091      * proper destination and remove "RM" coap header option before passing request / response to
2092      * RI as this option will make no sense to either RI or application.
2093      */
2094     RMUpdateInfo((CAHeaderOption_t **) &(responseInfo->info.options),
2095         (uint8_t *) &(responseInfo->info.numOptions),
2096         (CAEndpoint_t *)endPoint);
2097 #endif
2098
2099     OCHandleResponse(endPoint, responseInfo);
2100
2101     OIC_LOG(INFO, TAG, "Exit HandleCAResponses");
2102     OIC_TRACE_END();
2103 }
2104
2105 /*
2106  * This function handles error response from CA
2107  * code shall be added to handle the errors
2108  */
2109 void HandleCAErrorResponse(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo)
2110 {
2111     VERIFY_NON_NULL_NR(endPoint, FATAL);
2112     VERIFY_NON_NULL_NR(errorInfo, FATAL);
2113
2114     OIC_LOG(INFO, TAG, "Enter HandleCAErrorResponse");
2115     OIC_TRACE_BEGIN(%s:HandleCAErrorResponse, TAG);
2116
2117     ClientCB *cbNode = GetClientCB(errorInfo->info.token,
2118                                    errorInfo->info.tokenLength, NULL, NULL);
2119     if (cbNode)
2120     {
2121         OCClientResponse *response = NULL;
2122
2123         response = (OCClientResponse *)OICCalloc(1, sizeof(*response));
2124         if (!response)
2125         {
2126             OIC_LOG(ERROR, TAG, "Allocating memory for response failed");
2127             OIC_TRACE_END();
2128             return;
2129         }
2130
2131         response->devAddr.adapter = OC_DEFAULT_ADAPTER;
2132         CopyEndpointToDevAddr(endPoint, &response->devAddr);
2133         FixUpClientResponse(response);
2134         response->resourceUri = errorInfo->info.resourceUri;
2135         memcpy(response->identity.id, errorInfo->info.identity.id,
2136                sizeof (response->identity.id));
2137         response->identity.id_length = errorInfo->info.identity.id_length;
2138         response->result = CAResultToOCResult(errorInfo->result);
2139
2140         cbNode->callBack(cbNode->context, cbNode->handle, response);
2141         OICFree(response);
2142     }
2143
2144     ResourceObserver *observer = GetObserverUsingToken(errorInfo->info.token,
2145                                                        errorInfo->info.tokenLength);
2146     if (observer)
2147     {
2148         OIC_LOG(INFO, TAG, "Receiving communication error for an observer");
2149         OCStackResult result = CAResultToOCResult(errorInfo->result);
2150         if (OC_STACK_COMM_ERROR == result)
2151         {
2152             OCStackFeedBack(errorInfo->info.token, errorInfo->info.tokenLength,
2153                             OC_OBSERVER_FAILED_COMM);
2154         }
2155     }
2156
2157     OIC_LOG(INFO, TAG, "Exit HandleCAErrorResponse");
2158     OIC_TRACE_END();
2159 }
2160
2161 /*
2162  * This function sends out Direct Stack Responses. These are responses that are not coming
2163  * from the application entity handler. These responses have no payload and are usually ACKs,
2164  * RESETs or some error conditions that were caught by the stack.
2165  */
2166 OCStackResult SendDirectStackResponse(const CAEndpoint_t* endPoint, const uint16_t coapID,
2167         const CAResponseResult_t responseResult, const CAMessageType_t type,
2168         const uint8_t numOptions, const CAHeaderOption_t *options,
2169         CAToken_t token, uint8_t tokenLength, const char *resourceUri,
2170         CADataType_t dataType)
2171 {
2172     OIC_LOG(DEBUG, TAG, "Entering SendDirectStackResponse");
2173     CAResponseInfo_t respInfo = {
2174         .result = responseResult
2175     };
2176     respInfo.info.messageId = coapID;
2177     respInfo.info.numOptions = numOptions;
2178
2179     if (respInfo.info.numOptions)
2180     {
2181         respInfo.info.options =
2182             (CAHeaderOption_t *)OICCalloc(respInfo.info.numOptions, sizeof(CAHeaderOption_t));
2183         if (NULL == respInfo.info.options)
2184         {
2185             OIC_LOG(ERROR, TAG, "Calloc failed");
2186             return OC_STACK_NO_MEMORY;
2187         }
2188         memcpy (respInfo.info.options, options,
2189                 sizeof(CAHeaderOption_t) * respInfo.info.numOptions);
2190
2191     }
2192
2193     respInfo.info.payload = NULL;
2194     respInfo.info.token = token;
2195     respInfo.info.tokenLength = tokenLength;
2196     respInfo.info.type = type;
2197     respInfo.info.resourceUri = OICStrdup (resourceUri);
2198     respInfo.info.acceptFormat = CA_FORMAT_UNDEFINED;
2199     respInfo.info.dataType = dataType;
2200
2201 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
2202     // Add the destination to route option from the endpoint->routeData.
2203     bool doPost = false;
2204     OCStackResult result = RMAddInfo(endPoint->routeData, &respInfo, false, &doPost);
2205     if(OC_STACK_OK != result)
2206     {
2207         OIC_LOG_V(ERROR, TAG, "Add routing option failed [%d]", result);
2208         OICFree (respInfo.info.resourceUri);
2209         OICFree (respInfo.info.options);
2210         return result;
2211     }
2212     if (doPost)
2213     {
2214         OIC_LOG(DEBUG, TAG, "Sending a POST message for EMPTY ACK in Client Mode");
2215         CARequestInfo_t reqInfo = {.method = CA_POST };
2216         /* The following initialization is not done in a single initializer block as in
2217          * arduino, .c file is compiled as .cpp and moves it from C99 to C++11.  The latter
2218          * does not have designated initalizers. This is a work-around for now.
2219          */
2220         reqInfo.info.type = CA_MSG_NONCONFIRM;
2221         reqInfo.info.messageId = coapID;
2222         reqInfo.info.tokenLength = tokenLength;
2223         reqInfo.info.token = token;
2224         reqInfo.info.numOptions = respInfo.info.numOptions;
2225         reqInfo.info.payload = NULL;
2226         reqInfo.info.resourceUri = OICStrdup (OC_RSRVD_GATEWAY_URI);
2227         if (reqInfo.info.numOptions)
2228         {
2229             reqInfo.info.options =
2230                 (CAHeaderOption_t *)OICCalloc(reqInfo.info.numOptions, sizeof(CAHeaderOption_t));
2231             if (NULL == reqInfo.info.options)
2232             {
2233                 OIC_LOG(ERROR, TAG, "Calloc failed");
2234                 OICFree (reqInfo.info.resourceUri);
2235                 OICFree (respInfo.info.resourceUri);
2236                 OICFree (respInfo.info.options);
2237                 return OC_STACK_NO_MEMORY;
2238             }
2239             memcpy (reqInfo.info.options, respInfo.info.options,
2240                     sizeof(CAHeaderOption_t) * reqInfo.info.numOptions);
2241
2242         }
2243         CAResult_t caResult = CASendRequest(endPoint, &reqInfo);
2244         OICFree (reqInfo.info.resourceUri);
2245         OICFree (reqInfo.info.options);
2246         OICFree (respInfo.info.resourceUri);
2247         OICFree (respInfo.info.options);
2248         if (CA_STATUS_OK != caResult)
2249         {
2250             OIC_LOG(ERROR, TAG, "CASendRequest error");
2251             return CAResultToOCResult(caResult);
2252         }
2253     }
2254     else
2255 #endif
2256     {
2257         CAResult_t caResult = CASendResponse(endPoint, &respInfo);
2258
2259         // resourceUri in the info field is cloned in the CA layer and
2260         // thus ownership is still here.
2261         OICFree (respInfo.info.resourceUri);
2262         OICFree (respInfo.info.options);
2263         if(CA_STATUS_OK != caResult)
2264         {
2265             OIC_LOG(ERROR, TAG, "CASendResponse error");
2266             return CAResultToOCResult(caResult);
2267         }
2268     }
2269     OIC_LOG(DEBUG, TAG, "Exit SendDirectStackResponse");
2270     return OC_STACK_OK;
2271 }
2272
2273 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
2274 {
2275     OIC_LOG(INFO, TAG, "Entering HandleStackRequests (OCStack Layer)");
2276     OCStackResult result = OC_STACK_ERROR;
2277     if (!protocolRequest)
2278     {
2279         OIC_LOG(ERROR, TAG, "protocolRequest is NULL");
2280         return OC_STACK_INVALID_PARAM;
2281     }
2282
2283     OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken,
2284             protocolRequest->tokenLength);
2285     if (!request)
2286     {
2287         OIC_LOG(INFO, TAG, "This is a new Server Request");
2288         result = AddServerRequest(&request, protocolRequest->coapID,
2289                 protocolRequest->delayedResNeeded, 0, protocolRequest->method,
2290                 protocolRequest->numRcvdVendorSpecificHeaderOptions,
2291                 protocolRequest->observationOption, protocolRequest->qos,
2292                 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
2293                 protocolRequest->payloadFormat, protocolRequest->payload,
2294                 protocolRequest->requestToken, protocolRequest->tokenLength,
2295                 protocolRequest->resourceUrl, protocolRequest->reqTotalSize,
2296                 protocolRequest->acceptFormat, protocolRequest->acceptVersion,
2297                 &protocolRequest->devAddr);
2298         if (OC_STACK_OK != result)
2299         {
2300             OIC_LOG(ERROR, TAG, "Error adding server request");
2301             return result;
2302         }
2303
2304         if(!request)
2305         {
2306             OIC_LOG(ERROR, TAG, "Out of Memory");
2307             return OC_STACK_NO_MEMORY;
2308         }
2309
2310         if(!protocolRequest->reqMorePacket)
2311         {
2312             request->requestComplete = 1;
2313         }
2314     }
2315     else
2316     {
2317         OIC_LOG(INFO, TAG, "This is either a repeated or blocked Server Request");
2318     }
2319
2320     if (request->requestComplete)
2321     {
2322         OIC_LOG(INFO, TAG, "This Server Request is complete");
2323         ResourceHandling resHandling = OC_RESOURCE_VIRTUAL;
2324         OCResource *resource = NULL;
2325         result = DetermineResourceHandling (request, &resHandling, &resource);
2326         if (result == OC_STACK_OK)
2327         {
2328             result = ProcessRequest(resHandling, resource, request);
2329         }
2330     }
2331     else
2332     {
2333         OIC_LOG(INFO, TAG, "This Server Request is incomplete");
2334         result = OC_STACK_CONTINUE;
2335     }
2336     return result;
2337 }
2338
2339 void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
2340 {
2341     OIC_TRACE_MARK(%s:OCHandleRequests:%s, TAG, requestInfo->info.resourceUri);
2342     OIC_LOG(DEBUG, TAG, "Enter OCHandleRequests");
2343     OIC_LOG_V(INFO, TAG, "Endpoint URI : %s", requestInfo->info.resourceUri);
2344
2345     if (myStackMode == OC_CLIENT)
2346     {
2347         //TODO: should the client be responding to requests?
2348         return;
2349     }
2350
2351     // If the request message is Confirmable,
2352     // then the response SHOULD be returned in an Acknowledgement message.
2353     CAMessageType_t directResponseType = requestInfo->info.type;
2354     directResponseType = (directResponseType == CA_MSG_CONFIRM)
2355             ? CA_MSG_ACKNOWLEDGE : CA_MSG_NONCONFIRM;
2356
2357     char * uriWithoutQuery = NULL;
2358     char * query = NULL;
2359     OCStackResult requestResult = OC_STACK_ERROR;
2360
2361     requestResult = getQueryFromUri(requestInfo->info.resourceUri, &query, &uriWithoutQuery);
2362
2363     if (requestResult != OC_STACK_OK || !uriWithoutQuery)
2364     {
2365         OIC_LOG_V(ERROR, TAG, "getQueryFromUri() failed with OC error code %d\n", requestResult);
2366         return;
2367     }
2368     OIC_LOG_V(INFO, TAG, "URI without query: %s", uriWithoutQuery);
2369     OIC_LOG_V(INFO, TAG, "Query : %s", query);
2370
2371     OCServerProtocolRequest serverRequest = { 0 };
2372     if (strlen(uriWithoutQuery) < MAX_URI_LENGTH)
2373     {
2374         OICStrcpy(serverRequest.resourceUrl, sizeof(serverRequest.resourceUrl), uriWithoutQuery);
2375         OICFree(uriWithoutQuery);
2376     }
2377     else
2378     {
2379         OIC_LOG(ERROR, TAG, "URI length exceeds MAX_URI_LENGTH.");
2380         OICFree(uriWithoutQuery);
2381         OICFree(query);
2382         return;
2383     }
2384
2385     if (query)
2386     {
2387         if (strlen(query) < MAX_QUERY_LENGTH)
2388         {
2389             OICStrcpy(serverRequest.query, sizeof(serverRequest.query), query);
2390             OICFree(query);
2391         }
2392         else
2393         {
2394             OIC_LOG(ERROR, TAG, "Query length exceeds MAX_QUERY_LENGTH.");
2395             OICFree(query);
2396             return;
2397         }
2398     }
2399
2400     if ((requestInfo->info.payload) && (0 < requestInfo->info.payloadSize))
2401     {
2402         serverRequest.payloadFormat = CAToOCPayloadFormat(requestInfo->info.payloadFormat);
2403         serverRequest.reqTotalSize = requestInfo->info.payloadSize;
2404         serverRequest.payload = (uint8_t *) OICMalloc(requestInfo->info.payloadSize);
2405         if (!serverRequest.payload)
2406         {
2407             OIC_LOG(ERROR, TAG, "Allocation for payload failed.");
2408             return;
2409         }
2410         memcpy (serverRequest.payload, requestInfo->info.payload,
2411                 requestInfo->info.payloadSize);
2412     }
2413     else
2414     {
2415         serverRequest.reqTotalSize = 0;
2416     }
2417
2418     switch (requestInfo->method)
2419     {
2420         case CA_GET:
2421             serverRequest.method = OC_REST_GET;
2422             break;
2423         case CA_PUT:
2424             serverRequest.method = OC_REST_PUT;
2425             break;
2426         case CA_POST:
2427             serverRequest.method = OC_REST_POST;
2428             break;
2429         case CA_DELETE:
2430             serverRequest.method = OC_REST_DELETE;
2431             break;
2432         default:
2433             OIC_LOG_V(ERROR, TAG, "Received CA method %d not supported", requestInfo->method);
2434             SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_REQ,
2435                                     directResponseType, requestInfo->info.numOptions,
2436                                     requestInfo->info.options, requestInfo->info.token,
2437                                     requestInfo->info.tokenLength, requestInfo->info.resourceUri,
2438                                     CA_RESPONSE_DATA);
2439             OICFree(serverRequest.payload);
2440             return;
2441     }
2442
2443     OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)requestInfo->info.token,
2444                    requestInfo->info.tokenLength);
2445
2446     serverRequest.tokenLength = requestInfo->info.tokenLength;
2447     if (serverRequest.tokenLength)
2448     {
2449         // Non empty token
2450         serverRequest.requestToken = (CAToken_t)OICMalloc(requestInfo->info.tokenLength);
2451
2452         if (!serverRequest.requestToken)
2453         {
2454             OIC_LOG(FATAL, TAG, "Allocation for token failed.");
2455             SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_INTERNAL_SERVER_ERROR,
2456                                     directResponseType, requestInfo->info.numOptions,
2457                                     requestInfo->info.options, requestInfo->info.token,
2458                                     requestInfo->info.tokenLength, requestInfo->info.resourceUri,
2459                                     CA_RESPONSE_DATA);
2460             OICFree(serverRequest.payload);
2461             return;
2462         }
2463         memcpy(serverRequest.requestToken, requestInfo->info.token, requestInfo->info.tokenLength);
2464     }
2465
2466     serverRequest.acceptFormat = CAToOCPayloadFormat(requestInfo->info.acceptFormat);
2467     if (OC_FORMAT_VND_OCF_CBOR == serverRequest.acceptFormat)
2468     {
2469         serverRequest.acceptVersion = requestInfo->info.acceptVersion;
2470     }
2471
2472     if (requestInfo->info.type == CA_MSG_CONFIRM)
2473     {
2474         serverRequest.qos = OC_HIGH_QOS;
2475     }
2476     else
2477     {
2478         serverRequest.qos = OC_LOW_QOS;
2479     }
2480     // CA does not need the following field
2481     // Are we sure CA does not need them? how is it responding to multicast
2482     serverRequest.delayedResNeeded = 0;
2483
2484     serverRequest.coapID = requestInfo->info.messageId;
2485
2486     CopyEndpointToDevAddr(endPoint, &serverRequest.devAddr);
2487
2488     // copy vendor specific header options
2489     uint8_t tempNum = (requestInfo->info.numOptions);
2490
2491     // Assume no observation requested and it is a pure GET.
2492     // If obs registration/de-registration requested it'll be fetched from the
2493     // options in GetObserveHeaderOption()
2494     serverRequest.observationOption = OC_OBSERVE_NO_OPTION;
2495
2496     GetObserveHeaderOption(&serverRequest.observationOption, requestInfo->info.options, &tempNum);
2497     if (requestInfo->info.numOptions > MAX_HEADER_OPTIONS)
2498     {
2499         OIC_LOG(ERROR, TAG,
2500                 "The request info numOptions is greater than MAX_HEADER_OPTIONS");
2501         SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_BAD_OPT,
2502                                 directResponseType, requestInfo->info.numOptions,
2503                                 requestInfo->info.options, requestInfo->info.token,
2504                                 requestInfo->info.tokenLength, requestInfo->info.resourceUri,
2505                                 CA_RESPONSE_DATA);
2506         OICFree(serverRequest.payload);
2507         OICFree(serverRequest.requestToken);
2508         return;
2509     }
2510     serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
2511     if (serverRequest.numRcvdVendorSpecificHeaderOptions && requestInfo->info.options)
2512     {
2513         memcpy(&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
2514                sizeof(CAHeaderOption_t) * tempNum);
2515     }
2516
2517     requestResult = HandleStackRequests (&serverRequest);
2518
2519     if (requestResult == OC_STACK_SLOW_RESOURCE)
2520     {
2521         // Send ACK to client as precursor to slow response
2522         if (requestInfo->info.type == CA_MSG_CONFIRM)
2523         {
2524             SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_EMPTY,
2525                                     CA_MSG_ACKNOWLEDGE,0, NULL, NULL, 0, NULL,
2526                                     CA_RESPONSE_DATA);
2527         }
2528     }
2529     if (requestResult == OC_STACK_RESOURCE_ERROR
2530             && serverRequest.observationOption == OC_OBSERVE_REGISTER)
2531     {
2532         OIC_LOG(ERROR, TAG, "Observe Registration failed due to resource error");
2533     }
2534     else if (!OCResultToSuccess(requestResult))
2535     {
2536         OIC_LOG_V(ERROR, TAG, "HandleStackRequests failed. error: %d", requestResult);
2537
2538         CAResponseResult_t stackResponse = OCToCAStackResult(requestResult, serverRequest.method);
2539
2540         SendDirectStackResponse(endPoint, requestInfo->info.messageId, stackResponse,
2541                                 directResponseType, requestInfo->info.numOptions,
2542                                 requestInfo->info.options, requestInfo->info.token,
2543                                 requestInfo->info.tokenLength, requestInfo->info.resourceUri,
2544                                 CA_RESPONSE_DATA);
2545     }
2546     // requestToken is fed to HandleStackRequests, which then goes to AddServerRequest.
2547     // The token is copied in there, and is thus still owned by this function.
2548     OICFree(serverRequest.payload);
2549     OICFree(serverRequest.requestToken);
2550     OIC_LOG(INFO, TAG, "Exit OCHandleRequests");
2551 }
2552
2553 //This function will be called back by CA layer when a request is received
2554 void HandleCARequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* requestInfo)
2555 {
2556     OIC_LOG(INFO, TAG, "Enter HandleCARequests");
2557     OIC_TRACE_BEGIN(%s:HandleCARequests, TAG);
2558     if (!endPoint)
2559     {
2560         OIC_LOG(ERROR, TAG, "endPoint is NULL");
2561         OIC_TRACE_END();
2562         return;
2563     }
2564
2565     if (!requestInfo)
2566     {
2567         OIC_LOG(ERROR, TAG, "requestInfo is NULL");
2568         OIC_TRACE_END();
2569         return;
2570     }
2571
2572 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
2573 #ifdef ROUTING_GATEWAY
2574     bool needRIHandling = false;
2575     bool isEmptyMsg = false;
2576     /*
2577      * Routing manager is going to update either of endpoint or request or both.
2578      * This typecasting is done to avoid unnecessary duplication of Endpoint and requestInfo
2579      * RM can update "routeData" option in endPoint so that future RI requests can be sent to proper
2580      * destination. It can also remove "RM" coap header option before passing request / response to
2581      * RI as this option will make no sense to either RI or application.
2582      */
2583     OCStackResult ret = RMHandleRequest((CARequestInfo_t *)requestInfo, (CAEndpoint_t *)endPoint,
2584                                         &needRIHandling, &isEmptyMsg);
2585     if (OC_STACK_OK != ret || !needRIHandling)
2586     {
2587         OIC_LOG_V(INFO, TAG, "Routing status![%d]. Not forwarding to RI", ret);
2588         OIC_TRACE_END();
2589         return;
2590     }
2591 #endif
2592
2593     /*
2594      * Put source in sender endpoint so that the next packet from application can be routed to
2595      * proper destination and remove RM header option.
2596      */
2597     RMUpdateInfo((CAHeaderOption_t **) &(requestInfo->info.options),
2598         (uint8_t *) &(requestInfo->info.numOptions),
2599         (CAEndpoint_t *)endPoint);
2600
2601 #ifdef ROUTING_GATEWAY
2602     if (isEmptyMsg)
2603     {
2604         /*
2605          * In Gateways, the MSGType in route option is used to check if the actual
2606          * response is EMPTY message(4 bytes CoAP Header).  In case of Client, the
2607          * EMPTY response is sent in the form of POST request which need to be changed
2608          * to a EMPTY response by RM.  This translation is done in this part of the code.
2609          */
2610         OIC_LOG(INFO, TAG, "This is a Empty response from the Client");
2611         CAResponseInfo_t respInfo = {.result = CA_EMPTY,
2612                                      .info.messageId = requestInfo->info.messageId,
2613                                      .info.type = CA_MSG_ACKNOWLEDGE};
2614         OCHandleResponse(endPoint, &respInfo);
2615     }
2616     else
2617 #endif
2618 #endif
2619     {
2620         // Normal handling of the packet
2621         OCHandleRequests(endPoint, requestInfo);
2622     }
2623     OIC_LOG(INFO, TAG, "Exit HandleCARequests");
2624     OIC_TRACE_END();
2625 }
2626
2627 //-----------------------------------------------------------------------------
2628 // Public APIs
2629 //-----------------------------------------------------------------------------
2630 #ifdef RA_ADAPTER
2631 OCStackResult OCSetRAInfo(const OCRAInfo_t *raInfo)
2632 {
2633     if (!raInfo           ||
2634         !raInfo->username ||
2635         !raInfo->hostname ||
2636         !raInfo->xmpp_domain)
2637     {
2638
2639         return OC_STACK_INVALID_PARAM;
2640     }
2641     OCStackResult result = CAResultToOCResult(CASetRAInfo((const CARAInfo_t *) raInfo));
2642     gRASetInfo = (result == OC_STACK_OK)? true : false;
2643
2644     return result;
2645 }
2646 #endif
2647
2648 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
2649 {
2650     (void) ipAddr;
2651     (void) port;
2652     return OCInit1(mode, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS);
2653 }
2654
2655 OCStackResult OCInit1(OCMode mode, OCTransportFlags serverFlags, OCTransportFlags clientFlags)
2656 {
2657     OIC_LOG(DEBUG, TAG, "call OCInit1");
2658     return OCInit2(mode, serverFlags, clientFlags, OC_DEFAULT_ADAPTER);
2659 }
2660
2661 OCStackResult OCInit2(OCMode mode, OCTransportFlags serverFlags, OCTransportFlags clientFlags,
2662                       OCTransportAdapter transportType)
2663 {
2664     OIC_LOG(INFO, TAG, "Entering OCInit2");
2665
2666     // Serialize calls to start and stop the stack.
2667     OCEnterInitializer();
2668
2669     OCStackResult result = OC_STACK_OK;
2670
2671     if (g_ocStackStartCount == 0)
2672     {
2673         // This is the first call to initialize the stack so it gets to do the real work.
2674         result = OCInitializeInternal(mode, serverFlags, clientFlags, transportType);
2675     }
2676
2677     if (result == OC_STACK_OK)
2678     {
2679         // Increment the start count since we're about to return success.
2680         assert(g_ocStackStartCount != UINT_MAX);
2681         assert(stackState == OC_STACK_INITIALIZED);
2682         g_ocStackStartCount++;
2683     }
2684
2685     OCLeaveInitializer();
2686     return result;
2687 }
2688
2689 OCStackResult OCInitializeInternal(OCMode mode, OCTransportFlags serverFlags,
2690                                    OCTransportFlags clientFlags, OCTransportAdapter transportType)
2691 {
2692     if (stackState == OC_STACK_INITIALIZED)
2693     {
2694         OIC_LOG(INFO, TAG, "Subsequent calls to OCInit() without calling \
2695                 OCStop() between them are ignored.");
2696         return OC_STACK_OK;
2697     }
2698
2699 #ifndef ROUTING_GATEWAY
2700     if (OC_GATEWAY == mode)
2701     {
2702         OIC_LOG(ERROR, TAG, "Routing Manager not supported");
2703         return OC_STACK_INVALID_PARAM;
2704     }
2705 #endif
2706
2707 #ifdef RA_ADAPTER
2708     if(!gRASetInfo)
2709     {
2710         OIC_LOG(ERROR, TAG, "Need to call OCSetRAInfo before calling OCInit");
2711         return OC_STACK_ERROR;
2712     }
2713 #endif
2714
2715     OIC_LOG_V(INFO, TAG, "IoTivity version is v%s", IOTIVITY_VERSION);
2716     OCStackResult result = OC_STACK_ERROR;
2717
2718     // Validate mode
2719     if (!((mode == OC_CLIENT) || (mode == OC_SERVER) || (mode == OC_CLIENT_SERVER)
2720         || (mode == OC_GATEWAY)))
2721     {
2722         OIC_LOG(ERROR, TAG, "Invalid mode");
2723         return OC_STACK_ERROR;
2724     }
2725     myStackMode = mode;
2726
2727     if (mode == OC_CLIENT || mode == OC_CLIENT_SERVER || mode == OC_GATEWAY)
2728     {
2729         caglobals.client = true;
2730     }
2731     if (mode == OC_SERVER || mode == OC_CLIENT_SERVER || mode == OC_GATEWAY)
2732     {
2733         caglobals.server = true;
2734     }
2735
2736     caglobals.serverFlags = (CATransportFlags_t)serverFlags;
2737     if (!(caglobals.serverFlags & CA_IPFAMILY_MASK))
2738     {
2739         caglobals.serverFlags = (CATransportFlags_t)(caglobals.serverFlags|CA_IPV4|CA_IPV6);
2740     }
2741     caglobals.clientFlags = (CATransportFlags_t)clientFlags;
2742     if (!(caglobals.clientFlags & CA_IPFAMILY_MASK))
2743     {
2744         caglobals.clientFlags = (CATransportFlags_t)(caglobals.clientFlags|CA_IPV4|CA_IPV6);
2745     }
2746
2747     defaultDeviceHandler = NULL;
2748     defaultDeviceHandlerCallbackParameter = NULL;
2749
2750 #ifdef UWP_APP
2751     result = InitSqlite3TempDir();
2752     VERIFY_SUCCESS(result, OC_STACK_OK);
2753 #endif // UWP_APP
2754
2755     result = InitializeScheduleResourceList();
2756     VERIFY_SUCCESS(result, OC_STACK_OK);
2757
2758     result = CAResultToOCResult(CAInitialize((CATransportAdapter_t)transportType));
2759     VERIFY_SUCCESS(result, OC_STACK_OK);
2760
2761     result = CAResultToOCResult(OCSelectNetwork(transportType));
2762     VERIFY_SUCCESS(result, OC_STACK_OK);
2763
2764     result = CAResultToOCResult(CARegisterNetworkMonitorHandler(
2765       OCDefaultAdapterStateChangedHandler, OCDefaultConnectionStateChangedHandler));
2766     VERIFY_SUCCESS(result, OC_STACK_OK);
2767
2768     switch (myStackMode)
2769     {
2770         case OC_CLIENT:
2771             CARegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
2772             result = CAResultToOCResult(CAStartDiscoveryServer());
2773             OIC_LOG(INFO, TAG, "Client mode: CAStartDiscoveryServer");
2774             break;
2775         case OC_SERVER:
2776             SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
2777             result = CAResultToOCResult(CAStartListeningServer());
2778             OIC_LOG(INFO, TAG, "Server mode: CAStartListeningServer");
2779             break;
2780         case OC_CLIENT_SERVER:
2781         case OC_GATEWAY:
2782             SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
2783             result = CAResultToOCResult(CAStartListeningServer());
2784             if(result == OC_STACK_OK)
2785             {
2786                 result = CAResultToOCResult(CAStartDiscoveryServer());
2787             }
2788             break;
2789     }
2790     VERIFY_SUCCESS(result, OC_STACK_OK);
2791
2792 #ifdef TCP_ADAPTER
2793     CARegisterKeepAliveHandler(HandleKeepAliveConnCB);
2794 #endif
2795
2796 #ifdef WITH_PRESENCE
2797     PresenceTimeOutSize = sizeof (PresenceTimeOut) / sizeof (PresenceTimeOut[0]) - 1;
2798 #endif // WITH_PRESENCE
2799
2800     //Update Stack state to initialized
2801     stackState = OC_STACK_INITIALIZED;
2802
2803     // Initialize resource
2804     if(myStackMode != OC_CLIENT)
2805     {
2806         result = initResources();
2807     }
2808
2809 #if defined (ROUTING_GATEWAY) || defined (ROUTING_EP)
2810     RMSetStackMode(mode);
2811 #ifdef ROUTING_GATEWAY
2812     if (OC_GATEWAY == myStackMode)
2813     {
2814         result = RMInitialize();
2815     }
2816 #endif
2817 #endif
2818
2819 #ifdef TCP_ADAPTER
2820     if (result == OC_STACK_OK)
2821     {
2822         result = InitializeKeepAlive(myStackMode);
2823     }
2824 #endif
2825
2826 #if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
2827     // Initialize the Connection Manager
2828     if (result == OC_STACK_OK)
2829     {
2830         result = OCCMInitialize();
2831     }
2832 #endif
2833
2834 exit:
2835     if(result != OC_STACK_OK)
2836     {
2837         OIC_LOG(ERROR, TAG, "Stack initialization error");
2838         TerminateScheduleResourceList();
2839         deleteAllResources();
2840         CATerminate();
2841         stackState = OC_STACK_UNINITIALIZED;
2842     }
2843     return result;
2844 }
2845
2846 OCStackResult OCStop()
2847 {
2848     OIC_LOG(INFO, TAG, "Entering OCStop");
2849
2850     // Serialize calls to start and stop the stack.
2851     OCEnterInitializer();
2852
2853     OCStackResult result = OC_STACK_OK;
2854
2855     if (g_ocStackStartCount == 1)
2856     {
2857         // This is the last call to stop the stack, do the real work.
2858         result = OCDeInitializeInternal();
2859     }
2860     else if (g_ocStackStartCount == 0)
2861     {
2862         OIC_LOG(ERROR, TAG, "Too many calls to OCStop");
2863         assert(!"Too many calls to OCStop");
2864         result = OC_STACK_ERROR;
2865     }
2866
2867     if (result == OC_STACK_OK)
2868     {
2869         g_ocStackStartCount--;
2870     }
2871
2872     OCLeaveInitializer();
2873     return result;
2874 }
2875
2876 OCStackResult OCDeInitializeInternal()
2877 {
2878     assert(stackState == OC_STACK_INITIALIZED);
2879
2880 #ifdef WITH_PRESENCE
2881     // Ensure that the TTL associated with ANY and ALL presence notifications originating from
2882     // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
2883     presenceResource.presenceTTL = 0;
2884     presenceState = OC_PRESENCE_UNINITIALIZED;
2885 #endif // WITH_PRESENCE
2886
2887 #ifdef ROUTING_GATEWAY
2888     if (OC_GATEWAY == myStackMode)
2889     {
2890         RMTerminate();
2891     }
2892 #endif
2893
2894 #ifdef TCP_ADAPTER
2895     TerminateKeepAlive(myStackMode);
2896 #endif
2897
2898     OCStackResult result = CAResultToOCResult(
2899             CAUnregisterNetworkMonitorHandler(OCDefaultAdapterStateChangedHandler,
2900                                               OCDefaultConnectionStateChangedHandler));
2901     if (OC_STACK_OK != result)
2902     {
2903         OIC_LOG(ERROR, TAG, "CAUnregisterNetworkMonitorHandler has failed");
2904     }
2905
2906     TerminateScheduleResourceList();
2907     // Remove all observers
2908     DeleteObserverList();
2909     // Free memory dynamically allocated for resources
2910     deleteAllResources();
2911     // Remove all the client callbacks
2912     DeleteClientCBList();
2913     // Terminate connectivity-abstraction layer.
2914     CATerminate();
2915
2916 #if defined(TCP_ADAPTER) && defined(WITH_CLOUD)
2917     // Terminate the Connection Manager
2918     OCCMTerminate();
2919 #endif
2920
2921     // Unset cautil config
2922     CAUtilConfig_t configs = {(CATransportBTFlags_t)CA_DEFAULT_BT_FLAGS};
2923     CAUtilSetBTConfigure(configs);
2924
2925     stackState = OC_STACK_UNINITIALIZED;
2926     return OC_STACK_OK;
2927 }
2928
2929 OCStackResult OCStartMulticastServer()
2930 {
2931     if(stackState != OC_STACK_INITIALIZED)
2932     {
2933         OIC_LOG(ERROR, TAG, "OCStack is not initalized. Cannot start multicast server.");
2934         return OC_STACK_ERROR;
2935     }
2936     g_multicastServerStopped = false;
2937     return OC_STACK_OK;
2938 }
2939
2940 OCStackResult OCStopMulticastServer()
2941 {
2942     g_multicastServerStopped = true;
2943     return OC_STACK_OK;
2944 }
2945
2946 CAMessageType_t qualityOfServiceToMessageType(OCQualityOfService qos)
2947 {
2948     switch (qos)
2949     {
2950         case OC_HIGH_QOS:
2951             return CA_MSG_CONFIRM;
2952         case OC_LOW_QOS:
2953         case OC_MEDIUM_QOS:
2954         case OC_NA_QOS:
2955         default:
2956             return CA_MSG_NONCONFIRM;
2957     }
2958 }
2959
2960 /**
2961  *  A request uri consists of the following components in order:
2962  *                              example
2963  *  optionally one of
2964  *      CoAP over UDP prefix    "coap://"
2965  *      CoAP over TCP prefix    "coap+tcp://"
2966  *      CoAP over DTLS prefix   "coaps://"
2967  *      CoAP over TLS prefix    "coaps+tcp://"
2968  *  optionally one of
2969  *      IPv6 address            "[1234::5678]"
2970  *      IPv4 address            "192.168.1.1"
2971  *  optional port               ":5683"
2972  *  resource uri                "/oc/core..."
2973  *
2974  *  for PRESENCE requests, extract resource type.
2975  */
2976 static OCStackResult ParseRequestUri(const char *fullUri,
2977                                         OCTransportAdapter adapter,
2978                                         OCTransportFlags flags,
2979                                         OCDevAddr **devAddr,
2980                                         char **resourceUri,
2981                                         char **resourceType)
2982 {
2983     VERIFY_NON_NULL(fullUri, FATAL, OC_STACK_INVALID_CALLBACK);
2984
2985     OCStackResult result = OC_STACK_OK;
2986     OCDevAddr *da = NULL;
2987     char *colon = NULL;
2988     char *end;
2989
2990     // provide defaults for all returned values
2991     if (devAddr)
2992     {
2993         *devAddr = NULL;
2994     }
2995     if (resourceUri)
2996     {
2997         *resourceUri = NULL;
2998     }
2999     if (resourceType)
3000     {
3001         *resourceType = NULL;
3002     }
3003
3004     // delimit url prefix, if any
3005     const char *start = fullUri;
3006     char *slash2 = strstr(start, "//");
3007     if (slash2)
3008     {
3009         start = slash2 + 2;
3010     }
3011     char *slash = strchr(start, '/');
3012     if (!slash)
3013     {
3014         return OC_STACK_INVALID_URI;
3015     }
3016
3017     // process url scheme
3018     size_t prefixLen = slash2 - fullUri;
3019     bool istcp = false;
3020     if (prefixLen)
3021     {
3022         if (((prefixLen == sizeof(COAP_TCP_SCHEME) - 1) && (!strncmp(fullUri, COAP_TCP_SCHEME, prefixLen)))
3023         || ((prefixLen == sizeof(COAPS_TCP_SCHEME) - 1) && (!strncmp(fullUri, COAPS_TCP_SCHEME, prefixLen))))
3024         {
3025             istcp = true;
3026         }
3027     }
3028
3029     // TODO: this logic should come in with unit tests exercising the various strings
3030     // processs url prefix, if any
3031     size_t urlLen = slash - start;
3032     // port
3033     uint16_t port = 0;
3034     size_t len = 0;
3035     if (urlLen && devAddr)
3036     {   // construct OCDevAddr
3037         if (start[0] == '[')
3038         {   // ipv6 address
3039             char *close = strchr(++start, ']');
3040             if (!close || close > slash)
3041             {
3042                 return OC_STACK_INVALID_URI;
3043             }
3044             end = close;
3045             if (close[1] == ':')
3046             {
3047                 colon = close + 1;
3048             }
3049
3050             if (istcp)
3051             {
3052                 adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_TCP);
3053             }
3054             else
3055             {
3056                 adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
3057             }
3058             flags = (OCTransportFlags)(flags | OC_IP_USE_V6);
3059         }
3060         else
3061         {
3062             char *dot = strchr(start, '.');
3063             if (dot && dot < slash)
3064             {   // ipv4 address
3065                 colon = strchr(start, ':');
3066                 end = (colon && colon < slash) ? colon : slash;
3067
3068                 if (istcp)
3069                 {
3070                     // coap over tcp
3071                     adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_TCP);
3072                 }
3073                 else
3074                 {
3075                     adapter = (OCTransportAdapter)(adapter | OC_ADAPTER_IP);
3076                 }
3077                 flags = (OCTransportFlags)(flags | OC_IP_USE_V4);
3078             }
3079             else
3080             {   // MAC address
3081                 end = slash;
3082             }
3083         }
3084         len = end - start;
3085         if (len >= sizeof(da->addr))
3086         {
3087             return OC_STACK_INVALID_URI;
3088         }
3089         // collect port, if any
3090         if (colon && colon < slash)
3091         {
3092             for (colon++; colon < slash; colon++)
3093             {
3094                 char c = colon[0];
3095                 if (c < '0' || c > '9')
3096                 {
3097                     return OC_STACK_INVALID_URI;
3098                 }
3099                 port = 10 * port + c - '0';
3100             }
3101         }
3102
3103         len = end - start;
3104         if (len >= sizeof(da->addr))
3105         {
3106             return OC_STACK_INVALID_URI;
3107         }
3108
3109         da = (OCDevAddr *)OICCalloc(sizeof (OCDevAddr), 1);
3110         if (!da)
3111         {
3112             return OC_STACK_NO_MEMORY;
3113         }
3114
3115         // Decode address per RFC 6874.
3116         result = OCDecodeAddressForRFC6874(da->addr, sizeof(da->addr), start, end);
3117         if (result != OC_STACK_OK)
3118         {
3119              OICFree(*devAddr);
3120              return result;
3121         }
3122
3123         da->port = port;
3124         da->adapter = adapter;
3125         da->flags = flags;
3126         if (!strncmp(fullUri, "coaps", 5))
3127         {
3128             da->flags = (OCTransportFlags)(da->flags|CA_SECURE);
3129         }
3130         *devAddr = da;
3131     }
3132
3133     // process resource uri, if any
3134     if (slash)
3135     {   // request uri and query
3136         size_t ulen = strlen(slash); // resource uri length
3137         size_t tlen = 0;      // resource type length
3138         char *type = NULL;
3139
3140         static const char strPresence[] = "/oic/ad?rt=";
3141         static const size_t lenPresence = sizeof(strPresence) - 1;
3142         if (!strncmp(slash, strPresence, lenPresence))
3143         {
3144             type = slash + lenPresence;
3145             tlen = ulen - lenPresence;
3146         }
3147         // resource uri
3148         if (resourceUri)
3149         {
3150             *resourceUri = (char *)OICMalloc(ulen + 1);
3151             if (!*resourceUri)
3152             {
3153                 result = OC_STACK_NO_MEMORY;
3154                 goto error;
3155             }
3156             OICStrcpy(*resourceUri, (ulen + 1), slash);
3157         }
3158         // resource type
3159         if (type && resourceType)
3160         {
3161             *resourceType = (char *)OICMalloc(tlen + 1);
3162             if (!*resourceType)
3163             {
3164                 result = OC_STACK_NO_MEMORY;
3165                 goto error;
3166             }
3167
3168             OICStrcpy(*resourceType, (tlen + 1), type);
3169         }
3170     }
3171
3172     return OC_STACK_OK;
3173
3174 error:
3175     // free all returned values
3176     if (devAddr)
3177     {
3178         OICFree(*devAddr);
3179     }
3180     if (resourceUri)
3181     {
3182         OICFree(*resourceUri);
3183     }
3184     if (resourceType)
3185     {
3186         OICFree(*resourceType);
3187     }
3188     return result;
3189 }
3190
3191 static OCStackResult OCPreparePresence(CAEndpoint_t *endpoint,
3192                                        char **requestUri,
3193                                        bool isMulticast)
3194 {
3195     char uri[CA_MAX_URI_LENGTH];
3196
3197     FormCanonicalPresenceUri(endpoint, uri, isMulticast);
3198
3199     *requestUri = OICStrdup(uri);
3200     if (!*requestUri)
3201     {
3202         return OC_STACK_NO_MEMORY;
3203     }
3204
3205     return OC_STACK_OK;
3206 }
3207
3208 /**
3209  * Discover or Perform requests on a specified resource
3210  * Deprecated: use OCDoRequest instead
3211  */
3212 OCStackResult OCDoResource(OCDoHandle *handle,
3213                             OCMethod method,
3214                             const char *requestUri,
3215                             const OCDevAddr *destination,
3216                             OCPayload* payload,
3217                             OCConnectivityType connectivityType,
3218                             OCQualityOfService qos,
3219                             OCCallbackData *cbData,
3220                             OCHeaderOption *options,
3221                             uint8_t numOptions)
3222 {
3223     OIC_TRACE_BEGIN(%s:OCDoRequest, TAG);
3224     OCStackResult ret = OCDoRequest(handle, method, requestUri,destination, payload,
3225                 connectivityType, qos, cbData, options, numOptions);
3226     OIC_TRACE_END();
3227
3228     // This is the owner of the payload object, so we free it
3229     OCPayloadDestroy(payload);
3230     return ret;
3231 }
3232
3233 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
3234 static const char* ASSERT_ROLES_CTX = "Asserting roles from OCDoRequest";
3235 static void assertRolesCB(void* ctx, bool hasError)
3236 {
3237     OC_UNUSED(ctx); // Not used in release builds
3238
3239     if (!hasError)
3240     {
3241         OIC_LOG_V(DEBUG, TAG, "%s: Asserting roles SUCCEEDED - ctx: %s", __func__, (char*)ctx);
3242     }
3243     else
3244     {
3245         OIC_LOG_V(DEBUG, TAG, "%s: Asserting roles FAILED - ctx: %s", __func__, (char*)ctx);
3246     }
3247 }
3248 #endif // __WITH_DTLS__ || __WITH_TLS__
3249
3250 /**
3251  * Discover or Perform requests on a specified resource
3252  */
3253 OCStackResult OCDoRequest(OCDoHandle *handle,
3254                             OCMethod method,
3255                             const char *requestUri,
3256                             const OCDevAddr *destination,
3257                             OCPayload* payload,
3258                             OCConnectivityType connectivityType,
3259                             OCQualityOfService qos,
3260                             OCCallbackData *cbData,
3261                             OCHeaderOption *options,
3262                             uint8_t nu