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