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