Fixed usages of memset(..0..) to use Calloc/init'er
[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 #include "ocstack.h"
26 #include "ocstackinternal.h"
27 #include "ocresource.h"
28 #include "occlientcb.h"
29 #include "ocobserve.h"
30 #include "ocrandom.h"
31 #include "debug.h"
32 #include "occoap.h"
33 #include "ocmalloc.h"
34 #include "ocserverrequest.h"
35
36 //-----------------------------------------------------------------------------
37 // Typedefs
38 //-----------------------------------------------------------------------------
39 typedef enum {
40     OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED
41 } OCStackState;
42
43 #ifdef WITH_PRESENCE
44 typedef enum {
45     OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED
46 } OCPresenceState;
47 #endif
48
49 //-----------------------------------------------------------------------------
50 // Private variables
51 //-----------------------------------------------------------------------------
52 static OCStackState stackState = OC_STACK_UNINITIALIZED;
53
54 OCResource *headResource = NULL;
55 #ifdef WITH_PRESENCE
56 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
57 static PresenceResource presenceResource;
58 uint8_t PresenceTimeOutSize = 0;
59 uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
60 #endif
61
62 OCMode myStackMode;
63 OCDeviceEntityHandler defaultDeviceHandler;
64
65 //-----------------------------------------------------------------------------
66 // Macros
67 //-----------------------------------------------------------------------------
68 #define TAG  PCF("OCStack")
69 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
70              TAG, PCF(#arg " is NULL")); return (retVal); } }
71
72 //TODO: we should allow the server to define this
73 #define MAX_OBSERVE_AGE (0x2FFFFUL)
74 //-----------------------------------------------------------------------------
75 // Externs
76 //-----------------------------------------------------------------------------
77 extern void DeinitOCSecurityInfo();
78
79 //-----------------------------------------------------------------------------
80 // Internal API function
81 //-----------------------------------------------------------------------------
82
83 // This internal function is called to update the stack with the status of
84 // observers and communication failures
85 OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
86 {
87     OCStackResult result = OC_STACK_ERROR;
88     ResourceObserver * observer = NULL;
89     OCEntityHandlerRequest ehRequest = {0};
90
91     switch(status)
92     {
93     case OC_OBSERVER_NOT_INTERESTED:
94         OC_LOG(DEBUG, TAG, PCF("observer is not interested in our notifications anymore"));
95         observer = GetObserverUsingToken (token);
96         if(observer)
97         {
98             result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
99                     OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
100                     NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
101             if(result != OC_STACK_OK)
102             {
103                 return result;
104             }
105             observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
106         }
107         //observer is not observing anymore
108         result = DeleteObserverUsingToken (token);
109         if(result == OC_STACK_OK)
110         {
111             OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
112         }
113         else
114         {
115             result = OC_STACK_OK;
116             OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
117         }
118         break;
119     case OC_OBSERVER_STILL_INTERESTED:
120         //observer is still interested
121         OC_LOG(DEBUG, TAG, PCF("observer is interested in our \
122                 notifications, reset the failedCount"));
123         observer = GetObserverUsingToken(token);
124         if(observer)
125         {
126             observer->forceHighQos = 0;
127             observer->failedCommCount = 0;
128             result = OC_STACK_OK;
129         }
130         else
131         {
132             result = OC_STACK_OBSERVER_NOT_FOUND;
133         }
134         break;
135     case OC_OBSERVER_FAILED_COMM:
136         //observer is not reachable
137         OC_LOG(DEBUG, TAG, PCF("observer is unreachable"));
138         observer = GetObserverUsingToken(token);
139         if(observer)
140         {
141             if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
142             {
143                 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) NULL,
144                         OC_REST_NOMETHOD, (OCResourceHandle) NULL, NULL, NULL, 0,
145                         NULL, OC_OBSERVE_DEREGISTER, observer->observeId);
146                 if(result != OC_STACK_OK)
147                 {
148                     return OC_STACK_ERROR;
149                 }
150                 observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest);
151                 //observer is unreachable
152                 result = DeleteObserverUsingToken (token);
153                 if(result == OC_STACK_OK)
154                 {
155                     OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
156                 }
157                 else
158                 {
159                     result = OC_STACK_OK;
160                     OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
161                 }
162             }
163             else
164             {
165                 observer->failedCommCount++;
166                 result = OC_STACK_CONTINUE;
167             }
168             observer->forceHighQos = 1;
169             OC_LOG_V(DEBUG, TAG, "Failed count for this observer is %d",observer->failedCommCount);
170         }
171         break;
172     default:
173         OC_LOG(ERROR, TAG, PCF("Unknown status"));
174         result = OC_STACK_ERROR;
175         break;
176         }
177     return result;
178 }
179
180 //This function will be called back by occoap layer when a request is received
181 OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
182 {
183     OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
184
185     OCStackResult result = OC_STACK_ERROR;
186     ResourceHandling resHandling;
187     OCResource *resource;
188
189     OCServerRequest * request = GetServerRequestUsingToken(protocolRequest->requestToken);
190     if(!request)
191     {
192         OC_LOG(INFO, TAG, PCF("This is a new Server Request"));
193         result = AddServerRequest(&request, protocolRequest->coapID,
194                 protocolRequest->delayedResNeeded, protocolRequest->secured, 0,
195                 protocolRequest->method, protocolRequest->numRcvdVendorSpecificHeaderOptions,
196                 protocolRequest->observationOption, protocolRequest->qos,
197                 protocolRequest->query, protocolRequest->rcvdVendorSpecificHeaderOptions,
198                 protocolRequest->reqJSONPayload, &protocolRequest->requestToken,
199                 &protocolRequest->requesterAddr, protocolRequest->resourceUrl,
200                 protocolRequest->reqTotalSize);
201         if (OC_STACK_OK != result)
202         {
203             OC_LOG(ERROR, TAG, PCF("Error adding server request"));
204             return result;
205         }
206         VERIFY_NON_NULL(request, ERROR, OC_STACK_NO_MEMORY);
207
208         if(!protocolRequest->reqMorePacket)
209         {
210             request->requestComplete = 1;
211         }
212     }
213     else
214     {
215         OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request"));
216     }
217
218     if(request->requestComplete)
219     {
220         OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
221         result = DetermineResourceHandling (request, &resHandling, &resource);
222         if (result == OC_STACK_OK)
223         {
224             result = ProcessRequest(resHandling, resource, request);
225         }
226         else
227         {
228             result = OC_STACK_ERROR;
229         }
230     }
231     else
232     {
233         OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
234         result = OC_STACK_CONTINUE;
235     }
236     return result;
237 }
238
239 //This function will be called back by occoap layer when a response is received
240 void HandleStackResponses(OCResponse * response)
241 {
242     OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
243     OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)"));
244
245     if (response->cbNode)
246     {
247         OC_LOG(INFO, TAG, PCF("Calling into application address space"));
248         result = response->cbNode->callBack(response->cbNode->context,
249                 response->cbNode->handle, response->clientResponse);
250         if (result == OC_STACK_DELETE_TRANSACTION ||
251                 response->clientResponse->result == OC_STACK_COMM_ERROR ||
252                 response->clientResponse->result == OC_STACK_RESOURCE_DELETED)
253         {
254             FindAndDeleteClientCB(response->cbNode);
255         }
256     }
257 }
258
259 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
260 {
261     size_t index = 0;
262     unsigned char *itr, *coap;
263     uint8_t dotCount = 0;
264
265     ipAddr[index] = 0;
266     *port = 0;
267     /* search for scheme */
268     itr = ipAddrStr;
269     if (!isdigit((unsigned char) *ipAddrStr))
270     {
271         coap = (unsigned char *) OC_COAP_SCHEME;
272         while (*coap && tolower(*itr) == *coap)
273         {
274             coap++;
275             itr++;
276         }
277     }
278     ipAddrStr = itr;
279
280     while (*ipAddrStr) {
281         if (isdigit((unsigned char) *ipAddrStr))
282         {
283             ipAddr[index] *= 10;
284             ipAddr[index] += *ipAddrStr - '0';
285         }
286         else if ((unsigned char) *ipAddrStr == '.')
287         {
288             index++;
289             dotCount++;
290             ipAddr[index] = 0;
291         }
292         else
293         {
294             break;
295         }
296         ipAddrStr++;
297     }
298     if(*ipAddrStr == ':')
299     {
300         ipAddrStr++;
301         while (*ipAddrStr){
302             if (isdigit((unsigned char) *ipAddrStr))
303             {
304                 *port *= 10;
305                 *port += *ipAddrStr - '0';
306             }
307             else
308             {
309                 break;
310             }
311             ipAddrStr++;
312         }
313     }
314
315
316     if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
317             && dotCount == 3)
318     {
319         return 1;
320     }
321     else
322     {
323         return 0;
324     }
325 }
326
327 //-----------------------------------------------------------------------------
328 // Private internal function prototypes
329 //-----------------------------------------------------------------------------
330
331 static OCDoHandle GenerateInvocationHandle();
332 static OCStackResult initResources();
333 static void insertResource(OCResource *resource);
334 static OCResource *findResource(OCResource *resource);
335 static void insertResourceType(OCResource *resource,
336         OCResourceType *resourceType);
337 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
338         uint8_t index);
339 static void insertResourceInterface(OCResource *resource,
340         OCResourceInterface *resourceInterface);
341 static OCResourceInterface *findResourceInterfaceAtIndex(
342         OCResourceHandle handle, uint8_t index);
343 static void deleteResourceType(OCResourceType *resourceType);
344 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
345 static void deleteResourceElements(OCResource *resource);
346 static int deleteResource(OCResource *resource);
347 static void deleteAllResources();
348 static void incrementSequenceNumber(OCResource * resPtr);
349 static OCStackResult verifyUriQueryLength(const char * inputUri,
350         uint16_t uriLen);
351 static uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size);
352 OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI);
353
354 //-----------------------------------------------------------------------------
355 // Public APIs
356 //-----------------------------------------------------------------------------
357
358 /**
359  * Initialize the OC Stack.  Must be called prior to starting the stack.
360  *
361  * @param ipAddr
362  *     IP Address of host device
363  * @param port
364  *     Port of host device
365  * @param mode
366  *     Host device is client, server, or client-server
367  *
368  * @return
369  *     OC_STACK_OK    - no errors
370  *     OC_STACK_ERROR - stack init error
371  */
372 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
373 {
374     OCStackResult result = OC_STACK_ERROR;
375     OC_LOG(INFO, TAG, PCF("Entering OCInit"));
376
377     if (ipAddr)
378     {
379         OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
380     }
381
382     switch (mode)
383     {
384     case OC_CLIENT:
385         OC_LOG(INFO, TAG, PCF("Client mode"));
386         break;
387     case OC_SERVER:
388         OC_LOG(INFO, TAG, PCF("Server mode"));
389         break;
390     case OC_CLIENT_SERVER:
391         OC_LOG(INFO, TAG, PCF("Client-server mode"));
392         break;
393     default:
394         OC_LOG(ERROR, TAG, PCF("Invalid mode"));
395         return OC_STACK_ERROR;
396         break;
397     }
398     myStackMode = mode;
399
400     defaultDeviceHandler = NULL;
401
402 #ifdef WITH_PRESENCE
403     PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
404 #endif // WITH_PRESENCE
405
406     // Make call to OCCoAP layer
407     result = OCInitCoAP(ipAddr, (uint16_t) port, myStackMode);
408     if (result == OC_STACK_OK)
409     {
410         stackState = OC_STACK_INITIALIZED;
411     }
412     // Initialize resource
413     if(result == OC_STACK_OK && myStackMode != OC_CLIENT)
414     {
415         result = initResources();
416     }
417     if(result != OC_STACK_OK)
418     {
419         OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
420     }
421     return result;
422 }
423
424 /**
425  * Stop the OC stack.  Use for a controlled shutdown.
426  * @return
427  *     OC_STACK_OK    - no errors
428  *     OC_STACK_ERROR - stack not initialized
429  */
430 OCStackResult OCStop()
431 {
432     OCStackResult result = OC_STACK_ERROR;
433
434     OC_LOG(INFO, TAG, PCF("Entering OCStop"));
435
436     if (stackState != OC_STACK_INITIALIZED)
437     {
438         OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
439         return OC_STACK_ERROR;
440     }
441
442     // Free memory dynamically allocated for resources
443     deleteAllResources();
444
445     // Make call to OCCoAP layer
446     if (OCStopCoAP() == OC_STACK_OK)
447     {
448         // Remove all observers
449         DeleteObserverList();
450         // Remove all the client callbacks
451         DeleteClientCBList();
452         stackState = OC_STACK_UNINITIALIZED;
453         result = OC_STACK_OK;
454     } else {
455         result = OC_STACK_ERROR;
456     }
457
458     // Deinit security blob
459     DeinitOCSecurityInfo();
460
461     if (result != OC_STACK_OK) {
462         OC_LOG(ERROR, TAG, PCF("Stack stop error"));
463     }
464
465     return result;
466 }
467
468 /**
469  * Verify the lengths of the URI and the query separately
470  *
471  * @param inputUri       - Input URI and query.
472  * @param uriLen         - The length of the initial URI with query.
473  *
474  * Note: The '?' that appears after the URI is not considered as
475  * a part of the query.
476  */
477 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
478 {
479     char *query;
480
481     query = strchr (inputUri, '?');
482
483     if (query != NULL)
484     {
485         if((query - inputUri) > MAX_URI_LENGTH)
486         {
487             return OC_STACK_INVALID_URI;
488         }
489
490         if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
491         {
492             return OC_STACK_INVALID_QUERY;
493         }
494     }
495     else if(uriLen > MAX_URI_LENGTH)
496     {
497         return OC_STACK_INVALID_URI;
498     }
499     return OC_STACK_OK;
500 }
501
502 /**
503  * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
504  *
505  * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
506  * @param method             - @ref OCMethod to perform on the resource
507  * @param requiredUri        - URI of the resource to interact with
508  * @param referenceUri       - URI of the reference resource
509  * @param request            - JSON encoded request
510  * @param qos                - quality of service
511  * @param cbData             - struct that contains asynchronous callback function that is invoked
512  *                             by the stack when discovery or resource interaction is complete
513  * @param options            - The address of an array containing the vendor specific header
514  *                             header options to be sent with the request
515  * @param numOptions         - Number of vendor specific header options to be included
516  *
517  * @return
518  *     OC_STACK_OK               - no errors
519  *     OC_STACK_INVALID_CALLBACK - invalid callback function pointer
520  *     OC_STACK_INVALID_METHOD   - invalid resource method
521  *     OC_STACK_INVALID_URI      - invalid required or reference URI
522  */
523
524 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
525                            const char *referenceUri, const char *request,
526                            OCQualityOfService qos, OCCallbackData *cbData,
527                            OCHeaderOption * options, uint8_t numOptions)
528 {
529     OCStackResult result = OC_STACK_ERROR;
530     OCCoAPToken token;
531     ClientCB *clientCB = NULL;
532     unsigned char * requestUri = NULL;
533     unsigned char * resourceType = NULL;
534     char * newURI = (char *)requiredUri;
535     (void) referenceUri;
536
537     OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
538
539     // Validate input parameters
540     VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
541     VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
542
543     TODO ("Need to form the final query by concatenating require and reference URI's");
544     VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
545
546     uint16_t uriLen = strlen(requiredUri);
547
548     // ToDo: We should also check if the requiredUri has a mutlicast address, then qos has to be OC_Low_QOS
549     switch (method)
550     {
551         case OC_REST_GET:
552         case OC_REST_PUT:
553         case OC_REST_POST:
554         case OC_REST_DELETE:
555         case OC_REST_OBSERVE:
556         case OC_REST_OBSERVE_ALL:
557         case OC_REST_CANCEL_OBSERVE:
558             break;
559         #ifdef WITH_PRESENCE
560         case OC_REST_PRESENCE:
561             break;
562         #endif
563         default:
564             result = OC_STACK_INVALID_METHOD;
565             goto exit;
566     }
567
568     if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK)
569     {
570         goto exit;
571     }
572
573     if((request) && (strlen(request) > MAX_REQUEST_LENGTH))
574     {
575         result = OC_STACK_INVALID_PARAM;
576         goto exit;
577     }
578
579 #ifdef WITH_PRESENCE
580     if(method == OC_REST_PRESENCE)
581     {
582         result = getResourceType(requiredUri, &resourceType, &newURI);
583         if(result != OC_STACK_OK)
584         {
585             goto exit;
586         }
587     }
588 #endif // WITH_PRESENCE
589
590     requestUri = (unsigned char *) OCMalloc(uriLen + 1);
591     if(requestUri)
592     {
593         memcpy(requestUri, newURI, (uriLen + 1));
594     }
595     else
596     {
597         result = OC_STACK_NO_MEMORY;
598         goto exit;
599     }
600
601     *handle = GenerateInvocationHandle();
602     if(!*handle)
603     {
604         result = OC_STACK_NO_MEMORY;
605         goto exit;
606     }
607
608     // Generate token which will be used by OCStack to match responses received
609     // with the request
610     OCGenerateCoAPToken(&token);
611
612     if((result = AddClientCB(&clientCB, cbData, &token, *handle, method, requestUri, resourceType))
613             != OC_STACK_OK)
614     {
615         result = OC_STACK_NO_MEMORY;
616         goto exit;
617     }
618
619     // Make call to OCCoAP layer
620     result = OCDoCoAPResource(method, qos, &token, newURI, request, options, numOptions);
621
622 exit:
623     if(newURI != requiredUri)
624     {
625         OCFree(newURI);
626     }
627     if (result != OC_STACK_OK)
628     {
629         OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
630         FindAndDeleteClientCB(clientCB);
631     }
632     return result;
633 }
634
635 /**
636  * Cancel a request associated with a specific @ref OCDoResource invocation.
637  *
638  * @param handle - Used to identify a specific OCDoResource invocation.
639  * @param qos    - used to specify Quality of Service (read below for more info)
640  * @param options- used to specify vendor specific header options when sending
641  *                 explicit observe cancellation
642  * @param numOptions- Number of header options to be included
643  *
644  * @return
645  *     OC_STACK_OK               - No errors; Success
646  *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
647  */
648 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
649         uint8_t numOptions) {
650     /*
651      * This ftn is implemented one of two ways in the case of observation:
652      *
653      * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
654      *      Remove the callback associated on client side.
655      *      When the next notification comes in from server,
656      *      reply with RESET message to server.
657      *      Keep in mind that the server will react to RESET only
658      *      if the last notification was sent ans CON
659      *
660      * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
661      *      and it is associated with an observe request
662      *      (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
663      *      Send CON Observe request to server with
664      *      observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
665      *      Remove the callback associated on client side.
666      */
667     OCStackResult ret = OC_STACK_OK;
668
669     if(!handle) {
670         return OC_STACK_INVALID_PARAM;
671     }
672
673     OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
674
675     ClientCB *clientCB = GetClientCB(NULL, handle, NULL);
676
677     if(clientCB) {
678         switch (clientCB->method)
679         {
680             case OC_REST_OBSERVE:
681             case OC_REST_OBSERVE_ALL:
682                 if(qos == OC_HIGH_QOS)
683                 {
684                     ret = OCDoCoAPResource(OC_REST_CANCEL_OBSERVE, qos,
685                             &(clientCB->token), (const char *) clientCB->requestUri, NULL, options,
686                             numOptions);
687                 }
688                 else
689                 {
690                     FindAndDeleteClientCB(clientCB);
691                 }
692                 break;
693             #ifdef WITH_PRESENCE
694             case OC_REST_PRESENCE:
695                 FindAndDeleteClientCB(clientCB);
696                 break;
697             #endif
698             default:
699                 return OC_STACK_INVALID_METHOD;
700         }
701     }
702     return ret;
703 }
704 #ifdef WITH_PRESENCE
705 OCStackResult OCProcessPresence()
706 {
707     OCStackResult result = OC_STACK_OK;
708     uint8_t ipAddr[4] = { 0 };
709     uint16_t port = 0;
710
711     OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
712     ClientCB* cbNode = NULL;
713     OCDevAddr dst;
714     OCClientResponse clientResponse;
715     OCResponse * response = NULL;
716
717     LL_FOREACH(cbList, cbNode) {
718         if(OC_REST_PRESENCE == cbNode->method)
719         {
720             if(cbNode->presence)
721             {
722                 uint32_t now = GetTime(0);
723                 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
724                 OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
725
726
727                 if(cbNode->presence->TTLlevel >= (PresenceTimeOutSize + 1))
728                 {
729                     goto exit;
730                 }
731
732                 if(cbNode->presence->TTLlevel < PresenceTimeOutSize){
733                     OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d",
734                             cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
735                 }
736
737                 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
738                 {
739                     OC_LOG(DEBUG, TAG, PCF("----------------No more timeout ticks"));
740                     if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
741                     {
742                         OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
743                                 &dst);
744                         result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_TIMEOUT,
745                                 (OCDevAddr *) &dst, 0, NULL);
746                         if(result != OC_STACK_OK)
747                         {
748                             goto exit;
749                         }
750                         result = FormOCResponse(&response, cbNode, 0, &clientResponse);
751                         if(result != OC_STACK_OK)
752                         {
753                             goto exit;
754                         }
755
756                         // Increment the TTLLevel (going to a next state), so we don't keep
757                         // sending presence notification to client.
758                         cbNode->presence->TTLlevel++;
759                         OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d",
760                                                 cbNode->presence->TTLlevel);
761                     }
762                     else
763                     {
764                         result = OC_STACK_INVALID_IP;
765                         goto exit;
766                     }
767                     HandleStackResponses(response);
768                 }
769                 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
770                 {
771                     OC_LOG(DEBUG, TAG, PCF("time to test server presence =========="));
772                     OCCoAPToken token;
773                     OCGenerateCoAPToken(&token);
774                     result = OCDoCoAPResource(OC_REST_GET, OC_LOW_QOS,
775                             &token, (const char *)cbNode->requestUri, NULL, NULL, 0);
776                     if(result != OC_STACK_OK)
777                     {
778                         goto exit;
779                     }
780                     cbNode->presence->TTLlevel++;
781                     OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d", cbNode->presence->TTLlevel);
782                 }
783             }
784         }
785     }
786 exit:
787     if (result != OC_STACK_OK)
788     {
789         OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
790     }
791     return result;
792 }
793 #endif
794
795 /**
796  * Called in main loop of OC client or server.  Allows low-level processing of
797  * stack services.
798  *
799  * @return
800  *     OC_STACK_OK    - no errors
801  *     OC_STACK_ERROR - stack process error
802  */
803 OCStackResult OCProcess() {
804
805     OC_LOG(INFO, TAG, PCF("Entering OCProcess"));
806     #ifdef WITH_PRESENCE
807     OCProcessPresence();
808     #endif
809     OCProcessCoAP();
810
811     return OC_STACK_OK;
812 }
813
814 #ifdef WITH_PRESENCE
815 /**
816  * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out
817  * presence notifications to clients via multicast. Once this API has been called with a success,
818  * clients may query for this server's presence and this server's stack will respond via multicast.
819  *
820  * Server can call this function when it comes online for the first time, or when it comes back
821  * online from offline mode, or when it re enters network.
822  *
823  * @param ttl - Time To Live in seconds
824  * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
825  *
826  * @return
827  *     OC_STACK_OK      - No errors; Success
828  */
829 OCStackResult OCStartPresence(const uint32_t ttl)
830 {
831     OCChangeResourceProperty(
832             &(((OCResource *)presenceResource.handle)->resourceProperties),
833             OC_ACTIVE, 1);
834
835     if(ttl > 0)
836     {
837         presenceResource.presenceTTL = ttl;
838     }
839
840     if(OC_PRESENCE_UNINITIALIZED == presenceState)
841     {
842         OCDevAddr multiCastAddr;
843         OCCoAPToken token;
844
845         presenceState = OC_PRESENCE_INITIALIZED;
846         OCGenerateCoAPToken(&token);
847         OCBuildIPv4Address(224, 0, 1, 187, 5683, &multiCastAddr);
848         //add the presence observer
849         AddObserver(OC_PRESENCE_URI, NULL, 0, &token, &multiCastAddr,
850             (OCResource *)presenceResource.handle, OC_LOW_QOS);
851     }
852
853     // Each time OCStartPresence is called
854     // a different random 32-bit integer number is used
855     ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
856
857     return SendPresenceNotification(NULL);
858 }
859
860 /**
861  * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out
862  * presence notifications to clients via multicast. Once this API has been called with a success,
863  * this server's stack will not respond to clients querying for this server's presence.
864  *
865  * Server can call this function when it is terminating, going offline, or when going
866  * away from network.
867  *
868  * @return
869  *     OC_STACK_OK      - No errors; Success
870  */
871 OCStackResult OCStopPresence()
872 {
873     OCStackResult result = OC_STACK_ERROR;
874     //make resource inactive
875     result = OCChangeResourceProperty(
876             &(((OCResource *) presenceResource.handle)->resourceProperties),
877             OC_ACTIVE, 0);
878     result = SendPresenceNotification(NULL);
879
880     return result;
881 }
882 #endif
883
884
885 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler)
886 {
887     defaultDeviceHandler = entityHandler;
888
889     return OC_STACK_OK;
890 }
891
892 /**
893  * Create a resource
894  *
895  * @param handle - pointer to handle to newly created resource.  Set by ocstack.  Used to refer to resource
896  * @param resourceTypeName - name of resource type.  Example: "core.led"
897  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
898  * @param uri - URI of the resource.  Example:  "/a/led"
899  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
900  *                        NULL for default entity handler
901  * @param resourceProperties - properties supported by resource.  Example: OC_DISCOVERABLE|OC_OBSERVABLE
902  *
903  * @return
904  *     OC_STACK_OK    - no errors
905  *     OC_STACK_ERROR - stack process error
906  */
907 OCStackResult OCCreateResource(OCResourceHandle *handle,
908         const char *resourceTypeName,
909         const char *resourceInterfaceName,
910         const char *uri, OCEntityHandler entityHandler,
911         uint8_t resourceProperties) {
912
913     OCResource *pointer = NULL;
914     char *str = NULL;
915     size_t size;
916     OCStackResult result = OC_STACK_ERROR;
917
918     OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
919
920     if(myStackMode == OC_CLIENT)
921     {
922         return result;
923     }
924     // Validate parameters
925     // Is it presented during resource discovery?
926     if (!handle || !resourceTypeName || !uri) {
927         OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
928         return OC_STACK_INVALID_PARAM;
929     }
930
931     if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0) {
932         resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
933     }
934
935     // Make sure resourceProperties bitmask has allowed properties specified
936     if (resourceProperties
937             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE)) {
938         OC_LOG(ERROR, TAG, PCF("Invalid property"));
939         return OC_STACK_INVALID_PARAM;
940     }
941
942     // If the headResource is NULL, then no resources have been created...
943     pointer = headResource;
944     if (pointer) {
945         // At least one resources is in the resource list, so we need to search for
946         // repeated URLs, which are not allowed.  If a repeat is found, exit with an error
947         while (pointer) {
948             if (strcmp(uri, pointer->uri) == 0) {
949                 OC_LOG(ERROR, TAG, PCF("URI already in use"));
950                 return OC_STACK_INVALID_PARAM;
951             }
952             pointer = pointer->next;
953         }
954     }
955     // Create the pointer and insert it into the resource list
956     pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
957     if (!pointer) {
958         goto exit;
959     }
960     pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
961
962     insertResource(pointer);
963
964     // Set the uri
965     size = strlen(uri) + 1;
966     str = (char *) OCMalloc(size);
967     if (!str) {
968         goto exit;
969     }
970     strncpy(str, uri, size);
971     pointer->uri = str;
972
973     // Set properties.  Set OC_ACTIVE
974     pointer->resourceProperties = (OCResourceProperty) (resourceProperties
975             | OC_ACTIVE);
976
977     // Add the resourcetype to the resource
978     result = BindResourceTypeToResource(pointer, resourceTypeName);
979     if (result != OC_STACK_OK) {
980         OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
981         goto exit;
982     }
983
984     // Add the resourceinterface to the resource
985     result = BindResourceInterfaceToResource(pointer, resourceInterfaceName);
986     if (result != OC_STACK_OK) {
987         OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
988         goto exit;
989     }
990
991     // If an entity handler has been passed, attach it to the newly created
992     // resource.  Otherwise, set the default entity handler.
993     if (entityHandler)
994     {
995         pointer->entityHandler = entityHandler;
996     }
997     else
998     {
999         pointer->entityHandler = defaultResourceEHandler;
1000     }
1001
1002     *handle = pointer;
1003     result = OC_STACK_OK;
1004
1005     #ifdef WITH_PRESENCE
1006     if(presenceResource.handle)
1007     {
1008         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1009         SendPresenceNotification(pointer->rsrcType);
1010     }
1011     #endif
1012 exit:
1013     if (result != OC_STACK_OK)
1014     {
1015         // Deep delete of resource and other dynamic elements that it contains
1016         deleteResource(pointer);
1017         OCFree(str);
1018     }
1019     return result;
1020 }
1021
1022
1023
1024 /**
1025  * Create a resource. with host ip address for remote resource
1026  *
1027  * @param handle - pointer to handle to newly created resource.  Set by ocstack.
1028  *                 Used to refer to resource
1029  * @param resourceTypeName - name of resource type.  Example: "core.led"
1030  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
1031  * @param host - HOST address of the remote resource.  Example:  "coap://xxx.xxx.xxx.xxx:xxxxx"
1032  * @param uri - URI of the resource.  Example:  "/a/led"
1033  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1034  *                        NULL for default entity handler
1035  * @param resourceProperties - properties supported by resource.
1036  *                             Example: OC_DISCOVERABLE|OC_OBSERVABLE
1037  *
1038  * @return
1039  *     OC_STACK_OK    - no errors
1040  *     OC_STACK_ERROR - stack process error
1041  */
1042
1043 OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle,
1044         const char *resourceTypeName,
1045         const char *resourceInterfaceName,
1046         const char *host,
1047         const char *uri,
1048         OCEntityHandler entityHandler,
1049         uint8_t resourceProperties)
1050 {
1051     char *str = NULL;
1052     size_t size;
1053     OCStackResult result = OC_STACK_ERROR;
1054
1055     result = OCCreateResource(handle, resourceTypeName, resourceInterfaceName,
1056                                 uri, entityHandler, resourceProperties);
1057
1058     if (result != OC_STACK_ERROR)
1059     {
1060         // Set the uri
1061         size = strlen(host) + 1;
1062         str = (char *) OCMalloc(size);
1063         if (!str)
1064         {
1065             return OC_STACK_ERROR;
1066         }
1067         strncpy(str, host, size);
1068         ((OCResource *) *handle)->host = str;
1069     }
1070
1071     return result;
1072 }
1073
1074 /**
1075  * Add a resource to a collection resource.
1076  *
1077  * @param collectionHandle - handle to the collection resource
1078  * @param resourceHandle - handle to resource to be added to the collection resource
1079  *
1080  * @return
1081  *     OC_STACK_OK    - no errors
1082  *     OC_STACK_ERROR - stack process error
1083  *     OC_STACK_INVALID_PARAM - invalid collectionhandle
1084  */
1085 OCStackResult OCBindResource(
1086         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
1087     OCResource *resource;
1088     uint8_t i;
1089
1090     OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
1091
1092     // Validate parameters
1093     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
1094     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
1095     // Container cannot contain itself
1096     if (collectionHandle == resourceHandle) {
1097         OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
1098         return OC_STACK_INVALID_PARAM;
1099     }
1100
1101     // Use the handle to find the resource in the resource linked list
1102     resource = findResource((OCResource *) collectionHandle);
1103     if (!resource) {
1104         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
1105         return OC_STACK_INVALID_PARAM;
1106     }
1107
1108     // Look for an open slot to add add the child resource.
1109     // If found, add it and return success
1110     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
1111         if (!resource->rsrcResources[i]) {
1112             resource->rsrcResources[i] = (OCResource *) resourceHandle;
1113             OC_LOG(INFO, TAG, PCF("resource bound"));
1114             return OC_STACK_OK;
1115         }
1116     }
1117
1118     #ifdef WITH_PRESENCE
1119     if(presenceResource.handle)
1120     {
1121         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1122         SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
1123     }
1124     #endif
1125
1126     // Unable to add resourceHandle, so return error
1127     return OC_STACK_ERROR;
1128 }
1129
1130 /**
1131  * Remove a resource from a collection resource.
1132  *
1133  * @param collectionHandle - handle to the collection resource
1134  * @param resourceHandle - handle to resource to be added to the collection resource
1135  *
1136  * @return
1137  *     OC_STACK_OK    - no errors
1138  *     OC_STACK_ERROR - stack process error
1139  *     OC_STACK_INVALID_PARAM - invalid collectionHandle
1140  */
1141 OCStackResult OCUnBindResource(
1142         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
1143     OCResource *resource;
1144     uint8_t i;
1145
1146     OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
1147
1148     // Validate parameters
1149     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
1150     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
1151     // Container cannot contain itself
1152     if (collectionHandle == resourceHandle) {
1153         OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
1154         return OC_STACK_INVALID_PARAM;
1155     }
1156
1157     // Use the handle to find the resource in the resource linked list
1158     resource = findResource((OCResource *) collectionHandle);
1159     if (!resource) {
1160         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
1161         return OC_STACK_INVALID_PARAM;
1162     }
1163
1164     // Look for an open slot to add add the child resource.
1165     // If found, add it and return success
1166     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
1167         if (resourceHandle == resource->rsrcResources[i]) {
1168             resource->rsrcResources[i] = (OCResource *) NULL;
1169             OC_LOG(INFO, TAG, PCF("resource unbound"));
1170             return OC_STACK_OK;
1171         }
1172     }
1173
1174     OC_LOG(INFO, TAG, PCF("resource not found in collection"));
1175
1176     #ifdef WITH_PRESENCE
1177     if(presenceResource.handle)
1178     {
1179         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1180         SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
1181     }
1182     #endif
1183
1184     // Unable to add resourceHandle, so return error
1185     return OC_STACK_ERROR;
1186 }
1187
1188 OCStackResult BindResourceTypeToResource(OCResource* resource,
1189                                             const char *resourceTypeName)
1190 {
1191     OCResourceType *pointer = NULL;
1192     char *str = NULL;
1193     size_t size;
1194     OCStackResult result = OC_STACK_ERROR;
1195
1196     OC_LOG(INFO, TAG, PCF("Entering BindResourceTypeToResource"));
1197
1198     // Validate parameters
1199     VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
1200     // TODO:  Does resource attribute resentation really have to be maintained in stack?
1201     // Is it presented during resource discovery?
1202
1203     TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
1204
1205     // Create the resourcetype and insert it into the resource list
1206     pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
1207     if (!pointer) {
1208         goto exit;
1209     }
1210
1211     // Set the resourceTypeName
1212     size = strlen(resourceTypeName) + 1;
1213     str = (char *) OCMalloc(size);
1214     if (!str) {
1215         goto exit;
1216     }
1217     strncpy(str, resourceTypeName, size);
1218     pointer->resourcetypename = str;
1219
1220     insertResourceType(resource, pointer);
1221     result = OC_STACK_OK;
1222
1223     exit: if (result != OC_STACK_OK) {
1224         OCFree(pointer);
1225         OCFree(str);
1226     }
1227
1228     return result;
1229 }
1230
1231 OCStackResult BindResourceInterfaceToResource(OCResource* resource,
1232         const char *resourceInterfaceName)
1233 {
1234     OCResourceInterface *pointer = NULL;
1235     char *str = NULL;
1236     size_t size;
1237     OCStackResult result = OC_STACK_ERROR;
1238
1239     OC_LOG(INFO, TAG, PCF("Entering BindResourceInterfaceToResource"));
1240
1241     // Validate parameters
1242     VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
1243
1244     TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
1245
1246     // Create the resourceinterface and insert it into the resource list
1247     pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
1248     if (!pointer) {
1249         goto exit;
1250     }
1251
1252     // Set the resourceinterface name
1253     size = strlen(resourceInterfaceName) + 1;
1254     str = (char *) OCMalloc(size);
1255     if (!str) {
1256         goto exit;
1257     }
1258     strncpy(str, resourceInterfaceName, size);
1259     pointer->name = str;
1260
1261     // Bind the resourceinterface to the resource
1262     insertResourceInterface(resource, pointer);
1263
1264     result = OC_STACK_OK;
1265
1266     exit: if (result != OC_STACK_OK) {
1267         OCFree(pointer);
1268         OCFree(str);
1269     }
1270
1271     return result;
1272 }
1273
1274 /**
1275  * Bind a resourcetype to a resource.
1276  *
1277  * @param handle - handle to the resource
1278  * @param resourceTypeName - name of resource type.  Example: "core.led"
1279  *
1280  * @return
1281  *     OC_STACK_OK    - no errors
1282  *     OC_STACK_ERROR - stack process error
1283  */
1284 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
1285         const char *resourceTypeName) {
1286
1287     OCStackResult result = OC_STACK_ERROR;
1288     OCResource *resource;
1289
1290     // Make sure resource exists
1291     resource = findResource((OCResource *) handle);
1292     if (!resource) {
1293         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1294         return OC_STACK_ERROR;
1295     }
1296
1297     // call internal function
1298     result = BindResourceTypeToResource(resource, resourceTypeName);
1299
1300     #ifdef WITH_PRESENCE
1301     if(presenceResource.handle)
1302     {
1303         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1304         SendPresenceNotification(resource->rsrcType);
1305     }
1306     #endif
1307
1308     return result;
1309 }
1310
1311 /**
1312  * Bind a resourceinterface to a resource.
1313  *
1314  * @param handle - handle to the resource
1315  * @param resourceInterfaceName - name of resource interface.  Example: "oc.mi.b"
1316  *
1317  * @return
1318  *     OC_STACK_OK    - no errors
1319  *     OC_STACK_ERROR - stack process error
1320  */
1321
1322 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
1323         const char *resourceInterfaceName) {
1324
1325     OCStackResult result = OC_STACK_ERROR;
1326     OCResource *resource;
1327
1328     // Make sure resource exists
1329     resource = findResource((OCResource *) handle);
1330     if (!resource) {
1331         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1332         return OC_STACK_ERROR;
1333     }
1334
1335     // call internal function
1336     result = BindResourceInterfaceToResource(resource, resourceInterfaceName);
1337
1338     #ifdef WITH_PRESENCE
1339     if(presenceResource.handle)
1340     {
1341         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1342         SendPresenceNotification(resource->rsrcType);
1343     }
1344     #endif
1345
1346     return result;
1347 }
1348
1349 /**
1350  * Get the number of resources that have been created in the stack.
1351  *
1352  * @param numResources - pointer to count variable
1353  *
1354  * @return
1355  *     OC_STACK_OK    - no errors
1356  *     OC_STACK_ERROR - stack process error
1357
1358  */
1359 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
1360     OCResource *pointer = headResource;
1361
1362     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
1363     VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
1364     *numResources = 0;
1365     while (pointer) {
1366         *numResources = *numResources + 1;
1367         pointer = pointer->next;
1368     }
1369     return OC_STACK_OK;
1370 }
1371
1372 /**
1373  * Get a resource handle by index.
1374  *
1375  * @param index - index of resource, 0 to Count - 1
1376  *
1377  * @return
1378  *    Resource handle - if found
1379  *    NULL - if not found
1380  */
1381 OCResourceHandle OCGetResourceHandle(uint8_t index) {
1382     OCResource *pointer = headResource;
1383     uint8_t i = 0;
1384
1385     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
1386
1387     // Iterate through the list
1388     while ((i < index) && pointer) {
1389         i++;
1390         pointer = pointer->next;
1391     }
1392     return (OCResourceHandle) pointer;
1393 }
1394
1395 /**
1396  * Delete resource specified by handle.  Deletes resource and all resourcetype and resourceinterface
1397  * linked lists.
1398  *
1399  * @param handle - handle of resource to be deleted
1400  *
1401  * @return
1402  *     OC_STACK_OK              - no errors
1403  *     OC_STACK_ERROR           - stack process error
1404  *     OC_STACK_NO_RESOURCE     - resource not found
1405  *     OC_STACK_INVALID_PARAM   - invalid param
1406  */
1407 OCStackResult OCDeleteResource(OCResourceHandle handle) {
1408     OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
1409
1410     if (!handle) {
1411         OC_LOG(ERROR, TAG, PCF("Invalid param"));
1412         return OC_STACK_INVALID_PARAM;
1413     }
1414
1415     OCResource *resource = findResource((OCResource *) handle);
1416     if (resource == NULL) {
1417         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1418         return OC_STACK_NO_RESOURCE;
1419     }
1420
1421     if (deleteResource((OCResource *) handle) == 0) {
1422         OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
1423         return OC_STACK_ERROR;
1424     }
1425
1426     return OC_STACK_OK;
1427 }
1428
1429 /**
1430  * Get the URI of the resource specified by handle.
1431  *
1432  * @param handle - handle of resource
1433  * @return
1434  *    URI string - if resource found
1435  *    NULL - resource not found
1436  */
1437 const char *OCGetResourceUri(OCResourceHandle handle) {
1438     OCResource *resource;
1439     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
1440
1441     resource = findResource((OCResource *) handle);
1442     if (resource) {
1443         return resource->uri;
1444     }
1445     return (const char *) NULL;
1446 }
1447
1448 /**
1449  * Get the properties of the resource specified by handle.
1450  * NOTE: that after a resource is created, the OC_ACTIVE property is set
1451  * for the resource by the stack.
1452  *
1453  * @param handle - handle of resource
1454  * @return
1455  *    property bitmap - if resource found
1456  *    NULL - resource not found
1457  */
1458 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
1459     OCResource *resource;
1460     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
1461
1462     resource = findResource((OCResource *) handle);
1463     if (resource) {
1464         return resource->resourceProperties;
1465     }
1466     return 0;
1467 }
1468
1469 /**
1470  * Get the number of resource types of the resource.
1471  *
1472  * @param handle - handle of resource
1473  * @param numResourceTypes - pointer to count variable
1474  *
1475  * @return
1476  *     OC_STACK_OK    - no errors
1477  *     OC_STACK_ERROR - stack process error
1478  */
1479 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
1480         uint8_t *numResourceTypes) {
1481     OCResource *resource;
1482     OCResourceType *pointer;
1483
1484     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
1485     VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
1486     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1487
1488     *numResourceTypes = 0;
1489
1490     resource = findResource((OCResource *) handle);
1491     if (resource) {
1492         pointer = resource->rsrcType;
1493         while (pointer) {
1494             *numResourceTypes = *numResourceTypes + 1;
1495             pointer = pointer->next;
1496         }
1497     }
1498     return OC_STACK_OK;
1499 }
1500
1501 /**
1502  * Get name of resource type of the resource.
1503  *
1504  * @param handle - handle of resource
1505  * @param index - index of resource, 0 to Count - 1
1506  *
1507  * @return
1508  *    resource type name - if resource found
1509  *    NULL - resource not found
1510  */
1511 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
1512     OCResourceType *resourceType;
1513
1514     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
1515
1516     resourceType = findResourceTypeAtIndex(handle, index);
1517     if (resourceType) {
1518         return resourceType->resourcetypename;
1519     }
1520     return (const char *) NULL;
1521 }
1522
1523
1524
1525 /**
1526  * Get the number of resource interfaces of the resource.
1527  *
1528  * @param handle - handle of resource
1529  * @param numResources - pointer to count variable
1530  *
1531  * @return
1532  *     OC_STACK_OK    - no errors
1533  *     OC_STACK_ERROR - stack process error
1534  */
1535 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
1536         uint8_t *numResourceInterfaces) {
1537     OCResourceInterface *pointer;
1538     OCResource *resource;
1539
1540     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
1541
1542     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1543     VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
1544
1545     *numResourceInterfaces = 0;
1546     resource = findResource((OCResource *) handle);
1547     if (resource) {
1548         pointer = resource->rsrcInterface;
1549         while (pointer) {
1550             *numResourceInterfaces = *numResourceInterfaces + 1;
1551             pointer = pointer->next;
1552         }
1553     }
1554     return OC_STACK_OK;
1555 }
1556
1557 /**
1558  * Get name of resource interface of the resource.
1559  *
1560  * @param handle - handle of resource
1561  * @param index - index of resource, 0 to Count - 1
1562  *
1563  * @return
1564  *    resource interface name - if resource found
1565  *    NULL - resource not found
1566  */
1567 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
1568     OCResourceInterface *resourceInterface;
1569
1570     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
1571
1572     resourceInterface = findResourceInterfaceAtIndex(handle, index);
1573     if (resourceInterface) {
1574         return resourceInterface->name;
1575     }
1576     return (const char *) NULL;
1577 }
1578
1579 /**
1580  * Get resource handle from the collection resource by index.
1581  *
1582  * @param collectionHandle - handle of collection resource
1583  * @param index - index of contained resource, 0 to Count - 1
1584  *
1585  * @return
1586  *    handle to resource - if resource found
1587  *    NULL - resource not found
1588  */
1589 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
1590         uint8_t index) {
1591     OCResource *resource;
1592
1593     OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
1594
1595     if (index >= MAX_CONTAINED_RESOURCES) {
1596         return NULL;
1597     }
1598
1599     resource = findResource((OCResource *) collectionHandle);
1600     if (!resource) {
1601         return NULL;
1602     }
1603
1604     return resource->rsrcResources[index];
1605 }
1606
1607 /**
1608  * Bind an entity handler to the resource.
1609  *
1610  * @param handle - handle to the resource that the contained resource is to be bound
1611  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1612  * @return
1613  *     OC_STACK_OK    - no errors
1614  *     OC_STACK_ERROR - stack process error
1615  */
1616 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
1617         OCEntityHandler entityHandler) {
1618     OCResource *resource;
1619
1620     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
1621
1622     // Validate parameters
1623     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1624     //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
1625
1626     // Use the handle to find the resource in the resource linked list
1627     resource = findResource((OCResource *)handle);
1628     if (!resource) {
1629         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1630         return OC_STACK_ERROR;
1631     }
1632
1633     // Bind the handler
1634     resource->entityHandler = entityHandler;
1635
1636     #ifdef WITH_PRESENCE
1637     if(presenceResource.handle)
1638     {
1639         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1640         SendPresenceNotification(resource->rsrcType);
1641     }
1642     #endif
1643
1644     return OC_STACK_OK;
1645 }
1646
1647 /**
1648  * Get the entity handler for a resource.
1649  *
1650  * @param handle - handle of resource
1651  *
1652  * @return
1653  *    entity handler - if resource found
1654  *    NULL - resource not found
1655  */
1656 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
1657     OCResource *resource;
1658
1659     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
1660
1661     // Use the handle to find the resource in the resource linked list
1662     resource = findResource((OCResource *)handle);
1663     if (!resource) {
1664         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1665         return NULL;
1666     }
1667
1668     // Bind the handler
1669     return resource->entityHandler;
1670 }
1671
1672 void incrementSequenceNumber(OCResource * resPtr)
1673 {
1674     // Increment the sequence number
1675     resPtr->sequenceNum += 1;
1676     if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
1677     {
1678         resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
1679     }
1680     return;
1681 }
1682
1683 #ifdef WITH_PRESENCE
1684 /**
1685  * Notify Presence subscribers that a resource has been modified
1686  *
1687  * @param resourceType - Handle to the resourceType linked list of resource
1688  *                       that was modified.
1689  * @param qos          - Quality Of Service
1690  *
1691  */
1692 OCStackResult SendPresenceNotification(OCResourceType *resourceType)
1693 {
1694     OCResource *resPtr = NULL;
1695     OCStackResult result;
1696     OCMethod method = OC_REST_PRESENCE;
1697     uint32_t maxAge = 0;
1698     resPtr = findResource((OCResource *) presenceResource.handle);
1699     if(NULL == resPtr)
1700     {
1701         return OC_STACK_NO_RESOURCE;
1702     }
1703     if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
1704     {
1705         maxAge = presenceResource.presenceTTL;
1706     }
1707     else
1708     {
1709         maxAge = 0;
1710     }
1711
1712     result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
1713     return result;
1714 }
1715 #endif
1716
1717 /**
1718  * Notify observers that an observed value has changed.
1719  *
1720  * @param handle - handle of resource
1721  *
1722  * @return
1723  *     OC_STACK_OK    - no errors
1724  *     OC_STACK_NO_RESOURCE - invalid resource handle
1725  *     OC_STACK_NO_OBSERVERS - no more observers intrested in resource
1726  */
1727 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
1728
1729     OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
1730
1731     OCResource *resPtr = NULL;
1732     OCStackResult result;
1733     OCMethod method = OC_REST_NOMETHOD;
1734     uint32_t maxAge = 0;
1735
1736     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1737     // Verify that the resource exists
1738     resPtr = findResource ((OCResource *) handle);
1739     if (NULL == resPtr || myStackMode == OC_CLIENT)
1740     {
1741         return OC_STACK_NO_RESOURCE;
1742     }
1743     else
1744     {
1745         //only increment in the case of regular observing (not presence)
1746         incrementSequenceNumber(resPtr);
1747         method = OC_REST_OBSERVE;
1748         maxAge = MAX_OBSERVE_AGE;
1749         #ifdef WITH_PRESENCE
1750         result = SendAllObserverNotification (method, resPtr, maxAge, NULL, qos);
1751         #else
1752         result = SendAllObserverNotification (method, resPtr, maxAge, qos);
1753         #endif
1754         return result;
1755     }
1756 }
1757
1758 OCStackResult
1759 OCNotifyListOfObservers (OCResourceHandle handle,
1760                          OCObservationId  *obsIdList,
1761                          uint8_t          numberOfIds,
1762                          unsigned char    *notificationJSONPayload,
1763                          OCQualityOfService qos)
1764 {
1765     OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
1766
1767     OCResource *resPtr = NULL;
1768     //TODO: we should allow the server to define this
1769     uint32_t maxAge = MAX_OBSERVE_AGE;
1770
1771     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1772     VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
1773     VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
1774
1775     // Verify that the resource exists
1776     resPtr = findResource ((OCResource *) handle);
1777     if (NULL == resPtr || myStackMode == OC_CLIENT)
1778     {
1779         return OC_STACK_NO_RESOURCE;
1780     }
1781     else
1782     {
1783         incrementSequenceNumber(resPtr);
1784     }
1785     return (SendListObserverNotification(resPtr, obsIdList, numberOfIds,
1786             notificationJSONPayload, maxAge, qos));
1787 }
1788
1789 /**
1790  * Send a response to a request.
1791  * The response can be a regular, slow, or block (i.e. a response that
1792  * is too large to be sent in a single PDU and must span multiple transmissions)
1793  *
1794  * @param response - pointer to structure that contains response parameters
1795  *
1796  * @return
1797  *     OC_STACK_OK                         - No errors; Success
1798  *     OC_STACK_INVALID_PARAM              - Invalid pointer to OCServerResponse
1799  *     OC_STACK_INVALID_REQUEST_HANDLE     - Request handle not found
1800  *     OC_STACK_PERSISTENT_BUFFER_REQUIRED - Block transfer needed for response, so a
1801  *                                           persistent response buffer is necessary
1802  */
1803 OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
1804 {
1805     OCStackResult result = OC_STACK_ERROR;
1806     OCServerRequest *serverRequest = NULL;
1807
1808     OC_LOG(INFO, TAG, PCF("Entering OCDoResponse"));
1809
1810     // Validate input parameters
1811     VERIFY_NON_NULL(ehResponse, ERROR, OC_STACK_INVALID_PARAM);
1812     VERIFY_NON_NULL(ehResponse->requestHandle, ERROR, OC_STACK_INVALID_PARAM);
1813
1814     // TODO: Placeholder for creating a response entry when implementing
1815     // block transfer feature
1816
1817     // If a response payload is present, check if block transfer is required
1818     if (ehResponse->payload && OCIsPacketTransferRequired(NULL,
1819             (const char *)ehResponse->payload, ehResponse->payloadSize))
1820     {
1821         OC_LOG(INFO, TAG, PCF("Block transfer required"));
1822
1823         // Persistent response buffer is needed for block transfer
1824         if (!ehResponse->persistentBufferFlag)
1825         {
1826             OC_LOG(WARNING, TAG, PCF("Persistent response buffer required"));
1827             return OC_STACK_PERSISTENT_BUFFER_REQUIRED;
1828         }
1829         // TODO: Placeholder for block transfer handling
1830         // TODO: Placeholder for setting the the response handle in the OCServerResponse struct
1831             // when implementing the block transfer feature
1832     }
1833     else
1834     {
1835         // Normal response
1836
1837         // Get pointer to request info
1838         serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
1839         if(serverRequest)
1840         {
1841             result = serverRequest->ehResponseHandler(ehResponse);
1842         }
1843     }
1844     return result;
1845 }
1846
1847 /**
1848  * Cancel a response.  Applies to a block response
1849  *
1850  * @param responseHandle - response handle set by stack in OCServerResponse after
1851  *                         OCDoResponse is called
1852  *
1853  * @return
1854  *     OC_STACK_OK               - No errors; Success
1855  *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
1856  */
1857 OCStackResult OCCancelResponse(OCResponseHandle responseHandle)
1858 {
1859     OCStackResult result = OC_STACK_NOTIMPL;
1860
1861     OC_LOG(INFO, TAG, PCF("Entering OCCancelResponse"));
1862
1863     // TODO: validate response handle
1864
1865     return result;
1866 }
1867
1868 //-----------------------------------------------------------------------------
1869 // Private internal function definitions
1870 //-----------------------------------------------------------------------------
1871 /**
1872  * Generate handle of OCDoResource invocation for callback management.
1873  */
1874 static OCDoHandle GenerateInvocationHandle()
1875 {
1876     OCDoHandle handle = NULL;
1877     // Generate token here, it will be deleted when the transaction is deleted
1878     handle = (OCDoHandle) OCMalloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1879     if (handle)
1880     {
1881         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1882     }
1883
1884     return handle;
1885 }
1886 #ifdef WITH_PRESENCE
1887 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
1888         OCResourceProperty resourceProperties, uint8_t enable)
1889 {
1890     if (resourceProperties
1891             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
1892         OC_LOG(ERROR, TAG, PCF("Invalid property"));
1893         return OC_STACK_INVALID_PARAM;
1894     }
1895     if(!enable)
1896     {
1897         *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
1898     }
1899     else
1900     {
1901         *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
1902     }
1903     return OC_STACK_OK;
1904 }
1905 #endif
1906
1907 /**
1908  * Initialize resource data structures, variables, etc.
1909  */
1910 OCStackResult initResources() {
1911     OCStackResult result = OC_STACK_OK;
1912     // Init application resource vars
1913     headResource = NULL;
1914     // Init Virtual Resources
1915     #ifdef WITH_PRESENCE
1916     presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
1917     //presenceResource.token = OCGenerateCoAPToken();
1918     result = OCCreateResource(&presenceResource.handle,
1919             "core.presence",
1920             "core.r",
1921             OC_PRESENCE_URI,
1922             NULL,
1923             OC_OBSERVABLE);
1924     //make resource inactive
1925     result = OCChangeResourceProperty(
1926             &(((OCResource *) presenceResource.handle)->resourceProperties),
1927             OC_ACTIVE, 0);
1928     #endif
1929     return result;
1930 }
1931
1932 /**
1933  * Add a resource to the end of the linked list of resources.
1934  *
1935  * @param resource - resource to be added
1936  */
1937 void insertResource(OCResource *resource) {
1938     OCResource *pointer;
1939
1940     if (!headResource) {
1941         headResource = resource;
1942     } else {
1943         pointer = headResource;
1944
1945         while (pointer->next) {
1946             pointer = pointer->next;
1947         }
1948         pointer->next = resource;
1949     }
1950     resource->next = NULL;
1951 }
1952
1953 /**
1954  * Find a resource in the linked list of resources.
1955  *
1956  * @param resource - resource to be found
1957  * @return
1958  *     NULL                - resource not found
1959  *     pointer to resource - pointer to resource that was found in the linked list
1960  */
1961 OCResource *findResource(OCResource *resource) {
1962     OCResource *pointer = headResource;
1963
1964     while (pointer) {
1965         if (pointer == resource) {
1966             return resource;
1967         }
1968         pointer = pointer->next;
1969     }
1970     return NULL;
1971 }
1972
1973 void deleteAllResources()
1974 {
1975     OCResource *pointer = headResource;
1976     OCResource *temp;
1977
1978     while (pointer)
1979     {
1980         temp = pointer->next;
1981         deleteResource(pointer);
1982         pointer = temp;
1983     }
1984 }
1985
1986 /**
1987  * Delete the resource from the linked list.
1988  *
1989  * @param resource - resource to be deleted
1990  * @return
1991  *    0 - error
1992  *    1 - success
1993  */
1994 int deleteResource(OCResource *resource) {
1995     OCResource *prev = NULL;
1996     OCResource *temp;
1997
1998     temp = headResource;
1999     while (temp) {
2000         if (temp == resource) {
2001             // Invalidate all Resource Properties.
2002             resource->resourceProperties = (OCResourceProperty) 0;
2003             OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
2004
2005             #ifdef WITH_PRESENCE
2006             if(presenceResource.handle)
2007             {
2008                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
2009                 SendPresenceNotification(resource->rsrcType);
2010             }
2011             #endif
2012
2013             if (temp == headResource) {
2014                 headResource = temp->next;
2015             } else {
2016                 prev->next = temp->next;
2017             }
2018
2019             deleteResourceElements(temp);
2020             OCFree(temp);
2021             return 1;
2022         } else {
2023             prev = temp;
2024             temp = temp->next;
2025         }
2026     }
2027
2028     return 0;
2029 }
2030
2031 /**
2032  * Delete all of the dynamically allocated elements that were created for the resource.
2033  *
2034  * @param resource - specified resource
2035  */
2036 void deleteResourceElements(OCResource *resource) {
2037     if (!resource) {
2038         return;
2039     }
2040
2041     // remove URI
2042     OCFree(resource->uri);
2043
2044     // Delete resourcetype linked list
2045     deleteResourceType(resource->rsrcType);
2046
2047     // Delete resourceinterface linked list
2048     deleteResourceInterface(resource->rsrcInterface);
2049 }
2050
2051 /**
2052  * Delete all of the dynamically allocated elements that were created for the resource type.
2053  *
2054  * @param resourceType - specified resource type
2055  */
2056 void deleteResourceType(OCResourceType *resourceType) {
2057     OCResourceType *pointer = resourceType;
2058     OCResourceType *next;
2059
2060     while (pointer) {
2061         next = pointer->next;
2062         OCFree(pointer->resourcetypename);
2063         OCFree(pointer);
2064         pointer = next;
2065     }
2066 }
2067
2068 /**
2069  * Delete all of the dynamically allocated elements that were created for the resource interface.
2070  *
2071  * @param resourceInterface - specified resource interface
2072  */
2073 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
2074     OCResourceInterface *pointer = resourceInterface;
2075     OCResourceInterface *next;
2076
2077     while (pointer) {
2078         next = pointer->next;
2079         OCFree(pointer->name);
2080         OCFree(pointer);
2081         pointer = next;
2082     }
2083 }
2084
2085 /**
2086  * Insert a resource type into a resource's resource type linked list.
2087  *
2088  * @param resource - resource where resource type is to be inserted
2089  * @param resourceType - resource type to be inserted
2090  */
2091 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
2092     OCResourceType *pointer;
2093
2094     if (resource && !resource->rsrcType) {
2095         resource->rsrcType = resourceType;
2096     } else {
2097         if(resource)
2098         {
2099             pointer = resource->rsrcType;
2100         }
2101         else
2102         {
2103             pointer = resourceType;
2104         }
2105         while (pointer->next) {
2106             pointer = pointer->next;
2107         }
2108         pointer->next = resourceType;
2109     }
2110     resourceType->next = NULL;
2111 }
2112
2113 /**
2114  * Get a resource type at the specified index within a resource.
2115  *
2116  * @param handle - handle of resource
2117  * @param index - index of resource type
2118  *
2119  * @return
2120  *    resourcetype - if found
2121  *    NULL - not found
2122  */
2123 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
2124     OCResource *resource;
2125     OCResourceType *pointer;
2126     uint8_t i;
2127
2128     // Find the specified resource
2129     resource = findResource((OCResource *) handle);
2130     if (!resource) {
2131         return NULL;
2132     }
2133
2134     // Make sure a resource has a resourcetype
2135     if (!resource->rsrcType) {
2136         return NULL;
2137     }
2138
2139     // Iterate through the list
2140     pointer = resource->rsrcType;
2141     i = 0;
2142     while ((i < index) && pointer) {
2143         i++;
2144         pointer = pointer->next;
2145     }
2146     return pointer;
2147 }
2148
2149 /**
2150  * Insert a resource interface into a resource's resource interface linked list.
2151  *
2152  * @param resource - resource where resource interface is to be inserted
2153  * @param resourceInterface - resource interface to be inserted
2154  */
2155 void insertResourceInterface(OCResource *resource,
2156         OCResourceInterface *resourceInterface) {
2157     OCResourceInterface *pointer;
2158
2159     if (!resource->rsrcInterface) {
2160         resource->rsrcInterface = resourceInterface;
2161     } else {
2162         pointer = resource->rsrcInterface;
2163         while (pointer->next) {
2164             pointer = pointer->next;
2165         }
2166         pointer->next = resourceInterface;
2167     }
2168     resourceInterface->next = NULL;
2169 }
2170
2171 /**
2172  * Get a resource interface at the specified index within a resource.
2173  *
2174  * @param handle - handle of resource
2175  * @param index - index of resource interface
2176  *
2177  * @return
2178  *    resourceinterface - if found
2179  *    NULL - not found
2180  */
2181 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
2182         uint8_t index) {
2183     OCResource *resource;
2184     OCResourceInterface *pointer;
2185     uint8_t i = 0;
2186
2187     // Find the specified resource
2188     resource = findResource((OCResource *) handle);
2189     if (!resource) {
2190         return NULL;
2191     }
2192
2193     // Make sure a resource has a resourceinterface
2194     if (!resource->rsrcInterface) {
2195         return NULL;
2196     }
2197
2198     // Iterate through the list
2199     pointer = resource->rsrcInterface;
2200
2201     while ((i < index) && pointer) {
2202         i++;
2203         pointer = pointer->next;
2204     }
2205     return pointer;
2206 }
2207
2208 /**
2209  * Determine if a request/response must be sent in a block transfer because it is too large to be
2210  * sent in a single PDU.  This function can be used for either a request or a response
2211  *
2212  * @param request  - NULL or pointer to request
2213  * @param response - NULL or pointer to response
2214  * @param size     - 0 or size of the request/response.  If 0, strlen is used for determining
2215  *                   the length of the request/response
2216  *
2217  * @return
2218  *    0 - packet transfer NOT required (i.e. normal request/response)
2219  *    1 - packet transfer required (i.e. block transfer needed)
2220  */
2221 uint8_t OCIsPacketTransferRequired(const char *request, const char *response, uint16_t size)
2222 {
2223     uint8_t result = 0;
2224
2225     // Determine if we are checking a request or a response
2226     if (request)
2227     {
2228         // If size is greater than 0, use it for the request size value, otherwise
2229         // assume request is null terminated and use strlen for size value
2230         if ((size > MAX_REQUEST_LENGTH) || (strlen(request) > MAX_REQUEST_LENGTH))
2231         {
2232             result = 1;
2233         }
2234     }
2235     else if (response)
2236     {
2237         // If size is greater than 0, use it for the response size value, otherwise
2238         // assume response is null terminated and use strlen for size value
2239         if ((size > MAX_RESPONSE_LENGTH) || (strlen(response) > MAX_RESPONSE_LENGTH))
2240         {
2241             result = 1;
2242         }
2243     }
2244     return result;
2245 }
2246
2247 /**
2248  * Retrieves a resource type based upon a uri string if the uri string contains only just one
2249  * resource attribute (and that has to be of type "rt").
2250  *
2251  * @remark This API malloc's memory for the resource type and newURI. Do not malloc resourceType
2252  * or newURI before passing in.
2253  *
2254  * @param uri - Valid URI for "requiredUri" parameter to OCDoResource API.
2255  * @param resourceType - The resource type to be populated; pass by reference.
2256  * @param newURI - Return URI without resourceType appended to the end of it. This is used to
2257  *                 ensure that the uri parameter is not modified; pass by reference.
2258  *
2259  * @return
2260  *  OC_STACK_INVALID_URI   - Returns this if the URI is invalid/NULL.
2261  *  OC_STACK_INVALID_PARAM - Returns this if the resourceType parameter is invalid/NULL.
2262  *  OC_STACK_OK            - Success
2263  */
2264 OCStackResult getResourceType(const char * uri, unsigned char** resourceType, char ** newURI)
2265 {
2266     if(!uri)
2267     {
2268         return OC_STACK_INVALID_URI;
2269     }
2270     if(!resourceType || !newURI)
2271     {
2272         return OC_STACK_INVALID_PARAM;
2273     }
2274     char * ptr = NULL;
2275     char * leftToken = NULL;
2276     char * tempURI = (char *) OCMalloc(strlen(uri));
2277     if(!tempURI)
2278     {
2279         goto exit;
2280     }
2281     ptr = tempURI;
2282     strcpy(tempURI, uri);
2283     leftToken = strtok((char *)tempURI, "?");
2284
2285     while(leftToken != NULL)
2286     {
2287         if(strncmp(leftToken, "rt=", 3) == 0)
2288         {
2289             *resourceType = (unsigned char *) OCMalloc(strlen(leftToken)-3);
2290             if(!*resourceType)
2291             {
2292                 goto exit;
2293             }
2294             strcpy((char *)*resourceType, ((const char *)&leftToken[3]));
2295             break;
2296         }
2297         leftToken = strtok(NULL, "?");
2298     }
2299
2300     *newURI = ptr;
2301
2302     return OC_STACK_OK;
2303
2304     exit:
2305         return OC_STACK_NO_MEMORY;
2306 }