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