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