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