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