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