Follow-up for build breakage due to 3dec7176200a1e8f125226f22b9471374dd7ace1
[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     *handle = pointer;
3145     result = OC_STACK_OK;
3146
3147 #ifdef WITH_PRESENCE
3148     if (presenceResource.handle)
3149     {
3150         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3151         SendPresenceNotification(pointer->rsrcType, OC_PRESENCE_TRIGGER_CREATE);
3152     }
3153 #endif
3154 exit:
3155     if (result != OC_STACK_OK)
3156     {
3157         // Deep delete of resource and other dynamic elements that it contains
3158         deleteResource(pointer);
3159     }
3160     return result;
3161 }
3162
3163
3164 OCStackResult OCBindResource(
3165         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
3166 {
3167     OCResource *resource = NULL;
3168     uint8_t i = 0;
3169
3170     OIC_LOG(INFO, TAG, "Entering OCBindResource");
3171
3172     // Validate parameters
3173     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
3174     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
3175     // Container cannot contain itself
3176     if (collectionHandle == resourceHandle)
3177     {
3178         OIC_LOG(ERROR, TAG, "Added handle equals collection handle");
3179         return OC_STACK_INVALID_PARAM;
3180     }
3181
3182     // Use the handle to find the resource in the resource linked list
3183     resource = findResource((OCResource *) collectionHandle);
3184     if (!resource)
3185     {
3186         OIC_LOG(ERROR, TAG, "Collection handle not found");
3187         return OC_STACK_INVALID_PARAM;
3188     }
3189
3190     // Look for an open slot to add add the child resource.
3191     // If found, add it and return success
3192     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
3193     {
3194         if (!resource->rsrcResources[i])
3195         {
3196             resource->rsrcResources[i] = (OCResource *) resourceHandle;
3197             OIC_LOG(INFO, TAG, "resource bound");
3198
3199 #ifdef WITH_PRESENCE
3200             if (presenceResource.handle)
3201             {
3202                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3203                 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
3204                         OC_PRESENCE_TRIGGER_CHANGE);
3205             }
3206 #endif
3207             return OC_STACK_OK;
3208
3209         }
3210     }
3211
3212     // Unable to add resourceHandle, so return error
3213     return OC_STACK_ERROR;
3214 }
3215
3216 OCStackResult OCUnBindResource(
3217         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
3218 {
3219     OCResource *resource = NULL;
3220     uint8_t i = 0;
3221
3222     OIC_LOG(INFO, TAG, "Entering OCUnBindResource");
3223
3224     // Validate parameters
3225     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
3226     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
3227     // Container cannot contain itself
3228     if (collectionHandle == resourceHandle)
3229     {
3230         OIC_LOG(ERROR, TAG, "removing handle equals collection handle");
3231         return OC_STACK_INVALID_PARAM;
3232     }
3233
3234     // Use the handle to find the resource in the resource linked list
3235     resource = findResource((OCResource *) collectionHandle);
3236     if (!resource)
3237     {
3238         OIC_LOG(ERROR, TAG, "Collection handle not found");
3239         return OC_STACK_INVALID_PARAM;
3240     }
3241
3242     // Look for an open slot to add add the child resource.
3243     // If found, add it and return success
3244     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
3245     {
3246         if (resourceHandle == resource->rsrcResources[i])
3247         {
3248             resource->rsrcResources[i] = (OCResource *) NULL;
3249             OIC_LOG(INFO, TAG, "resource unbound");
3250
3251             // Send notification when resource is unbounded successfully.
3252 #ifdef WITH_PRESENCE
3253             if (presenceResource.handle)
3254             {
3255                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3256                 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
3257                         OC_PRESENCE_TRIGGER_CHANGE);
3258             }
3259 #endif
3260             return OC_STACK_OK;
3261         }
3262     }
3263
3264     OIC_LOG(INFO, TAG, "resource not found in collection");
3265
3266     // Unable to add resourceHandle, so return error
3267     return OC_STACK_ERROR;
3268 }
3269
3270 // Precondition is that the parameter has been checked to not equal NULL.
3271 static bool ValidateResourceTypeInterface(const char *resourceItemName)
3272 {
3273     if (resourceItemName[0] < 'a' || resourceItemName[0] > 'z')
3274     {
3275         return false;
3276     }
3277
3278     size_t index = 1;
3279     while (resourceItemName[index] != '\0')
3280     {
3281         if (resourceItemName[index] != '.' &&
3282                 resourceItemName[index] != '-' &&
3283                 (resourceItemName[index] < 'a' || resourceItemName[index] > 'z') &&
3284                 (resourceItemName[index] < '0' || resourceItemName[index] > '9'))
3285         {
3286             return false;
3287         }
3288         ++index;
3289     }
3290
3291     return true;
3292 }
3293 OCStackResult BindResourceTypeToResource(OCResource* resource,
3294                                             const char *resourceTypeName)
3295 {
3296     OCResourceType *pointer = NULL;
3297     char *str = NULL;
3298     OCStackResult result = OC_STACK_ERROR;
3299
3300     VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
3301
3302     if (!ValidateResourceTypeInterface(resourceTypeName))
3303     {
3304         OIC_LOG(ERROR, TAG, "resource type illegal (see RFC 6690)");
3305         return OC_STACK_INVALID_PARAM;
3306     }
3307
3308     pointer = (OCResourceType *) OICCalloc(1, sizeof(OCResourceType));
3309     if (!pointer)
3310     {
3311         result = OC_STACK_NO_MEMORY;
3312         goto exit;
3313     }
3314
3315     str = OICStrdup(resourceTypeName);
3316     if (!str)
3317     {
3318         result = OC_STACK_NO_MEMORY;
3319         goto exit;
3320     }
3321     pointer->resourcetypename = str;
3322
3323     insertResourceType(resource, pointer);
3324     result = OC_STACK_OK;
3325
3326     exit:
3327     if (result != OC_STACK_OK)
3328     {
3329         OICFree(pointer);
3330         OICFree(str);
3331     }
3332
3333     return result;
3334 }
3335
3336 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
3337         const char *resourceInterfaceName)
3338 {
3339     OCResourceInterface *pointer = NULL;
3340     char *str = NULL;
3341     OCStackResult result = OC_STACK_ERROR;
3342
3343     VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
3344
3345     if (!ValidateResourceTypeInterface(resourceInterfaceName))
3346     {
3347         OIC_LOG(ERROR, TAG, "resource /interface illegal (see RFC 6690)");
3348         return OC_STACK_INVALID_PARAM;
3349     }
3350
3351     OIC_LOG_V(INFO, TAG, "Binding %s interface to %s", resourceInterfaceName, resource->uri);
3352
3353     pointer = (OCResourceInterface *) OICCalloc(1, sizeof(OCResourceInterface));
3354     if (!pointer)
3355     {
3356         result = OC_STACK_NO_MEMORY;
3357         goto exit;
3358     }
3359
3360     str = OICStrdup(resourceInterfaceName);
3361     if (!str)
3362     {
3363         result = OC_STACK_NO_MEMORY;
3364         goto exit;
3365     }
3366     pointer->name = str;
3367
3368     // Bind the resourceinterface to the resource
3369     insertResourceInterface(resource, pointer);
3370
3371     result = OC_STACK_OK;
3372
3373     exit:
3374     if (result != OC_STACK_OK)
3375     {
3376         OICFree(pointer);
3377         OICFree(str);
3378     }
3379
3380     return result;
3381 }
3382
3383 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
3384         const char *resourceTypeName)
3385 {
3386
3387     OCStackResult result = OC_STACK_ERROR;
3388     OCResource *resource = NULL;
3389
3390     resource = findResource((OCResource *) handle);
3391     if (!resource)
3392     {
3393         OIC_LOG(ERROR, TAG, "Resource not found");
3394         return OC_STACK_ERROR;
3395     }
3396
3397     result = BindResourceTypeToResource(resource, resourceTypeName);
3398
3399 #ifdef WITH_PRESENCE
3400     if(presenceResource.handle)
3401     {
3402         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3403         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3404     }
3405 #endif
3406
3407     return result;
3408 }
3409
3410 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
3411         const char *resourceInterfaceName)
3412 {
3413
3414     OCStackResult result = OC_STACK_ERROR;
3415     OCResource *resource = NULL;
3416
3417     resource = findResource((OCResource *) handle);
3418     if (!resource)
3419     {
3420         OIC_LOG(ERROR, TAG, "Resource not found");
3421         return OC_STACK_ERROR;
3422     }
3423
3424     result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
3425
3426 #ifdef WITH_PRESENCE
3427     if (presenceResource.handle)
3428     {
3429         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3430         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3431     }
3432 #endif
3433
3434     return result;
3435 }
3436
3437 OCStackResult OCGetNumberOfResources(uint8_t *numResources)
3438 {
3439     OCResource *pointer = headResource;
3440
3441     VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
3442     *numResources = 0;
3443     while (pointer)
3444     {
3445         *numResources = *numResources + 1;
3446         pointer = pointer->next;
3447     }
3448     return OC_STACK_OK;
3449 }
3450
3451 OCResourceHandle OCGetResourceHandle(uint8_t index)
3452 {
3453     OCResource *pointer = headResource;
3454
3455     for( uint8_t i = 0; i < index && pointer; ++i)
3456     {
3457         pointer = pointer->next;
3458     }
3459     return (OCResourceHandle) pointer;
3460 }
3461
3462 OCStackResult OCDeleteResource(OCResourceHandle handle)
3463 {
3464     if (!handle)
3465     {
3466         OIC_LOG(ERROR, TAG, "Invalid handle for deletion");
3467         return OC_STACK_INVALID_PARAM;
3468     }
3469
3470     OCResource *resource = findResource((OCResource *) handle);
3471     if (resource == NULL)
3472     {
3473         OIC_LOG(ERROR, TAG, "Resource not found");
3474         return OC_STACK_NO_RESOURCE;
3475     }
3476
3477     if (deleteResource((OCResource *) handle) != OC_STACK_OK)
3478     {
3479         OIC_LOG(ERROR, TAG, "Error deleting resource");
3480         return OC_STACK_ERROR;
3481     }
3482
3483     return OC_STACK_OK;
3484 }
3485
3486 const char *OCGetResourceUri(OCResourceHandle handle)
3487 {
3488     OCResource *resource = NULL;
3489
3490     resource = findResource((OCResource *) handle);
3491     if (resource)
3492     {
3493         return resource->uri;
3494     }
3495     return (const char *) NULL;
3496 }
3497
3498 OCResourceProperty OCGetResourceProperties(OCResourceHandle handle)
3499 {
3500     OCResource *resource = NULL;
3501
3502     resource = findResource((OCResource *) handle);
3503     if (resource)
3504     {
3505         return resource->resourceProperties;
3506     }
3507     return (OCResourceProperty)-1;
3508 }
3509
3510 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
3511         uint8_t *numResourceTypes)
3512 {
3513     OCResource *resource = NULL;
3514     OCResourceType *pointer = NULL;
3515
3516     VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
3517     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3518
3519     *numResourceTypes = 0;
3520
3521     resource = findResource((OCResource *) handle);
3522     if (resource)
3523     {
3524         pointer = resource->rsrcType;
3525         while (pointer)
3526         {
3527             *numResourceTypes = *numResourceTypes + 1;
3528             pointer = pointer->next;
3529         }
3530     }
3531     return OC_STACK_OK;
3532 }
3533
3534 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index)
3535 {
3536     OCResourceType *resourceType = NULL;
3537
3538     resourceType = findResourceTypeAtIndex(handle, index);
3539     if (resourceType)
3540     {
3541         return resourceType->resourcetypename;
3542     }
3543     return (const char *) NULL;
3544 }
3545
3546 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
3547         uint8_t *numResourceInterfaces)
3548 {
3549     OCResourceInterface *pointer = NULL;
3550     OCResource *resource = NULL;
3551
3552     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3553     VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
3554
3555     *numResourceInterfaces = 0;
3556     resource = findResource((OCResource *) handle);
3557     if (resource)
3558     {
3559         pointer = resource->rsrcInterface;
3560         while (pointer)
3561         {
3562             *numResourceInterfaces = *numResourceInterfaces + 1;
3563             pointer = pointer->next;
3564         }
3565     }
3566     return OC_STACK_OK;
3567 }
3568
3569 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index)
3570 {
3571     OCResourceInterface *resourceInterface = NULL;
3572
3573     resourceInterface = findResourceInterfaceAtIndex(handle, index);
3574     if (resourceInterface)
3575     {
3576         return resourceInterface->name;
3577     }
3578     return (const char *) NULL;
3579 }
3580
3581 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
3582         uint8_t index)
3583 {
3584     OCResource *resource = NULL;
3585
3586     if (index >= MAX_CONTAINED_RESOURCES)
3587     {
3588         return NULL;
3589     }
3590
3591     resource = findResource((OCResource *) collectionHandle);
3592     if (!resource)
3593     {
3594         return NULL;
3595     }
3596
3597     return resource->rsrcResources[index];
3598 }
3599
3600 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
3601         OCEntityHandler entityHandler,
3602         void* callbackParam)
3603 {
3604     OCResource *resource = NULL;
3605
3606     // Validate parameters
3607     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3608
3609     // Use the handle to find the resource in the resource linked list
3610     resource = findResource((OCResource *)handle);
3611     if (!resource)
3612     {
3613         OIC_LOG(ERROR, TAG, "Resource not found");
3614         return OC_STACK_ERROR;
3615     }
3616
3617     // Bind the handler
3618     resource->entityHandler = entityHandler;
3619     resource->entityHandlerCallbackParam = callbackParam;
3620
3621 #ifdef WITH_PRESENCE
3622     if (presenceResource.handle)
3623     {
3624         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3625         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3626     }
3627 #endif
3628
3629     return OC_STACK_OK;
3630 }
3631
3632 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle)
3633 {
3634     OCResource *resource = NULL;
3635
3636     resource = findResource((OCResource *)handle);
3637     if (!resource)
3638     {
3639         OIC_LOG(ERROR, TAG, "Resource not found");
3640         return NULL;
3641     }
3642
3643     // Bind the handler
3644     return resource->entityHandler;
3645 }
3646
3647 void incrementSequenceNumber(OCResource * resPtr)
3648 {
3649     // Increment the sequence number
3650     resPtr->sequenceNum += 1;
3651     if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
3652     {
3653         resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
3654     }
3655     return;
3656 }
3657
3658 #ifdef WITH_PRESENCE
3659 OCStackResult SendPresenceNotification(OCResourceType *resourceType,
3660         OCPresenceTrigger trigger)
3661 {
3662     OCResource *resPtr = NULL;
3663     OCStackResult result = OC_STACK_ERROR;
3664     OCMethod method = OC_REST_PRESENCE;
3665     uint32_t maxAge = 0;
3666     resPtr = findResource((OCResource *) presenceResource.handle);
3667     if(NULL == resPtr)
3668     {
3669         return OC_STACK_NO_RESOURCE;
3670     }
3671
3672     if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
3673     {
3674         maxAge = presenceResource.presenceTTL;
3675
3676         result = SendAllObserverNotification(method, resPtr, maxAge,
3677                 trigger, resourceType, OC_LOW_QOS);
3678     }
3679
3680     return result;
3681 }
3682
3683 OCStackResult SendStopNotification()
3684 {
3685     OCResource *resPtr = NULL;
3686     OCStackResult result = OC_STACK_ERROR;
3687     OCMethod method = OC_REST_PRESENCE;
3688     resPtr = findResource((OCResource *) presenceResource.handle);
3689     if(NULL == resPtr)
3690     {
3691         return OC_STACK_NO_RESOURCE;
3692     }
3693
3694     // maxAge is 0. ResourceType is NULL.
3695     result = SendAllObserverNotification(method, resPtr, 0, OC_PRESENCE_TRIGGER_DELETE,
3696             NULL, OC_LOW_QOS);
3697
3698     return result;
3699 }
3700
3701 #endif // WITH_PRESENCE
3702 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos)
3703 {
3704     OCResource *resPtr = NULL;
3705     OCStackResult result = OC_STACK_ERROR;
3706     OCMethod method = OC_REST_NOMETHOD;
3707     uint32_t maxAge = 0;
3708
3709     OIC_LOG(INFO, TAG, "Notifying all observers");
3710 #ifdef WITH_PRESENCE
3711     if(handle == presenceResource.handle)
3712     {
3713         return OC_STACK_OK;
3714     }
3715 #endif // WITH_PRESENCE
3716     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3717
3718     // Verify that the resource exists
3719     resPtr = findResource ((OCResource *) handle);
3720     if (NULL == resPtr)
3721     {
3722         return OC_STACK_NO_RESOURCE;
3723     }
3724     else
3725     {
3726         //only increment in the case of regular observing (not presence)
3727         incrementSequenceNumber(resPtr);
3728         method = OC_REST_OBSERVE;
3729         maxAge = MAX_OBSERVE_AGE;
3730 #ifdef WITH_PRESENCE
3731         result = SendAllObserverNotification (method, resPtr, maxAge,
3732                 OC_PRESENCE_TRIGGER_DELETE, NULL, qos);
3733 #else
3734         result = SendAllObserverNotification (method, resPtr, maxAge, qos);
3735 #endif
3736         return result;
3737     }
3738 }
3739
3740 OCStackResult
3741 OCNotifyListOfObservers (OCResourceHandle handle,
3742                          OCObservationId  *obsIdList,
3743                          uint8_t          numberOfIds,
3744                          const OCRepPayload       *payload,
3745                          OCQualityOfService qos)
3746 {
3747     OIC_LOG(INFO, TAG, "Entering OCNotifyListOfObservers");
3748
3749     OCResource *resPtr = NULL;
3750     //TODO: we should allow the server to define this
3751     uint32_t maxAge = MAX_OBSERVE_AGE;
3752
3753     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3754     VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
3755     VERIFY_NON_NULL(payload, ERROR, OC_STACK_ERROR);
3756
3757     resPtr = findResource ((OCResource *) handle);
3758     if (NULL == resPtr || myStackMode == OC_CLIENT)
3759     {
3760         return OC_STACK_NO_RESOURCE;
3761     }
3762     else
3763     {
3764         incrementSequenceNumber(resPtr);
3765     }
3766     return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
3767             payload, maxAge, qos));
3768 }
3769
3770 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
3771 {
3772     OCStackResult result = OC_STACK_ERROR;
3773     OCServerRequest *serverRequest = NULL;
3774
3775     OIC_LOG(INFO, TAG, "Entering OCDoResponse");
3776
3777     // Validate input parameters
3778     VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
3779     VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
3780
3781     // Normal response
3782     // Get pointer to request info
3783     serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
3784     if(serverRequest)
3785     {
3786         // response handler in ocserverrequest.c. Usually HandleSingleResponse.
3787         result = serverRequest->ehResponseHandler(ehResponse);
3788     }
3789
3790     return result;
3791 }
3792
3793 //-----------------------------------------------------------------------------
3794 // Private internal function definitions
3795 //-----------------------------------------------------------------------------
3796 static OCDoHandle GenerateInvocationHandle()
3797 {
3798     OCDoHandle handle = NULL;
3799     // Generate token here, it will be deleted when the transaction is deleted
3800     handle = (OCDoHandle) OICMalloc(sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3801     if (handle)
3802     {
3803         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3804     }
3805
3806     return handle;
3807 }
3808
3809 #ifdef WITH_PRESENCE
3810 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
3811         OCResourceProperty resourceProperties, uint8_t enable)
3812 {
3813     if (!inputProperty)
3814     {
3815         return OC_STACK_INVALID_PARAM;
3816     }
3817     if (resourceProperties
3818             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW))
3819     {
3820         OIC_LOG(ERROR, TAG, "Invalid property");
3821         return OC_STACK_INVALID_PARAM;
3822     }
3823     if(!enable)
3824     {
3825         *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
3826     }
3827     else
3828     {
3829         *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
3830     }
3831     return OC_STACK_OK;
3832 }
3833 #endif
3834
3835 OCStackResult initResources()
3836 {
3837     OCStackResult result = OC_STACK_OK;
3838
3839     headResource = NULL;
3840     tailResource = NULL;
3841     // Init Virtual Resources
3842 #ifdef WITH_PRESENCE
3843     presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
3844
3845     result = OCCreateResource(&presenceResource.handle,
3846             OC_RSRVD_RESOURCE_TYPE_PRESENCE,
3847             "core.r",
3848             OC_RSRVD_PRESENCE_URI,
3849             NULL,
3850             NULL,
3851             OC_OBSERVABLE);
3852     //make resource inactive
3853     result = OCChangeResourceProperty(
3854             &(((OCResource *) presenceResource.handle)->resourceProperties),
3855             OC_ACTIVE, 0);
3856 #endif
3857 #ifndef WITH_ARDUINO
3858     if (result == OC_STACK_OK)
3859     {
3860         result = SRMInitSecureResources();
3861     }
3862 #endif
3863
3864     if(result == OC_STACK_OK)
3865     {
3866         result = OCCreateResource(&deviceResource,
3867                                   OC_RSRVD_RESOURCE_TYPE_DEVICE,
3868                                   OC_RSRVD_INTERFACE_DEFAULT,
3869                                   OC_RSRVD_DEVICE_URI,
3870                                   NULL,
3871                                   NULL,
3872                                   OC_DISCOVERABLE);
3873         if(result == OC_STACK_OK)
3874         {
3875             result = BindResourceInterfaceToResource((OCResource *)deviceResource,
3876                                                      OC_RSRVD_INTERFACE_READ);
3877         }
3878     }
3879
3880     if(result == OC_STACK_OK)
3881     {
3882         result = OCCreateResource(&platformResource,
3883                                   OC_RSRVD_RESOURCE_TYPE_PLATFORM,
3884                                   OC_RSRVD_INTERFACE_DEFAULT,
3885                                   OC_RSRVD_PLATFORM_URI,
3886                                   NULL,
3887                                   NULL,
3888                                   OC_DISCOVERABLE);
3889         if(result == OC_STACK_OK)
3890         {
3891             result = BindResourceInterfaceToResource((OCResource *)platformResource,
3892                                                      OC_RSRVD_INTERFACE_READ);
3893         }
3894     }
3895
3896     return result;
3897 }
3898
3899 void insertResource(OCResource *resource)
3900 {
3901     if (!headResource)
3902     {
3903         headResource = resource;
3904         tailResource = resource;
3905     }
3906     else
3907     {
3908         tailResource->next = resource;
3909         tailResource = resource;
3910     }
3911     resource->next = NULL;
3912 }
3913
3914 OCResource *findResource(OCResource *resource)
3915 {
3916     OCResource *pointer = headResource;
3917
3918     while (pointer)
3919     {
3920         if (pointer == resource)
3921         {
3922             return resource;
3923         }
3924         pointer = pointer->next;
3925     }
3926     return NULL;
3927 }
3928
3929 void deleteAllResources()
3930 {
3931     OCResource *pointer = headResource;
3932     OCResource *temp = NULL;
3933
3934     while (pointer)
3935     {
3936         temp = pointer->next;
3937 #ifdef WITH_PRESENCE
3938         if (pointer != (OCResource *) presenceResource.handle)
3939         {
3940 #endif // WITH_PRESENCE
3941             deleteResource(pointer);
3942 #ifdef WITH_PRESENCE
3943         }
3944 #endif // WITH_PRESENCE
3945         pointer = temp;
3946     }
3947
3948     SRMDeInitSecureResources();
3949
3950 #ifdef WITH_PRESENCE
3951     // Ensure that the last resource to be deleted is the presence resource. This allows for all
3952     // presence notification attributed to their deletion to be processed.
3953     deleteResource((OCResource *) presenceResource.handle);
3954 #endif // WITH_PRESENCE
3955 }
3956
3957 OCStackResult deleteResource(OCResource *resource)
3958 {
3959     OCResource *prev = NULL;
3960     OCResource *temp = NULL;
3961     if(!resource)
3962     {
3963         OIC_LOG(DEBUG,TAG,"resource is NULL");
3964         return OC_STACK_INVALID_PARAM;
3965     }
3966
3967     OIC_LOG_V (INFO, TAG, "Deleting resource %s", resource->uri);
3968
3969     temp = headResource;
3970     while (temp)
3971     {
3972         if (temp == resource)
3973         {
3974             // Invalidate all Resource Properties.
3975             resource->resourceProperties = (OCResourceProperty) 0;
3976 #ifdef WITH_PRESENCE
3977             if(resource != (OCResource *) presenceResource.handle)
3978             {
3979 #endif // WITH_PRESENCE
3980                 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
3981 #ifdef WITH_PRESENCE
3982             }
3983
3984             if(presenceResource.handle)
3985             {
3986                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3987                 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_DELETE);
3988             }
3989 #endif
3990             // Only resource in list.
3991             if (temp == headResource && temp == tailResource)
3992             {
3993                 headResource = NULL;
3994                 tailResource = NULL;
3995             }
3996             // Deleting head.
3997             else if (temp == headResource)
3998             {
3999                 headResource = temp->next;
4000             }
4001             // Deleting tail.
4002             else if (temp == tailResource)
4003             {
4004                 tailResource = prev;
4005                 tailResource->next = NULL;
4006             }
4007             else
4008             {
4009                 prev->next = temp->next;
4010             }
4011
4012             deleteResourceElements(temp);
4013             OICFree(temp);
4014             return OC_STACK_OK;
4015         }
4016         else
4017         {
4018             prev = temp;
4019             temp = temp->next;
4020         }
4021     }
4022
4023     return OC_STACK_ERROR;
4024 }
4025
4026 void deleteResourceElements(OCResource *resource)
4027 {
4028     if (!resource)
4029     {
4030         return;
4031     }
4032
4033     OICFree(resource->uri);
4034     deleteResourceType(resource->rsrcType);
4035     deleteResourceInterface(resource->rsrcInterface);
4036 }
4037
4038 void deleteResourceType(OCResourceType *resourceType)
4039 {
4040     OCResourceType *pointer = resourceType;
4041     OCResourceType *next = NULL;
4042
4043     while (pointer)
4044     {
4045         next = pointer->next;
4046         OICFree(pointer->resourcetypename);
4047         OICFree(pointer);
4048         pointer = next;
4049     }
4050 }
4051
4052 void deleteResourceInterface(OCResourceInterface *resourceInterface)
4053 {
4054     OCResourceInterface *pointer = resourceInterface;
4055     OCResourceInterface *next = NULL;
4056
4057     while (pointer)
4058     {
4059         next = pointer->next;
4060         OICFree(pointer->name);
4061         OICFree(pointer);
4062         pointer = next;
4063     }
4064 }
4065
4066 void insertResourceType(OCResource *resource, OCResourceType *resourceType)
4067 {
4068     OCResourceType *pointer = NULL;
4069     OCResourceType *previous = NULL;
4070     if (!resource || !resourceType)
4071     {
4072         return;
4073     }
4074     // resource type list is empty.
4075     else if (!resource->rsrcType)
4076     {
4077         resource->rsrcType = resourceType;
4078     }
4079     else
4080     {
4081         pointer = resource->rsrcType;
4082
4083         while (pointer)
4084         {
4085             if (!strcmp(resourceType->resourcetypename, pointer->resourcetypename))
4086             {
4087                 OIC_LOG_V(INFO, TAG, "Type %s already exists", resourceType->resourcetypename);
4088                 OICFree(resourceType->resourcetypename);
4089                 OICFree(resourceType);
4090                 return;
4091             }
4092             previous = pointer;
4093             pointer = pointer->next;
4094         }
4095         previous->next = resourceType;
4096     }
4097     resourceType->next = NULL;
4098
4099     OIC_LOG_V(INFO, TAG, "Added type %s to %s", resourceType->resourcetypename, resource->uri);
4100 }
4101
4102 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index)
4103 {
4104     OCResource *resource = NULL;
4105     OCResourceType *pointer = NULL;
4106
4107     // Find the specified resource
4108     resource = findResource((OCResource *) handle);
4109     if (!resource)
4110     {
4111         return NULL;
4112     }
4113
4114     // Make sure a resource has a resourcetype
4115     if (!resource->rsrcType)
4116     {
4117         return NULL;
4118     }
4119
4120     // Iterate through the list
4121     pointer = resource->rsrcType;
4122     for(uint8_t i = 0; i< index && pointer; ++i)
4123     {
4124         pointer = pointer->next;
4125     }
4126     return pointer;
4127 }
4128
4129 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
4130 {
4131     if(resourceTypeList && resourceTypeName)
4132     {
4133         OCResourceType * rtPointer = resourceTypeList;
4134         while(resourceTypeName && rtPointer)
4135         {
4136             if(rtPointer->resourcetypename &&
4137                     strcmp(resourceTypeName, (const char *)
4138                     (rtPointer->resourcetypename)) == 0)
4139             {
4140                 break;
4141             }
4142             rtPointer = rtPointer->next;
4143         }
4144         return rtPointer;
4145     }
4146     return NULL;
4147 }
4148
4149 /*
4150  * Insert a new interface into interface linked list only if not already present.
4151  * If alredy present, 2nd arg is free'd.
4152  * Default interface will always be first if present.
4153  */
4154 void insertResourceInterface(OCResource *resource, OCResourceInterface *newInterface)
4155 {
4156     OCResourceInterface *pointer = NULL;
4157     OCResourceInterface *previous = NULL;
4158
4159     newInterface->next = NULL;
4160
4161     OCResourceInterface **firstInterface = &(resource->rsrcInterface);
4162
4163     if (!*firstInterface)
4164     {
4165         *firstInterface = newInterface;
4166     }
4167     else if (strcmp(newInterface->name, OC_RSRVD_INTERFACE_DEFAULT) == 0)
4168     {
4169         if (strcmp((*firstInterface)->name, OC_RSRVD_INTERFACE_DEFAULT) == 0)
4170         {
4171             OICFree(newInterface->name);
4172             OICFree(newInterface);
4173             return;
4174         }
4175         else
4176         {
4177             newInterface->next = *firstInterface;
4178             *firstInterface = newInterface;
4179         }
4180     }
4181     else
4182     {
4183         pointer = *firstInterface;
4184         while (pointer)
4185         {
4186             if (strcmp(newInterface->name, pointer->name) == 0)
4187             {
4188                 OICFree(newInterface->name);
4189                 OICFree(newInterface);
4190                 return;
4191             }
4192             previous = pointer;
4193             pointer = pointer->next;
4194         }
4195         previous->next = newInterface;
4196     }
4197 }
4198
4199 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
4200         uint8_t index)
4201 {
4202     OCResource *resource = NULL;
4203     OCResourceInterface *pointer = NULL;
4204
4205     // Find the specified resource
4206     resource = findResource((OCResource *) handle);
4207     if (!resource)
4208     {
4209         return NULL;
4210     }
4211
4212     // Make sure a resource has a resourceinterface
4213     if (!resource->rsrcInterface)
4214     {
4215         return NULL;
4216     }
4217
4218     // Iterate through the list
4219     pointer = resource->rsrcInterface;
4220
4221     for (uint8_t i = 0; i < index && pointer; ++i)
4222     {
4223         pointer = pointer->next;
4224     }
4225     return pointer;
4226 }
4227
4228 /*
4229  * This function splits the uri using the '?' delimiter.
4230  * "uriWithoutQuery" is the block of characters between the beginning
4231  * till the delimiter or '\0' which ever comes first.
4232  * "query" is whatever is to the right of the delimiter if present.
4233  * No delimiter sets the query to NULL.
4234  * If either are present, they will be malloc'ed into the params 2, 3.
4235  * The first param, *uri is left untouched.
4236
4237  * NOTE: This function does not account for whitespace at the end of the uri NOR
4238  *       malformed uri's with '??'. Whitespace at the end will be assumed to be
4239  *       part of the query.
4240  */
4241 OCStackResult getQueryFromUri(const char * uri, char** query, char ** uriWithoutQuery)
4242 {
4243     if(!uri)
4244     {
4245         return OC_STACK_INVALID_URI;
4246     }
4247     if(!query || !uriWithoutQuery)
4248     {
4249         return OC_STACK_INVALID_PARAM;
4250     }
4251
4252     *query           = NULL;
4253     *uriWithoutQuery = NULL;
4254
4255     size_t uriWithoutQueryLen = 0;
4256     size_t queryLen = 0;
4257     size_t uriLen = strlen(uri);
4258
4259     char *pointerToDelimiter = strstr(uri, "?");
4260
4261     uriWithoutQueryLen = pointerToDelimiter == NULL ? uriLen : (size_t)(pointerToDelimiter - uri);
4262     queryLen = pointerToDelimiter == NULL ? 0 : uriLen - uriWithoutQueryLen - 1;
4263
4264     if (uriWithoutQueryLen)
4265     {
4266         *uriWithoutQuery =  (char *) OICCalloc(uriWithoutQueryLen + 1, 1);
4267         if (!*uriWithoutQuery)
4268         {
4269             goto exit;
4270         }
4271         OICStrcpy(*uriWithoutQuery, uriWithoutQueryLen +1, uri);
4272     }
4273     if (queryLen)
4274     {
4275         *query = (char *) OICCalloc(queryLen + 1, 1);
4276         if (!*query)
4277         {
4278             OICFree(*uriWithoutQuery);
4279             *uriWithoutQuery = NULL;
4280             goto exit;
4281         }
4282         OICStrcpy(*query, queryLen + 1, pointerToDelimiter + 1);
4283     }
4284
4285     return OC_STACK_OK;
4286
4287     exit:
4288         return OC_STACK_NO_MEMORY;
4289 }
4290
4291 const OicUuid_t* OCGetServerInstanceID(void)
4292 {
4293     static bool generated = false;
4294     static OicUuid_t sid;
4295     if (generated)
4296     {
4297         return &sid;
4298     }
4299
4300     if (GetDoxmDeviceID(&sid) != OC_STACK_OK)
4301     {
4302         OIC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
4303         return NULL;
4304     }
4305     generated = true;
4306     return &sid;
4307 }
4308
4309 const char* OCGetServerInstanceIDString(void)
4310 {
4311     static bool generated = false;
4312     static char sidStr[UUID_STRING_SIZE];
4313
4314     if(generated)
4315     {
4316         return sidStr;
4317     }
4318
4319     const OicUuid_t* sid = OCGetServerInstanceID();
4320
4321     if(OCConvertUuidToString(sid->id, sidStr) != RAND_UUID_OK)
4322     {
4323         OIC_LOG(FATAL, TAG, "Generate UUID String for Server Instance failed!");
4324         return NULL;
4325     }
4326
4327     generated = true;
4328     return sidStr;
4329 }
4330
4331 CAResult_t OCSelectNetwork()
4332 {
4333     CAResult_t retResult = CA_STATUS_FAILED;
4334     CAResult_t caResult = CA_STATUS_OK;
4335
4336     CATransportAdapter_t connTypes[] = {
4337             CA_ADAPTER_IP,
4338             CA_ADAPTER_RFCOMM_BTEDR,
4339             CA_ADAPTER_GATT_BTLE,
4340             CA_ADAPTER_NFC
4341 #ifdef RA_ADAPTER
4342             ,CA_ADAPTER_REMOTE_ACCESS
4343 #endif
4344
4345 #ifdef TCP_ADAPTER
4346             ,CA_ADAPTER_TCP
4347 #endif
4348         };
4349     int numConnTypes = sizeof(connTypes)/sizeof(connTypes[0]);
4350
4351     for(int i = 0; i<numConnTypes; i++)
4352     {
4353         // Ignore CA_NOT_SUPPORTED error. The CA Layer may have not compiled in the interface.
4354         if(caResult == CA_STATUS_OK || caResult == CA_NOT_SUPPORTED)
4355         {
4356            caResult = CASelectNetwork(connTypes[i]);
4357            if(caResult == CA_STATUS_OK)
4358            {
4359                retResult = CA_STATUS_OK;
4360            }
4361         }
4362     }
4363
4364     if(retResult != CA_STATUS_OK)
4365     {
4366         return caResult; // Returns error of appropriate transport that failed fatally.
4367     }
4368
4369     return retResult;
4370 }
4371
4372 OCStackResult CAResultToOCResult(CAResult_t caResult)
4373 {
4374     switch (caResult)
4375     {
4376         case CA_STATUS_OK:
4377             return OC_STACK_OK;
4378         case CA_STATUS_INVALID_PARAM:
4379             return OC_STACK_INVALID_PARAM;
4380         case CA_ADAPTER_NOT_ENABLED:
4381             return OC_STACK_ADAPTER_NOT_ENABLED;
4382         case CA_SERVER_STARTED_ALREADY:
4383             return OC_STACK_OK;
4384         case CA_SERVER_NOT_STARTED:
4385             return OC_STACK_ERROR;
4386         case CA_DESTINATION_NOT_REACHABLE:
4387             return OC_STACK_COMM_ERROR;
4388         case CA_SOCKET_OPERATION_FAILED:
4389             return OC_STACK_COMM_ERROR;
4390         case CA_SEND_FAILED:
4391             return OC_STACK_COMM_ERROR;
4392         case CA_RECEIVE_FAILED:
4393             return OC_STACK_COMM_ERROR;
4394         case CA_MEMORY_ALLOC_FAILED:
4395             return OC_STACK_NO_MEMORY;
4396         case CA_REQUEST_TIMEOUT:
4397             return OC_STACK_TIMEOUT;
4398         case CA_DESTINATION_DISCONNECTED:
4399             return OC_STACK_COMM_ERROR;
4400         case CA_STATUS_FAILED:
4401             return OC_STACK_ERROR;
4402         case CA_NOT_SUPPORTED:
4403             return OC_STACK_NOTIMPL;
4404         default:
4405             return OC_STACK_ERROR;
4406     }
4407 }