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