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