Merge remote-tracking branch 'origin/master' into easysetup, Provisioning Handler...
[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         da = (OCDevAddr *)OICCalloc(1, sizeof (OCDevAddr));
1870
1871         len = end - start;
1872         if (len >= sizeof(da->addr))
1873         {
1874             return OC_STACK_INVALID_URI;
1875         }
1876
1877         da = (OCDevAddr *)OICCalloc(sizeof (OCDevAddr), 1);
1878
1879         if (!da)
1880         {
1881             return OC_STACK_NO_MEMORY;
1882         }
1883         OICStrcpyPartial(da->addr, sizeof(da->addr), start, len);
1884         da->port = port;
1885         da->adapter = adapter;
1886         da->flags = flags;
1887         if (!strncmp(fullUri, "coaps:", 6))
1888         {
1889             da->flags = (OCTransportFlags)(da->flags|CA_SECURE);
1890         }
1891         *devAddr = da;
1892     }
1893
1894     // process resource uri, if any
1895     if (slash)
1896     {   // request uri and query
1897         size_t ulen = strlen(slash); // resource uri length
1898         size_t tlen = 0;      // resource type length
1899         char *type = NULL;
1900
1901         static const char strPresence[] = "/oic/ad?rt=";
1902         static const size_t lenPresence = sizeof(strPresence) - 1;
1903         if (!strncmp(slash, strPresence, lenPresence))
1904         {
1905             type = slash + lenPresence;
1906             tlen = ulen - lenPresence;
1907         }
1908         // resource uri
1909         if (resourceUri)
1910         {
1911             *resourceUri = (char *)OICMalloc(ulen + 1);
1912             if (!*resourceUri)
1913             {
1914                 result = OC_STACK_NO_MEMORY;
1915                 goto error;
1916             }
1917             strcpy(*resourceUri, slash);
1918         }
1919         // resource type
1920         if (type && resourceType)
1921         {
1922             *resourceType = (char *)OICMalloc(tlen + 1);
1923             if (!*resourceType)
1924             {
1925                 result = OC_STACK_NO_MEMORY;
1926                 goto error;
1927             }
1928
1929             OICStrcpy(*resourceType, (tlen+1), type);
1930         }
1931     }
1932
1933     return OC_STACK_OK;
1934
1935 error:
1936     // free all returned values
1937     if (devAddr)
1938     {
1939         OICFree(*devAddr);
1940     }
1941     if (resourceUri)
1942     {
1943         OICFree(*resourceUri);
1944     }
1945     if (resourceType)
1946     {
1947         OICFree(*resourceType);
1948     }
1949     return result;
1950 }
1951
1952 static OCStackResult OCPreparePresence(CAEndpoint_t *endpoint,
1953                                         char *resourceUri, char **requestUri)
1954 {
1955     char uri[CA_MAX_URI_LENGTH];
1956
1957     FormCanonicalPresenceUri(endpoint, resourceUri, uri);
1958
1959     *requestUri = OICStrdup(uri);
1960     if (!*requestUri)
1961     {
1962         return OC_STACK_NO_MEMORY;
1963     }
1964
1965     return OC_STACK_OK;
1966 }
1967
1968 /**
1969  * Discover or Perform requests on a specified resource
1970  */
1971 OCStackResult OCDoResource(OCDoHandle *handle,
1972                             OCMethod method,
1973                             const char *requestUri,
1974                             const OCDevAddr *destination,
1975                             OCPayload* payload,
1976                             OCConnectivityType connectivityType,
1977                             OCQualityOfService qos,
1978                             OCCallbackData *cbData,
1979                             OCHeaderOption *options,
1980                             uint8_t numOptions)
1981 {
1982     OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
1983
1984     // Validate input parameters
1985     VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
1986     VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
1987     VERIFY_NON_NULL(requestUri , FATAL, OC_STACK_INVALID_URI);
1988
1989     OCStackResult result = OC_STACK_ERROR;
1990     CAResult_t caResult;
1991     CAToken_t token = NULL;
1992     uint8_t tokenLength = CA_MAX_TOKEN_LEN;
1993     ClientCB *clientCB = NULL;
1994     OCDoHandle resHandle = NULL;
1995     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
1996     OCDevAddr tmpDevAddr = { OC_DEFAULT_ADAPTER };
1997     uint32_t ttl = 0;
1998     OCTransportAdapter adapter;
1999     OCTransportFlags flags;
2000     // the request contents are put here
2001     CARequestInfo_t requestInfo = {.method = CA_GET};
2002     // requestUri  will be parsed into the following three variables
2003     OCDevAddr *devAddr = NULL;
2004     char *resourceUri = NULL;
2005     char *resourceType = NULL;
2006
2007     // To track if memory is allocated for additional header options
2008     uint8_t hdrOptionMemAlloc = 0;
2009
2010     // This validation is broken, but doesn't cause harm
2011     size_t uriLen = strlen(requestUri );
2012     if ((result = verifyUriQueryLength(requestUri , uriLen)) != OC_STACK_OK)
2013     {
2014         goto exit;
2015     }
2016
2017     /*
2018      * Support original behavior with address on resourceUri argument.
2019      */
2020     adapter = (OCTransportAdapter)(connectivityType >> CT_ADAPTER_SHIFT);
2021     flags = (OCTransportFlags)(connectivityType & CT_MASK_FLAGS);
2022
2023     result = ParseRequestUri(requestUri, adapter, flags, &devAddr, &resourceUri, &resourceType);
2024
2025     if (result != OC_STACK_OK)
2026     {
2027         OC_LOG_V(DEBUG, TAG, "Unable to parse uri: %s", requestUri);
2028         goto exit;
2029     }
2030
2031     switch (method)
2032     {
2033     case OC_REST_GET:
2034     case OC_REST_OBSERVE:
2035     case OC_REST_OBSERVE_ALL:
2036     case OC_REST_CANCEL_OBSERVE:
2037         requestInfo.method = CA_GET;
2038         break;
2039     case OC_REST_PUT:
2040         requestInfo.method = CA_PUT;
2041         break;
2042     case OC_REST_POST:
2043         requestInfo.method = CA_POST;
2044         break;
2045     case OC_REST_DELETE:
2046         requestInfo.method = CA_DELETE;
2047         break;
2048     case OC_REST_DISCOVER:
2049         qos = OC_LOW_QOS;
2050         if (destination || devAddr)
2051         {
2052             requestInfo.isMulticast = false;
2053         }
2054         else
2055         {
2056             tmpDevAddr.adapter = adapter;
2057             tmpDevAddr.flags = flags;
2058             destination = &tmpDevAddr;
2059             requestInfo.isMulticast = true;
2060         }
2061         // CA_DISCOVER will become GET and isMulticast
2062         requestInfo.method = CA_GET;
2063         break;
2064 #ifdef WITH_PRESENCE
2065     case OC_REST_PRESENCE:
2066         // Replacing method type with GET because "presence"
2067         // is a stack layer only implementation.
2068         requestInfo.method = CA_GET;
2069         break;
2070 #endif
2071     default:
2072         result = OC_STACK_INVALID_METHOD;
2073         goto exit;
2074     }
2075
2076     if (!devAddr && !destination)
2077     {
2078         OC_LOG_V(DEBUG, TAG, "no devAddr and no destination");
2079         result = OC_STACK_INVALID_PARAM;
2080         goto exit;
2081     }
2082
2083     /* If not original behavior, use destination argument */
2084     if (destination && !devAddr)
2085     {
2086         devAddr = (OCDevAddr *)OICMalloc(sizeof (OCDevAddr));
2087         if (!devAddr)
2088         {
2089             result = OC_STACK_NO_MEMORY;
2090             goto exit;
2091         }
2092         *devAddr = *destination;
2093     }
2094
2095     resHandle = GenerateInvocationHandle();
2096     if (!resHandle)
2097     {
2098         result = OC_STACK_NO_MEMORY;
2099         goto exit;
2100     }
2101
2102     caResult = CAGenerateToken(&token, tokenLength);
2103     if (caResult != CA_STATUS_OK)
2104     {
2105         OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
2106         result= OC_STACK_ERROR;
2107         goto exit;
2108     }
2109
2110     // fill in request data
2111     requestInfo.info.type = qualityOfServiceToMessageType(qos);
2112     requestInfo.info.token = token;
2113     requestInfo.info.tokenLength = tokenLength;
2114     requestInfo.info.resourceUri = resourceUri;
2115
2116     if ((method == OC_REST_OBSERVE) || (method == OC_REST_OBSERVE_ALL))
2117     {
2118         result = CreateObserveHeaderOption (&(requestInfo.info.options),
2119                                     options, numOptions, OC_OBSERVE_REGISTER);
2120         if (result != OC_STACK_OK)
2121         {
2122             goto exit;
2123         }
2124         hdrOptionMemAlloc = 1;
2125         requestInfo.info.numOptions = numOptions + 1;
2126     }
2127     else
2128     {
2129         requestInfo.info.options = (CAHeaderOption_t*)options;
2130         requestInfo.info.numOptions = numOptions;
2131     }
2132
2133     CopyDevAddrToEndpoint(devAddr, &endpoint);
2134
2135     if(payload)
2136     {
2137         if((result =
2138             OCConvertPayload(payload, &requestInfo.info.payload, &requestInfo.info.payloadSize))
2139                 != OC_STACK_OK)
2140         {
2141             OC_LOG(ERROR, TAG, PCF("Failed to create CBOR Payload"));
2142             goto exit;
2143         }
2144     }
2145     else
2146     {
2147         requestInfo.info.payload = NULL;
2148         requestInfo.info.payloadSize = 0;
2149     }
2150
2151     if (result != OC_STACK_OK)
2152     {
2153         OC_LOG(ERROR, TAG, PCF("CACreateEndpoint error"));
2154         goto exit;
2155     }
2156
2157     // prepare for response
2158 #ifdef WITH_PRESENCE
2159     if (method == OC_REST_PRESENCE)
2160     {
2161         char *presenceUri = NULL;
2162         result = OCPreparePresence(&endpoint, resourceUri, &presenceUri);
2163         if (OC_STACK_OK != result)
2164         {
2165             goto exit;
2166         }
2167
2168         // Assign full presence uri as coap://ip:port/oic/ad to add to callback list.
2169         // Presence notification will form a canonical uri to
2170         // look for callbacks into the application.
2171         resourceUri = presenceUri;
2172     }
2173 #endif
2174
2175     ttl = GetTicks(MAX_CB_TIMEOUT_SECONDS * MILLISECONDS_PER_SECOND);
2176     result = AddClientCB(&clientCB, cbData, token, tokenLength, &resHandle,
2177                             method, devAddr, resourceUri, resourceType, ttl);
2178     if (OC_STACK_OK != result)
2179     {
2180         goto exit;
2181     }
2182
2183     devAddr = NULL;       // Client CB list entry now owns it
2184     resourceUri = NULL;   // Client CB list entry now owns it
2185     resourceType = NULL;  // Client CB list entry now owns it
2186
2187     // send request
2188     caResult = CASendRequest(&endpoint, &requestInfo);
2189     if (caResult != CA_STATUS_OK)
2190     {
2191         OC_LOG(ERROR, TAG, PCF("CASendRequest"));
2192         result = OC_STACK_COMM_ERROR;
2193         goto exit;
2194     }
2195
2196     if (handle)
2197     {
2198         *handle = resHandle;
2199     }
2200
2201 exit:
2202     if (result != OC_STACK_OK)
2203     {
2204         OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
2205         FindAndDeleteClientCB(clientCB);
2206         CADestroyToken(token);
2207         if (handle)
2208         {
2209             *handle = NULL;
2210         }
2211         OICFree(resHandle);
2212     }
2213
2214     // This is the owner of the payload object, so we free it
2215     OCPayloadDestroy(payload);
2216     OICFree(requestInfo.info.payload);
2217     OICFree(devAddr);
2218     OICFree(resourceUri);
2219     OICFree(resourceType);
2220     if (hdrOptionMemAlloc)
2221     {
2222         OICFree(requestInfo.info.options);
2223     }
2224     return result;
2225 }
2226
2227 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
2228         uint8_t numOptions)
2229 {
2230     /*
2231      * This ftn is implemented one of two ways in the case of observation:
2232      *
2233      * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
2234      *      Remove the callback associated on client side.
2235      *      When the next notification comes in from server,
2236      *      reply with RESET message to server.
2237      *      Keep in mind that the server will react to RESET only
2238      *      if the last notification was sent as CON
2239      *
2240      * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
2241      *      and it is associated with an observe request
2242      *      (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
2243      *      Send CON Observe request to server with
2244      *      observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
2245      *      Remove the callback associated on client side.
2246      */
2247     OCStackResult ret = OC_STACK_OK;
2248     CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2249     CAResult_t caResult;
2250     CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
2251     CARequestInfo_t requestInfo = {.method = CA_GET};
2252
2253     if(!handle)
2254     {
2255         return OC_STACK_INVALID_PARAM;
2256     }
2257
2258     ClientCB *clientCB = GetClientCB(NULL, 0, handle, NULL);
2259     if (!clientCB)
2260     {
2261         OC_LOG(ERROR, TAG, PCF("Client callback not found. Called OCCancel twice?"));
2262         goto Error;
2263     }
2264
2265     switch (clientCB->method)
2266     {
2267         case OC_REST_OBSERVE:
2268         case OC_REST_OBSERVE_ALL:
2269             OC_LOG_V(INFO, TAG, "Canceling observation for resource %s",
2270                                         clientCB->requestUri);
2271             if (qos != OC_HIGH_QOS)
2272             {
2273                 FindAndDeleteClientCB(clientCB);
2274                 break;
2275             }
2276             else
2277             {
2278                 OC_LOG(INFO, TAG, PCF("Cancelling observation as CONFIRMABLE"));
2279             }
2280
2281             requestData.type = qualityOfServiceToMessageType(qos);
2282             requestData.token = clientCB->token;
2283             requestData.tokenLength = clientCB->tokenLength;
2284             if (CreateObserveHeaderOption (&(requestData.options),
2285                     options, numOptions, OC_OBSERVE_DEREGISTER) != OC_STACK_OK)
2286             {
2287                 return OC_STACK_ERROR;
2288             }
2289             requestData.numOptions = numOptions + 1;
2290             requestData.resourceUri = OICStrdup (clientCB->requestUri);
2291
2292             requestInfo.method = CA_GET;
2293             requestInfo.info = requestData;
2294
2295             CopyDevAddrToEndpoint(clientCB->devAddr, &endpoint);
2296
2297             // send request
2298             caResult = CASendRequest(&endpoint, &requestInfo);
2299             if (caResult != CA_STATUS_OK)
2300             {
2301                 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
2302                 ret = OC_STACK_ERROR;
2303             }
2304             ret = CAResultToOCResult (caResult);
2305             break;
2306
2307 #ifdef WITH_PRESENCE
2308         case OC_REST_PRESENCE:
2309             FindAndDeleteClientCB(clientCB);
2310             break;
2311 #endif
2312
2313         default:
2314             ret = OC_STACK_INVALID_METHOD;
2315             break;
2316     }
2317
2318 Error:
2319     if (requestData.numOptions > 0)
2320     {
2321         OICFree(requestData.options);
2322     }
2323     if (requestData.resourceUri)
2324     {
2325         OICFree (requestData.resourceUri);
2326     }
2327     return ret;
2328 }
2329
2330 /**
2331  * @brief   Register Persistent storage callback.
2332  * @param   persistentStorageHandler [IN] Pointers to open, read, write, close & unlink handlers.
2333  * @return
2334  *     OC_STACK_OK    - No errors; Success
2335  *     OC_STACK_INVALID_PARAM - Invalid parameter
2336  */
2337 OCStackResult OCRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
2338 {
2339     OC_LOG(INFO, TAG, PCF("RegisterPersistentStorageHandler !!"));
2340     if(!persistentStorageHandler)
2341     {
2342         OC_LOG(ERROR, TAG, PCF("The persistent storage handler is invalid"));
2343         return OC_STACK_INVALID_PARAM;
2344     }
2345     else
2346     {
2347         if( !persistentStorageHandler->open ||
2348                 !persistentStorageHandler->close ||
2349                 !persistentStorageHandler->read ||
2350                 !persistentStorageHandler->unlink ||
2351                 !persistentStorageHandler->write)
2352         {
2353             OC_LOG(ERROR, TAG, PCF("The persistent storage handler is invalid"));
2354             return OC_STACK_INVALID_PARAM;
2355         }
2356     }
2357     return SRMRegisterPersistentStorageHandler(persistentStorageHandler);
2358 }
2359
2360 #ifdef WITH_PRESENCE
2361
2362 OCStackResult OCProcessPresence()
2363 {
2364     OCStackResult result = OC_STACK_OK;
2365
2366     // the following line floods the log with messages that are irrelevant
2367     // to most purposes.  Uncomment as needed.
2368     //OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
2369     ClientCB* cbNode = NULL;
2370     OCClientResponse clientResponse;
2371     OCStackApplicationResult cbResult = OC_STACK_DELETE_TRANSACTION;
2372
2373     LL_FOREACH(cbList, cbNode)
2374     {
2375         if (OC_REST_PRESENCE != cbNode->method || !cbNode->presence)
2376         {
2377             continue;
2378         }
2379
2380         uint32_t now = GetTicks(0);
2381         OC_LOG_V(DEBUG, TAG, "this TTL level %d",
2382                                                 cbNode->presence->TTLlevel);
2383         OC_LOG_V(DEBUG, TAG, "current ticks %d", now);
2384
2385         if (cbNode->presence->TTLlevel > PresenceTimeOutSize)
2386         {
2387             goto exit;
2388         }
2389
2390         if (cbNode->presence->TTLlevel < PresenceTimeOutSize)
2391         {
2392             OC_LOG_V(DEBUG, TAG, "timeout ticks %d",
2393                     cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
2394         }
2395         if (cbNode->presence->TTLlevel >= PresenceTimeOutSize)
2396         {
2397             OC_LOG(DEBUG, TAG, PCF("No more timeout ticks"));
2398
2399             clientResponse.sequenceNumber = 0;
2400             clientResponse.result = OC_STACK_PRESENCE_TIMEOUT;
2401             clientResponse.devAddr = *cbNode->devAddr;
2402             FixUpClientResponse(&clientResponse);
2403             clientResponse.payload = NULL;
2404
2405             // Increment the TTLLevel (going to a next state), so we don't keep
2406             // sending presence notification to client.
2407             cbNode->presence->TTLlevel++;
2408             OC_LOG_V(DEBUG, TAG, "moving to TTL level %d",
2409                                         cbNode->presence->TTLlevel);
2410
2411             cbResult = cbNode->callBack(cbNode->context, cbNode->handle, &clientResponse);
2412             if (cbResult == OC_STACK_DELETE_TRANSACTION)
2413             {
2414                 FindAndDeleteClientCB(cbNode);
2415             }
2416         }
2417
2418         if (now < cbNode->presence->timeOut[cbNode->presence->TTLlevel])
2419         {
2420             continue;
2421         }
2422
2423         CAResult_t caResult = CA_STATUS_OK;
2424         CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
2425         CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
2426         CARequestInfo_t requestInfo = {.method = CA_GET};
2427
2428         OC_LOG(DEBUG, TAG, PCF("time to test server presence"));
2429
2430         CopyDevAddrToEndpoint(cbNode->devAddr, &endpoint);
2431
2432         requestData.type = CA_MSG_NONCONFIRM;
2433         requestData.token = cbNode->token;
2434         requestData.tokenLength = cbNode->tokenLength;
2435         requestData.resourceUri = OC_RSRVD_PRESENCE_URI;
2436         requestInfo.method = CA_GET;
2437         requestInfo.info = requestData;
2438
2439         caResult = CASendRequest(&endpoint, &requestInfo);
2440
2441         if (caResult != CA_STATUS_OK)
2442         {
2443             OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
2444             goto exit;
2445         }
2446
2447         cbNode->presence->TTLlevel++;
2448         OC_LOG_V(DEBUG, TAG, "moving to TTL level %d", cbNode->presence->TTLlevel);
2449     }
2450 exit:
2451     if (result != OC_STACK_OK)
2452     {
2453         OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
2454     }
2455
2456     return result;
2457 }
2458 #endif // WITH_PRESENCE
2459
2460 OCStackResult OCProcess()
2461 {
2462 #ifdef WITH_PRESENCE
2463     OCProcessPresence();
2464 #endif
2465     CAHandleRequestResponse();
2466
2467     return OC_STACK_OK;
2468 }
2469
2470 #ifdef WITH_PRESENCE
2471 OCStackResult OCStartPresence(const uint32_t ttl)
2472 {
2473     uint8_t tokenLength = CA_MAX_TOKEN_LEN;
2474     OCChangeResourceProperty(
2475             &(((OCResource *)presenceResource.handle)->resourceProperties),
2476             OC_ACTIVE, 1);
2477
2478     if (OC_MAX_PRESENCE_TTL_SECONDS < ttl)
2479     {
2480         presenceResource.presenceTTL = OC_MAX_PRESENCE_TTL_SECONDS;
2481         OC_LOG(INFO, TAG, PCF("Setting Presence TTL to max value"));
2482     }
2483     else if (0 == ttl)
2484     {
2485         presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
2486         OC_LOG(INFO, TAG, PCF("Setting Presence TTL to default value"));
2487     }
2488     else
2489     {
2490         presenceResource.presenceTTL = ttl;
2491     }
2492     OC_LOG_V(DEBUG, TAG, "Presence TTL is %lu seconds", presenceResource.presenceTTL);
2493
2494     if (OC_PRESENCE_UNINITIALIZED == presenceState)
2495     {
2496         presenceState = OC_PRESENCE_INITIALIZED;
2497
2498         OCDevAddr devAddr = { OC_DEFAULT_ADAPTER };
2499
2500         CAToken_t caToken = NULL;
2501         CAResult_t caResult = CAGenerateToken(&caToken, tokenLength);
2502         if (caResult != CA_STATUS_OK)
2503         {
2504             OC_LOG(ERROR, TAG, PCF("CAGenerateToken error"));
2505             CADestroyToken(caToken);
2506             return OC_STACK_ERROR;
2507         }
2508
2509         AddObserver(OC_RSRVD_PRESENCE_URI, NULL, 0, caToken, tokenLength,
2510                 (OCResource *)presenceResource.handle, OC_LOW_QOS, &devAddr);
2511         CADestroyToken(caToken);
2512     }
2513
2514     // Each time OCStartPresence is called
2515     // a different random 32-bit integer number is used
2516     ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2517
2518     return SendPresenceNotification(((OCResource *)presenceResource.handle)->rsrcType,
2519             OC_PRESENCE_TRIGGER_CREATE);
2520 }
2521
2522 OCStackResult OCStopPresence()
2523 {
2524     OCStackResult result = OC_STACK_ERROR;
2525
2526     if(presenceResource.handle)
2527     {
2528         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2529
2530     // make resource inactive
2531     result = OCChangeResourceProperty(
2532             &(((OCResource *) presenceResource.handle)->resourceProperties),
2533             OC_ACTIVE, 0);
2534     }
2535
2536     if(result != OC_STACK_OK)
2537     {
2538         OC_LOG(ERROR, TAG,
2539                       PCF("Changing the presence resource properties to ACTIVE not successful"));
2540         return result;
2541     }
2542
2543     return SendStopNotification();
2544 }
2545 #endif
2546
2547 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler,
2548                                             void* callbackParameter)
2549 {
2550     defaultDeviceHandler = entityHandler;
2551     defaultDeviceHandlerCallbackParameter = callbackParameter;
2552
2553     return OC_STACK_OK;
2554 }
2555
2556 OCStackResult OCSetPlatformInfo(OCPlatformInfo platformInfo)
2557 {
2558     OC_LOG(INFO, TAG, PCF("Entering OCSetPlatformInfo"));
2559
2560     if(myStackMode ==  OC_SERVER || myStackMode == OC_CLIENT_SERVER)
2561     {
2562         if (validatePlatformInfo(platformInfo))
2563         {
2564             return SavePlatformInfo(platformInfo);
2565         }
2566         else
2567         {
2568             return OC_STACK_INVALID_PARAM;
2569         }
2570     }
2571     else
2572     {
2573         return OC_STACK_ERROR;
2574     }
2575 }
2576
2577 OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
2578 {
2579     OC_LOG(INFO, TAG, PCF("Entering OCSetDeviceInfo"));
2580
2581     if (!deviceInfo.deviceName || deviceInfo.deviceName[0] == '\0')
2582     {
2583         OC_LOG(ERROR, TAG, PCF("Null or empty device name."));
2584         return OC_STACK_INVALID_PARAM;
2585     }
2586
2587     return SaveDeviceInfo(deviceInfo);
2588 }
2589
2590 OCStackResult OCCreateResource(OCResourceHandle *handle,
2591         const char *resourceTypeName,
2592         const char *resourceInterfaceName,
2593         const char *uri, OCEntityHandler entityHandler,
2594         void* callbackParam,
2595         uint8_t resourceProperties)
2596 {
2597
2598     OCResource *pointer = NULL;
2599     char *str = NULL;
2600     OCStackResult result = OC_STACK_ERROR;
2601
2602     OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
2603
2604     if(myStackMode == OC_CLIENT)
2605     {
2606         return OC_STACK_INVALID_PARAM;
2607     }
2608     // Validate parameters
2609     if(!uri || uri[0]=='\0' || strlen(uri)>=MAX_URI_LENGTH )
2610     {
2611         OC_LOG(ERROR, TAG, PCF("URI is empty or too long"));
2612         return OC_STACK_INVALID_URI;
2613     }
2614     // Is it presented during resource discovery?
2615     if (!handle || !resourceTypeName || resourceTypeName[0] == '\0' )
2616     {
2617         OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
2618         return OC_STACK_INVALID_PARAM;
2619     }
2620
2621     if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0)
2622     {
2623         resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
2624     }
2625
2626     // Make sure resourceProperties bitmask has allowed properties specified
2627     if (resourceProperties
2628             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE |
2629                OC_EXPLICIT_DISCOVERABLE))
2630     {
2631         OC_LOG(ERROR, TAG, PCF("Invalid property"));
2632         return OC_STACK_INVALID_PARAM;
2633     }
2634
2635     // If the headResource is NULL, then no resources have been created...
2636     pointer = headResource;
2637     if (pointer)
2638     {
2639         // At least one resources is in the resource list, so we need to search for
2640         // repeated URLs, which are not allowed.  If a repeat is found, exit with an error
2641         while (pointer)
2642         {
2643             if (strncmp(uri, pointer->uri, MAX_URI_LENGTH) == 0)
2644             {
2645                 OC_LOG_V(ERROR, TAG, "Resource %s already exists", uri);
2646                 return OC_STACK_INVALID_PARAM;
2647             }
2648             pointer = pointer->next;
2649         }
2650     }
2651     // Create the pointer and insert it into the resource list
2652     pointer = (OCResource *) OICCalloc(1, sizeof(OCResource));
2653     if (!pointer)
2654     {
2655         result = OC_STACK_NO_MEMORY;
2656         goto exit;
2657     }
2658     pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
2659
2660     insertResource(pointer);
2661
2662     // Set the uri
2663     str = OICStrdup(uri);
2664     if (!str)
2665     {
2666         result = OC_STACK_NO_MEMORY;
2667         goto exit;
2668     }
2669     pointer->uri = str;
2670
2671     // Set properties.  Set OC_ACTIVE
2672     pointer->resourceProperties = (OCResourceProperty) (resourceProperties
2673             | OC_ACTIVE);
2674
2675     // Add the resourcetype to the resource
2676     result = BindResourceTypeToResource(pointer, resourceTypeName);
2677     if (result != OC_STACK_OK)
2678     {
2679         OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
2680         goto exit;
2681     }
2682
2683     // Add the resourceinterface to the resource
2684     result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
2685     if (result != OC_STACK_OK)
2686     {
2687         OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
2688         goto exit;
2689     }
2690
2691     // If an entity handler has been passed, attach it to the newly created
2692     // resource.  Otherwise, set the default entity handler.
2693     if (entityHandler)
2694     {
2695         pointer->entityHandler = entityHandler;
2696         pointer->entityHandlerCallbackParam = callbackParam;
2697     }
2698     else
2699     {
2700         pointer->entityHandler = defaultResourceEHandler;
2701         pointer->entityHandlerCallbackParam = NULL;
2702     }
2703
2704     *handle = pointer;
2705     result = OC_STACK_OK;
2706
2707 #ifdef WITH_PRESENCE
2708     if (presenceResource.handle)
2709     {
2710         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2711         SendPresenceNotification(pointer->rsrcType, OC_PRESENCE_TRIGGER_CREATE);
2712     }
2713 #endif
2714 exit:
2715     if (result != OC_STACK_OK)
2716     {
2717         // Deep delete of resource and other dynamic elements that it contains
2718         deleteResource(pointer);
2719         OICFree(str);
2720     }
2721     return result;
2722 }
2723
2724
2725 OCStackResult OCBindResource(
2726         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
2727 {
2728     OCResource *resource = NULL;
2729     uint8_t i = 0;
2730
2731     OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
2732
2733     // Validate parameters
2734     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2735     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2736     // Container cannot contain itself
2737     if (collectionHandle == resourceHandle)
2738     {
2739         OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
2740         return OC_STACK_INVALID_PARAM;
2741     }
2742
2743     // Use the handle to find the resource in the resource linked list
2744     resource = findResource((OCResource *) collectionHandle);
2745     if (!resource)
2746     {
2747         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2748         return OC_STACK_INVALID_PARAM;
2749     }
2750
2751     // Look for an open slot to add add the child resource.
2752     // If found, add it and return success
2753     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
2754     {
2755         if (!resource->rsrcResources[i])
2756         {
2757             resource->rsrcResources[i] = (OCResource *) resourceHandle;
2758             OC_LOG(INFO, TAG, PCF("resource bound"));
2759
2760 #ifdef WITH_PRESENCE
2761             if (presenceResource.handle)
2762             {
2763                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2764                 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
2765                         OC_PRESENCE_TRIGGER_CHANGE);
2766             }
2767 #endif
2768             return OC_STACK_OK;
2769
2770         }
2771     }
2772
2773     // Unable to add resourceHandle, so return error
2774     return OC_STACK_ERROR;
2775 }
2776
2777 OCStackResult OCUnBindResource(
2778         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle)
2779 {
2780     OCResource *resource = NULL;
2781     uint8_t i = 0;
2782
2783     OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
2784
2785     // Validate parameters
2786     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
2787     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
2788     // Container cannot contain itself
2789     if (collectionHandle == resourceHandle)
2790     {
2791         OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
2792         return OC_STACK_INVALID_PARAM;
2793     }
2794
2795     // Use the handle to find the resource in the resource linked list
2796     resource = findResource((OCResource *) collectionHandle);
2797     if (!resource)
2798     {
2799         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
2800         return OC_STACK_INVALID_PARAM;
2801     }
2802
2803     // Look for an open slot to add add the child resource.
2804     // If found, add it and return success
2805     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++)
2806     {
2807         if (resourceHandle == resource->rsrcResources[i])
2808         {
2809             resource->rsrcResources[i] = (OCResource *) NULL;
2810             OC_LOG(INFO, TAG, PCF("resource unbound"));
2811
2812             // Send notification when resource is unbounded successfully.
2813 #ifdef WITH_PRESENCE
2814             if (presenceResource.handle)
2815             {
2816                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2817                 SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType,
2818                         OC_PRESENCE_TRIGGER_CHANGE);
2819             }
2820 #endif
2821             return OC_STACK_OK;
2822         }
2823     }
2824
2825     OC_LOG(INFO, TAG, PCF("resource not found in collection"));
2826
2827     // Unable to add resourceHandle, so return error
2828     return OC_STACK_ERROR;
2829 }
2830
2831 OCStackResult BindResourceTypeToResource(OCResource* resource,
2832                                             const char *resourceTypeName)
2833 {
2834     OCResourceType *pointer = NULL;
2835     char *str = NULL;
2836     OCStackResult result = OC_STACK_ERROR;
2837
2838     VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
2839
2840     pointer = (OCResourceType *) OICCalloc(1, sizeof(OCResourceType));
2841     if (!pointer)
2842     {
2843         result = OC_STACK_NO_MEMORY;
2844         goto exit;
2845     }
2846
2847     str = OICStrdup(resourceTypeName);
2848     if (!str)
2849     {
2850         result = OC_STACK_NO_MEMORY;
2851         goto exit;
2852     }
2853     pointer->resourcetypename = str;
2854
2855     insertResourceType(resource, pointer);
2856     result = OC_STACK_OK;
2857
2858     exit:
2859     if (result != OC_STACK_OK)
2860     {
2861         OICFree(pointer);
2862         OICFree(str);
2863     }
2864
2865     return result;
2866 }
2867
2868 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
2869         const char *resourceInterfaceName)
2870 {
2871     OCResourceInterface *pointer = NULL;
2872     char *str = NULL;
2873     OCStackResult result = OC_STACK_ERROR;
2874
2875     VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
2876
2877     OC_LOG_V(INFO, TAG, "Binding %s interface to %s", resourceInterfaceName, resource->uri);
2878
2879     pointer = (OCResourceInterface *) OICCalloc(1, sizeof(OCResourceInterface));
2880     if (!pointer)
2881     {
2882         result = OC_STACK_NO_MEMORY;
2883         goto exit;
2884     }
2885
2886     str = OICStrdup(resourceInterfaceName);
2887     if (!str)
2888     {
2889         result = OC_STACK_NO_MEMORY;
2890         goto exit;
2891     }
2892     pointer->name = str;
2893
2894     // Bind the resourceinterface to the resource
2895     insertResourceInterface(resource, pointer);
2896
2897     result = OC_STACK_OK;
2898
2899     exit:
2900     if (result != OC_STACK_OK)
2901     {
2902         OICFree(pointer);
2903         OICFree(str);
2904     }
2905
2906     return result;
2907 }
2908
2909 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
2910         const char *resourceTypeName)
2911 {
2912
2913     OCStackResult result = OC_STACK_ERROR;
2914     OCResource *resource = NULL;
2915
2916     resource = findResource((OCResource *) handle);
2917     if (!resource)
2918     {
2919         OC_LOG(ERROR, TAG, PCF("Resource not found"));
2920         return OC_STACK_ERROR;
2921     }
2922
2923     result = BindResourceTypeToResource(resource, resourceTypeName);
2924
2925 #ifdef WITH_PRESENCE
2926     if(presenceResource.handle)
2927     {
2928         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2929         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
2930     }
2931 #endif
2932
2933     return result;
2934 }
2935
2936 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
2937         const char *resourceInterfaceName)
2938 {
2939
2940     OCStackResult result = OC_STACK_ERROR;
2941     OCResource *resource = NULL;
2942
2943     resource = findResource((OCResource *) handle);
2944     if (!resource)
2945     {
2946         OC_LOG(ERROR, TAG, PCF("Resource not found"));
2947         return OC_STACK_ERROR;
2948     }
2949
2950     result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
2951
2952 #ifdef WITH_PRESENCE
2953     if (presenceResource.handle)
2954     {
2955         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2956         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
2957     }
2958 #endif
2959
2960     return result;
2961 }
2962
2963 OCStackResult OCGetNumberOfResources(uint8_t *numResources)
2964 {
2965     OCResource *pointer = headResource;
2966
2967     VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
2968     *numResources = 0;
2969     while (pointer)
2970     {
2971         *numResources = *numResources + 1;
2972         pointer = pointer->next;
2973     }
2974     return OC_STACK_OK;
2975 }
2976
2977 OCResourceHandle OCGetResourceHandle(uint8_t index)
2978 {
2979     OCResource *pointer = headResource;
2980
2981     for( uint8_t i = 0; i < index && pointer; ++i)
2982     {
2983         pointer = pointer->next;
2984     }
2985     return (OCResourceHandle) pointer;
2986 }
2987
2988 OCStackResult OCDeleteResource(OCResourceHandle handle)
2989 {
2990     if (!handle)
2991     {
2992         OC_LOG(ERROR, TAG, PCF("Invalid handle for deletion"));
2993         return OC_STACK_INVALID_PARAM;
2994     }
2995
2996     OCResource *resource = findResource((OCResource *) handle);
2997     if (resource == NULL)
2998     {
2999         OC_LOG(ERROR, TAG, PCF("Resource not found"));
3000         return OC_STACK_NO_RESOURCE;
3001     }
3002
3003     if (deleteResource((OCResource *) handle) != OC_STACK_OK)
3004     {
3005         OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
3006         return OC_STACK_ERROR;
3007     }
3008
3009     return OC_STACK_OK;
3010 }
3011
3012 const char *OCGetResourceUri(OCResourceHandle handle)
3013 {
3014     OCResource *resource = NULL;
3015
3016     resource = findResource((OCResource *) handle);
3017     if (resource)
3018     {
3019         return resource->uri;
3020     }
3021     return (const char *) NULL;
3022 }
3023
3024 OCResourceProperty OCGetResourceProperties(OCResourceHandle handle)
3025 {
3026     OCResource *resource = NULL;
3027
3028     resource = findResource((OCResource *) handle);
3029     if (resource)
3030     {
3031         return resource->resourceProperties;
3032     }
3033     return (OCResourceProperty)-1;
3034 }
3035
3036 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
3037         uint8_t *numResourceTypes)
3038 {
3039     OCResource *resource = NULL;
3040     OCResourceType *pointer = NULL;
3041
3042     VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
3043     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3044
3045     *numResourceTypes = 0;
3046
3047     resource = findResource((OCResource *) handle);
3048     if (resource)
3049     {
3050         pointer = resource->rsrcType;
3051         while (pointer)
3052         {
3053             *numResourceTypes = *numResourceTypes + 1;
3054             pointer = pointer->next;
3055         }
3056     }
3057     return OC_STACK_OK;
3058 }
3059
3060 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index)
3061 {
3062     OCResourceType *resourceType = NULL;
3063
3064     resourceType = findResourceTypeAtIndex(handle, index);
3065     if (resourceType)
3066     {
3067         return resourceType->resourcetypename;
3068     }
3069     return (const char *) NULL;
3070 }
3071
3072 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
3073         uint8_t *numResourceInterfaces)
3074 {
3075     OCResourceInterface *pointer = NULL;
3076     OCResource *resource = NULL;
3077
3078     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3079     VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
3080
3081     *numResourceInterfaces = 0;
3082     resource = findResource((OCResource *) handle);
3083     if (resource)
3084     {
3085         pointer = resource->rsrcInterface;
3086         while (pointer)
3087         {
3088             *numResourceInterfaces = *numResourceInterfaces + 1;
3089             pointer = pointer->next;
3090         }
3091     }
3092     return OC_STACK_OK;
3093 }
3094
3095 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index)
3096 {
3097     OCResourceInterface *resourceInterface = NULL;
3098
3099     resourceInterface = findResourceInterfaceAtIndex(handle, index);
3100     if (resourceInterface)
3101     {
3102         return resourceInterface->name;
3103     }
3104     return (const char *) NULL;
3105 }
3106
3107 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
3108         uint8_t index)
3109 {
3110     OCResource *resource = NULL;
3111
3112     if (index >= MAX_CONTAINED_RESOURCES)
3113     {
3114         return NULL;
3115     }
3116
3117     resource = findResource((OCResource *) collectionHandle);
3118     if (!resource)
3119     {
3120         return NULL;
3121     }
3122
3123     return resource->rsrcResources[index];
3124 }
3125
3126 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
3127         OCEntityHandler entityHandler,
3128         void* callbackParam)
3129 {
3130     OCResource *resource = NULL;
3131
3132     // Validate parameters
3133     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
3134
3135     // Use the handle to find the resource in the resource linked list
3136     resource = findResource((OCResource *)handle);
3137     if (!resource)
3138     {
3139         OC_LOG(ERROR, TAG, PCF("Resource not found"));
3140         return OC_STACK_ERROR;
3141     }
3142
3143     // Bind the handler
3144     resource->entityHandler = entityHandler;
3145     resource->entityHandlerCallbackParam = callbackParam;
3146
3147 #ifdef WITH_PRESENCE
3148     if (presenceResource.handle)
3149     {
3150         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3151         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
3152     }
3153 #endif
3154
3155     return OC_STACK_OK;
3156 }
3157
3158 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle)
3159 {
3160     OCResource *resource = NULL;
3161
3162     resource = findResource((OCResource *)handle);
3163     if (!resource)
3164     {
3165         OC_LOG(ERROR, TAG, PCF("Resource not found"));
3166         return NULL;
3167     }
3168
3169     // Bind the handler
3170     return resource->entityHandler;
3171 }
3172
3173 void incrementSequenceNumber(OCResource * resPtr)
3174 {
3175     // Increment the sequence number
3176     resPtr->sequenceNum += 1;
3177     if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
3178     {
3179         resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
3180     }
3181     return;
3182 }
3183
3184 #ifdef WITH_PRESENCE
3185 OCStackResult SendPresenceNotification(OCResourceType *resourceType,
3186         OCPresenceTrigger trigger)
3187 {
3188     OCResource *resPtr = NULL;
3189     OCStackResult result = OC_STACK_ERROR;
3190     OCMethod method = OC_REST_PRESENCE;
3191     uint32_t maxAge = 0;
3192     resPtr = findResource((OCResource *) presenceResource.handle);
3193     if(NULL == resPtr)
3194     {
3195         return OC_STACK_NO_RESOURCE;
3196     }
3197
3198     if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
3199     {
3200         maxAge = presenceResource.presenceTTL;
3201
3202         result = SendAllObserverNotification(method, resPtr, maxAge,
3203                 trigger, resourceType, OC_LOW_QOS);
3204     }
3205
3206     return result;
3207 }
3208
3209 OCStackResult SendStopNotification()
3210 {
3211     OCResource *resPtr = NULL;
3212     OCStackResult result = OC_STACK_ERROR;
3213     OCMethod method = OC_REST_PRESENCE;
3214     resPtr = findResource((OCResource *) presenceResource.handle);
3215     if(NULL == resPtr)
3216     {
3217         return OC_STACK_NO_RESOURCE;
3218     }
3219
3220     // maxAge is 0. ResourceType is NULL.
3221     result = SendAllObserverNotification(method, resPtr, 0, OC_PRESENCE_TRIGGER_DELETE,
3222             NULL, OC_LOW_QOS);
3223
3224     return result;
3225 }
3226
3227 #endif // WITH_PRESENCE
3228 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos)
3229 {
3230     OCResource *resPtr = NULL;
3231     OCStackResult result = OC_STACK_ERROR;
3232     OCMethod method = OC_REST_NOMETHOD;
3233     uint32_t maxAge = 0;
3234
3235     OC_LOG(INFO, TAG, PCF("Notifying all observers"));
3236 #ifdef WITH_PRESENCE
3237     if (handle == presenceResource.handle)
3238     {
3239         return OC_STACK_OK;
3240     }
3241 #endif // WITH_PRESENCE
3242     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3243
3244     // Verify that the resource exists
3245     resPtr = findResource ((OCResource *) handle);
3246     if (NULL == resPtr)
3247     {
3248         return OC_STACK_NO_RESOURCE;
3249     }
3250     else
3251     {
3252         //only increment in the case of regular observing (not presence)
3253         incrementSequenceNumber(resPtr);
3254         method = OC_REST_OBSERVE;
3255         maxAge = MAX_OBSERVE_AGE;
3256 #ifdef WITH_PRESENCE
3257         result = SendAllObserverNotification (method, resPtr, maxAge,
3258                 OC_PRESENCE_TRIGGER_DELETE, NULL, qos);
3259 #else
3260         result = SendAllObserverNotification (method, resPtr, maxAge, qos);
3261 #endif
3262         return result;
3263     }
3264 }
3265
3266 OCStackResult
3267 OCNotifyListOfObservers (OCResourceHandle handle,
3268                          OCObservationId  *obsIdList,
3269                          uint8_t          numberOfIds,
3270                          const OCRepPayload       *payload,
3271                          OCQualityOfService qos)
3272 {
3273     OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
3274
3275     OCResource *resPtr = NULL;
3276     //TODO: we should allow the server to define this
3277     uint32_t maxAge = MAX_OBSERVE_AGE;
3278
3279     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
3280     VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
3281     VERIFY_NON_NULL(payload, ERROR, OC_STACK_ERROR);
3282
3283     resPtr = findResource ((OCResource *) handle);
3284     if (NULL == resPtr || myStackMode == OC_CLIENT)
3285     {
3286         return OC_STACK_NO_RESOURCE;
3287     }
3288     else
3289     {
3290         incrementSequenceNumber(resPtr);
3291     }
3292     return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
3293             payload, maxAge, qos));
3294 }
3295
3296 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
3297 {
3298     OCStackResult result = OC_STACK_ERROR;
3299     OCServerRequest *serverRequest = NULL;
3300
3301     OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
3302
3303     // Validate input parameters
3304     VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
3305     VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
3306
3307     // Normal response
3308     // Get pointer to request info
3309     serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
3310     if(serverRequest)
3311     {
3312         // response handler in ocserverrequest.c. Usually HandleSingleResponse.
3313         result = serverRequest->ehResponseHandler(ehResponse);
3314     }
3315
3316     return result;
3317 }
3318
3319 //-----------------------------------------------------------------------------
3320 // Private internal function definitions
3321 //-----------------------------------------------------------------------------
3322 static OCDoHandle GenerateInvocationHandle()
3323 {
3324     OCDoHandle handle = NULL;
3325     // Generate token here, it will be deleted when the transaction is deleted
3326     handle = (OCDoHandle) OICMalloc(sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3327     if (handle)
3328     {
3329         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[CA_MAX_TOKEN_LEN]));
3330     }
3331
3332     return handle;
3333 }
3334
3335 #ifdef WITH_PRESENCE
3336 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
3337         OCResourceProperty resourceProperties, uint8_t enable)
3338 {
3339     if (!inputProperty)
3340     {
3341         return OC_STACK_INVALID_PARAM;
3342     }
3343     if (resourceProperties
3344             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW))
3345     {
3346         OC_LOG(ERROR, TAG, PCF("Invalid property"));
3347         return OC_STACK_INVALID_PARAM;
3348     }
3349     if(!enable)
3350     {
3351         *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
3352     }
3353     else
3354     {
3355         *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
3356     }
3357     return OC_STACK_OK;
3358 }
3359 #endif
3360
3361 OCStackResult initResources()
3362 {
3363     OCStackResult result = OC_STACK_OK;
3364
3365     headResource = NULL;
3366     tailResource = NULL;
3367     // Init Virtual Resources
3368 #ifdef WITH_PRESENCE
3369     presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
3370
3371     result = OCCreateResource(&presenceResource.handle,
3372             OC_RSRVD_RESOURCE_TYPE_PRESENCE,
3373             "core.r",
3374             OC_RSRVD_PRESENCE_URI,
3375             NULL,
3376             NULL,
3377             OC_OBSERVABLE);
3378     //make resource inactive
3379     result = OCChangeResourceProperty(
3380             &(((OCResource *) presenceResource.handle)->resourceProperties),
3381             OC_ACTIVE, 0);
3382 #endif
3383
3384     if (result == OC_STACK_OK)
3385     {
3386         result = SRMInitSecureResources();
3387     }
3388
3389     return result;
3390 }
3391
3392 void insertResource(OCResource *resource)
3393 {
3394     if (!headResource)
3395     {
3396         headResource = resource;
3397         tailResource = resource;
3398     }
3399     else
3400     {
3401         tailResource->next = resource;
3402         tailResource = resource;
3403     }
3404     resource->next = NULL;
3405 }
3406
3407 OCResource *findResource(OCResource *resource)
3408 {
3409     OCResource *pointer = headResource;
3410
3411     while (pointer)
3412     {
3413         if (pointer == resource)
3414         {
3415             return resource;
3416         }
3417         pointer = pointer->next;
3418     }
3419     return NULL;
3420 }
3421
3422 void deleteAllResources()
3423 {
3424     OCResource *pointer = headResource;
3425     OCResource *temp = NULL;
3426
3427     while (pointer)
3428     {
3429         temp = pointer->next;
3430 #ifdef WITH_PRESENCE
3431         if (pointer != (OCResource *) presenceResource.handle)
3432         {
3433 #endif // WITH_PRESENCE
3434             deleteResource(pointer);
3435 #ifdef WITH_PRESENCE
3436         }
3437 #endif // WITH_PRESENCE
3438         pointer = temp;
3439     }
3440
3441     SRMDeInitSecureResources();
3442
3443 #ifdef WITH_PRESENCE
3444     // Ensure that the last resource to be deleted is the presence resource. This allows for all
3445     // presence notification attributed to their deletion to be processed.
3446     deleteResource((OCResource *) presenceResource.handle);
3447 #endif // WITH_PRESENCE
3448 }
3449
3450 OCStackResult deleteResource(OCResource *resource)
3451 {
3452     OCResource *prev = NULL;
3453     OCResource *temp = NULL;
3454     if(!resource)
3455     {
3456         OC_LOG_V(DEBUG,TAG,"resource is NULL");
3457         return OC_STACK_INVALID_PARAM;
3458     }
3459
3460     OC_LOG_V (INFO, TAG, "Deleting resource %s", resource->uri);
3461
3462     temp = headResource;
3463     while (temp)
3464     {
3465         if (temp == resource)
3466         {
3467             // Invalidate all Resource Properties.
3468             resource->resourceProperties = (OCResourceProperty) 0;
3469 #ifdef WITH_PRESENCE
3470             if(resource != (OCResource *) presenceResource.handle)
3471             {
3472 #endif // WITH_PRESENCE
3473                 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
3474 #ifdef WITH_PRESENCE
3475             }
3476
3477             if(presenceResource.handle)
3478             {
3479                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
3480                 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_DELETE);
3481             }
3482 #endif
3483             // Only resource in list.
3484             if (temp == headResource && temp == tailResource)
3485             {
3486                 headResource = NULL;
3487                 tailResource = NULL;
3488             }
3489             // Deleting head.
3490             else if (temp == headResource)
3491             {
3492                 headResource = temp->next;
3493             }
3494             // Deleting tail.
3495             else if (temp == tailResource)
3496             {
3497                 tailResource = prev;
3498                 tailResource->next = NULL;
3499             }
3500             else
3501             {
3502                 prev->next = temp->next;
3503             }
3504
3505             deleteResourceElements(temp);
3506             OICFree(temp);
3507             return OC_STACK_OK;
3508         }
3509         else
3510         {
3511             prev = temp;
3512             temp = temp->next;
3513         }
3514     }
3515
3516     return OC_STACK_ERROR;
3517 }
3518
3519 void deleteResourceElements(OCResource *resource)
3520 {
3521     if (!resource)
3522     {
3523         return;
3524     }
3525
3526     OICFree(resource->uri);
3527     deleteResourceType(resource->rsrcType);
3528     deleteResourceInterface(resource->rsrcInterface);
3529 }
3530
3531 void deleteResourceType(OCResourceType *resourceType)
3532 {
3533     OCResourceType *pointer = resourceType;
3534     OCResourceType *next = NULL;
3535
3536     while (pointer)
3537     {
3538         next = pointer->next;
3539         OICFree(pointer->resourcetypename);
3540         OICFree(pointer);
3541         pointer = next;
3542     }
3543 }
3544
3545 void deleteResourceInterface(OCResourceInterface *resourceInterface)
3546 {
3547     OCResourceInterface *pointer = resourceInterface;
3548     OCResourceInterface *next = NULL;
3549
3550     while (pointer)
3551     {
3552         next = pointer->next;
3553         OICFree(pointer->name);
3554         OICFree(pointer);
3555         pointer = next;
3556     }
3557 }
3558
3559 void insertResourceType(OCResource *resource, OCResourceType *resourceType)
3560 {
3561     OCResourceType *pointer = NULL;
3562     OCResourceType *previous = NULL;
3563     if (!resource || !resourceType)
3564     {
3565         return;
3566     }
3567     // resource type list is empty.
3568     else if (!resource->rsrcType)
3569     {
3570         resource->rsrcType = resourceType;
3571     }
3572     else
3573     {
3574         pointer = resource->rsrcType;
3575
3576         while (pointer)
3577         {
3578             if (!strcmp(resourceType->resourcetypename, pointer->resourcetypename))
3579             {
3580                 OC_LOG_V(INFO, TAG, "Type %s already exists", resourceType->resourcetypename);
3581                 OICFree(resourceType->resourcetypename);
3582                 OICFree(resourceType);
3583                 return;
3584             }
3585             previous = pointer;
3586             pointer = pointer->next;
3587         }
3588         previous->next = resourceType;
3589     }
3590     resourceType->next = NULL;
3591
3592     OC_LOG_V(INFO, TAG, "Added type %s to %s", resourceType->resourcetypename, resource->uri);
3593 }
3594
3595 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index)
3596 {
3597     OCResource *resource = NULL;
3598     OCResourceType *pointer = NULL;
3599
3600     // Find the specified resource
3601     resource = findResource((OCResource *) handle);
3602     if (!resource)
3603     {
3604         return NULL;
3605     }
3606
3607     // Make sure a resource has a resourcetype
3608     if (!resource->rsrcType)
3609     {
3610         return NULL;
3611     }
3612
3613     // Iterate through the list
3614     pointer = resource->rsrcType;
3615     for(uint8_t i = 0; i< index && pointer; ++i)
3616     {
3617         pointer = pointer->next;
3618     }
3619     return pointer;
3620 }
3621
3622 OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
3623 {
3624     if(resourceTypeList && resourceTypeName)
3625     {
3626         OCResourceType * rtPointer = resourceTypeList;
3627         while(resourceTypeName && rtPointer)
3628         {
3629             if(rtPointer->resourcetypename &&
3630                     strcmp(resourceTypeName, (const char *)
3631                     (rtPointer->resourcetypename)) == 0)
3632             {
3633                 break;
3634             }
3635             rtPointer = rtPointer->next;
3636         }
3637         return rtPointer;
3638     }
3639     return NULL;
3640 }
3641
3642 /*
3643  * Insert a new interface into interface linked list only if not already present.
3644  * If alredy present, 2nd arg is free'd.
3645  * Default interface will always be first if present.
3646  */
3647 void insertResourceInterface(OCResource *resource, OCResourceInterface *newInterface)
3648 {
3649     OCResourceInterface *pointer = NULL;
3650     OCResourceInterface *previous = NULL;
3651
3652     newInterface->next = NULL;
3653
3654     OCResourceInterface **firstInterface = &(resource->rsrcInterface);
3655
3656     if (!*firstInterface)
3657     {
3658         *firstInterface = newInterface;
3659     }
3660     else if (strcmp(newInterface->name, OC_RSRVD_INTERFACE_DEFAULT) == 0)
3661     {
3662         if (strcmp((*firstInterface)->name, OC_RSRVD_INTERFACE_DEFAULT) == 0)
3663         {
3664             OICFree(newInterface->name);
3665             OICFree(newInterface);
3666             return;
3667         }
3668         else
3669         {
3670             newInterface->next = *firstInterface;
3671             *firstInterface = newInterface;
3672         }
3673     }
3674     else
3675     {
3676         pointer = *firstInterface;
3677         while (pointer)
3678         {
3679             if (strcmp(newInterface->name, pointer->name) == 0)
3680             {
3681                 OICFree(newInterface->name);
3682                 OICFree(newInterface);
3683                 return;
3684             }
3685             previous = pointer;
3686             pointer = pointer->next;
3687         }
3688         previous->next = newInterface;
3689     }
3690 }
3691
3692 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
3693         uint8_t index)
3694 {
3695     OCResource *resource = NULL;
3696     OCResourceInterface *pointer = NULL;
3697
3698     // Find the specified resource
3699     resource = findResource((OCResource *) handle);
3700     if (!resource)
3701     {
3702         return NULL;
3703     }
3704
3705     // Make sure a resource has a resourceinterface
3706     if (!resource->rsrcInterface)
3707     {
3708         return NULL;
3709     }
3710
3711     // Iterate through the list
3712     pointer = resource->rsrcInterface;
3713
3714     for (uint8_t i = 0; i < index && pointer; ++i)
3715     {
3716         pointer = pointer->next;
3717     }
3718     return pointer;
3719 }
3720
3721 /*
3722  * This function splits the uri using the '?' delimiter.
3723  * "uriWithoutQuery" is the block of characters between the beginning
3724  * till the delimiter or '\0' which ever comes first.
3725  * "query" is whatever is to the right of the delimiter if present.
3726  * No delimiter sets the query to NULL.
3727  * If either are present, they will be malloc'ed into the params 2, 3.
3728  * The first param, *uri is left untouched.
3729
3730  * NOTE: This function does not account for whitespace at the end of the uri NOR
3731  *       malformed uri's with '??'. Whitespace at the end will be assumed to be
3732  *       part of the query.
3733  */
3734 OCStackResult getQueryFromUri(const char * uri, char** query, char ** uriWithoutQuery)
3735 {
3736     if(!uri)
3737     {
3738         return OC_STACK_INVALID_URI;
3739     }
3740     if(!query || !uriWithoutQuery)
3741     {
3742         return OC_STACK_INVALID_PARAM;
3743     }
3744
3745     *query           = NULL;
3746     *uriWithoutQuery = NULL;
3747
3748     size_t uriWithoutQueryLen = 0;
3749     size_t queryLen = 0;
3750     size_t uriLen = strlen(uri);
3751
3752     char *pointerToDelimiter = strstr(uri, "?");
3753
3754     uriWithoutQueryLen = pointerToDelimiter == NULL ? uriLen : (size_t)(pointerToDelimiter - uri);
3755     queryLen = pointerToDelimiter == NULL ? 0 : uriLen - uriWithoutQueryLen - 1;
3756
3757     if (uriWithoutQueryLen)
3758     {
3759         *uriWithoutQuery =  (char *) OICCalloc(uriWithoutQueryLen + 1, 1);
3760         if (!*uriWithoutQuery)
3761         {
3762             goto exit;
3763         }
3764         OICStrcpy(*uriWithoutQuery, uriWithoutQueryLen +1, uri);
3765     }
3766     if (queryLen)
3767     {
3768         *query = (char *) OICCalloc(queryLen + 1, 1);
3769         if (!*query)
3770         {
3771             OICFree(*uriWithoutQuery);
3772             *uriWithoutQuery = NULL;
3773             goto exit;
3774         }
3775         OICStrcpy(*query, queryLen + 1, pointerToDelimiter + 1);
3776     }
3777
3778     return OC_STACK_OK;
3779
3780     exit:
3781         return OC_STACK_NO_MEMORY;
3782 }
3783
3784 const OicUuid_t* OCGetServerInstanceID(void)
3785 {
3786     static bool generated = false;
3787     static OicUuid_t sid;
3788     if (generated)
3789     {
3790         return &sid;
3791     }
3792
3793     if (GetDoxmDeviceID(&sid) != OC_STACK_OK)
3794     {
3795         OC_LOG(FATAL, TAG, PCF("Generate UUID for Server Instance failed!"));
3796         return NULL;
3797     }
3798     generated = true;
3799     return &sid;
3800 }
3801
3802 const char* OCGetServerInstanceIDString(void)
3803 {
3804     static bool generated = false;
3805     static char sidStr[UUID_STRING_SIZE];
3806
3807     if(generated)
3808     {
3809         return sidStr;
3810     }
3811
3812     const OicUuid_t* sid = OCGetServerInstanceID();
3813
3814     if(OCConvertUuidToString(sid->id, sidStr) != RAND_UUID_OK)
3815     {
3816         OC_LOG(FATAL, TAG, PCF("Generate UUID String for Server Instance failed!"));
3817         return NULL;
3818     }
3819
3820     generated = true;
3821     return sidStr;
3822 }
3823
3824 CAResult_t OCSelectNetwork()
3825 {
3826     CAResult_t retResult = CA_STATUS_FAILED;
3827     CAResult_t caResult = CA_STATUS_OK;
3828
3829     CATransportAdapter_t connTypes[] = {
3830             CA_ADAPTER_IP,
3831             CA_ADAPTER_RFCOMM_BTEDR,
3832             CA_ADAPTER_GATT_BTLE
3833
3834 #ifdef RA_ADAPTER
3835             ,CA_ADAPTER_REMOTE_ACCESS
3836 #endif
3837         };
3838     int numConnTypes = sizeof(connTypes)/sizeof(connTypes[0]);
3839
3840     for(int i = 0; i<numConnTypes; i++)
3841     {
3842         // Ignore CA_NOT_SUPPORTED error. The CA Layer may have not compiled in the interface.
3843         if(caResult == CA_STATUS_OK || caResult == CA_NOT_SUPPORTED)
3844         {
3845            caResult = CASelectNetwork(connTypes[i]);
3846            if(caResult == CA_STATUS_OK)
3847            {
3848                retResult = CA_STATUS_OK;
3849            }
3850         }
3851     }
3852
3853     if(retResult != CA_STATUS_OK)
3854     {
3855         return caResult; // Returns error of appropriate transport that failed fatally.
3856     }
3857
3858     return retResult;
3859 }
3860
3861 OCStackResult CAResultToOCResult(CAResult_t caResult)
3862 {
3863     switch (caResult)
3864     {
3865         case CA_STATUS_OK:
3866             return OC_STACK_OK;
3867         case CA_STATUS_INVALID_PARAM:
3868             return OC_STACK_INVALID_PARAM;
3869         case CA_ADAPTER_NOT_ENABLED:
3870             return OC_STACK_ADAPTER_NOT_ENABLED;
3871         case CA_SERVER_STARTED_ALREADY:
3872             return OC_STACK_OK;
3873         case CA_SERVER_NOT_STARTED:
3874             return OC_STACK_ERROR;
3875         case CA_DESTINATION_NOT_REACHABLE:
3876             return OC_STACK_COMM_ERROR;
3877         case CA_SOCKET_OPERATION_FAILED:
3878             return OC_STACK_COMM_ERROR;
3879         case CA_SEND_FAILED:
3880             return OC_STACK_COMM_ERROR;
3881         case CA_RECEIVE_FAILED:
3882             return OC_STACK_COMM_ERROR;
3883         case CA_MEMORY_ALLOC_FAILED:
3884             return OC_STACK_NO_MEMORY;
3885         case CA_REQUEST_TIMEOUT:
3886             return OC_STACK_TIMEOUT;
3887         case CA_DESTINATION_DISCONNECTED:
3888             return OC_STACK_COMM_ERROR;
3889         case CA_STATUS_FAILED:
3890             return OC_STACK_ERROR;
3891         case CA_NOT_SUPPORTED:
3892             return OC_STACK_NOTIMPL;
3893         default:
3894             return OC_STACK_ERROR;
3895     }
3896 }