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