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