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