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