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