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