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