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