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