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