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