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