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