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