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