d1d9d84600017b5dbbf378add7855a5fa068861b
[contrib/iotivity.git] / resource / csdk / stack / src / ocstack.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21
22 //-----------------------------------------------------------------------------
23 // Includes
24 //-----------------------------------------------------------------------------
25 #include "ocstack.h"
26 #include "ocstackinternal.h"
27 #include "ocresource.h"
28 #include "occlientcb.h"
29 #include "ocobserve.h"
30 #include "ocrandom.h"
31 #include "debug.h"
32 #include "occoap.h"
33 #include "ocmalloc.h"
34
35 //-----------------------------------------------------------------------------
36 // Typedefs
37 //-----------------------------------------------------------------------------
38 typedef enum {
39     OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED
40 } OCStackState;
41
42 #ifdef WITH_PRESENCE
43 typedef enum {
44     OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED
45 } OCPresenceState;
46 #endif
47
48 //-----------------------------------------------------------------------------
49 // Private variables
50 //-----------------------------------------------------------------------------
51 static OCStackState stackState = OC_STACK_UNINITIALIZED;
52
53 OCResource *headResource = NULL;
54 #ifdef WITH_PRESENCE
55 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
56 static PresenceResource presenceResource;
57 uint8_t PresenceTimeOutSize = 4;
58 uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
59 #endif
60
61 OCMode myStackMode;
62 OCDeviceEntityHandler defaultDeviceHandler;
63
64 //-----------------------------------------------------------------------------
65 // Macros
66 //-----------------------------------------------------------------------------
67 #define TAG  PCF("OCStack")
68 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
69              TAG, PCF(#arg " is NULL")); return (retVal); } }
70
71 //-----------------------------------------------------------------------------
72 // Internal API function
73 //-----------------------------------------------------------------------------
74
75 //This function will be called back by occoap layer when a request is received
76 OCStackResult HandleStackRequests(OCRequest * request)
77 {
78     OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
79
80     OCStackResult result = OC_STACK_ERROR;
81     ResourceHandling resHandling;
82     OCResource *resource;
83
84     VERIFY_NON_NULL(request, ERROR, OC_STACK_ERROR);
85     VERIFY_NON_NULL(request->entityHandlerRequest, ERROR, OC_STACK_ERROR);
86
87     result = DetermineResourceHandling (request, &resHandling, &resource);
88
89     if (result == OC_STACK_OK)
90     {
91         result = BuildJSONResponse(resHandling, resource, request);
92     }
93
94     return result;
95 }
96
97 //This function will be called back by occoap layer when a response is received
98 void HandleStackResponses(OCResponse * response)
99 {
100     OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
101     OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)"));
102
103     if (response->cbNode)
104     {
105         OC_LOG(INFO, TAG, PCF("Calling into application address space"));
106         result = response->cbNode->callBack(response->cbNode->context,
107                 response->cbNode->handle, response->clientResponse);
108         if (result == OC_STACK_DELETE_TRANSACTION ||
109                 response->clientResponse->result == OC_STACK_COMM_ERROR ||
110                 response->clientResponse->result == OC_STACK_RESOURCE_DELETED)
111         {
112             FindAndDeleteClientCB(response->cbNode);
113         }
114     }
115 }
116
117 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
118 {
119     size_t index = 0;
120     unsigned char *itr, *coap;
121     uint8_t dotCount = 0;
122
123     ipAddr[index] = 0;
124     *port = 0;
125     /* search for scheme */
126     itr = ipAddrStr;
127     if (!isdigit((unsigned char) *ipAddrStr))
128     {
129         coap = (unsigned char *) OC_COAP_SCHEME;
130         while (*coap && tolower(*itr) == *coap)
131         {
132             coap++;
133             itr++;
134         }
135     }
136     ipAddrStr = itr;
137
138     while (*ipAddrStr) {
139         if (isdigit((unsigned char) *ipAddrStr))
140         {
141             ipAddr[index] *= 10;
142             ipAddr[index] += *ipAddrStr - '0';
143         }
144         else if ((unsigned char) *ipAddrStr == '.')
145         {
146             index++;
147             dotCount++;
148             ipAddr[index] = 0;
149         }
150         else
151         {
152             break;
153         }
154         ipAddrStr++;
155     }
156     if(*ipAddrStr == ':')
157     {
158         ipAddrStr++;
159         while (*ipAddrStr){
160             if (isdigit((unsigned char) *ipAddrStr))
161             {
162                 *port *= 10;
163                 *port += *ipAddrStr - '0';
164             }
165             else
166             {
167                 break;
168             }
169             ipAddrStr++;
170         }
171     }
172
173
174     if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
175             && dotCount == 3)
176     {
177         return 1;
178     }
179     else
180     {
181         return 0;
182     }
183 }
184
185 //-----------------------------------------------------------------------------
186 // Private internal function prototypes
187 //-----------------------------------------------------------------------------
188
189 static OCDoHandle GenerateInvocationHandle();
190 static OCStackResult initResources();
191 static void insertResource(OCResource *resource);
192 static OCResource *findResource(OCResource *resource);
193 static void insertResourceType(OCResource *resource,
194         OCResourceType *resourceType);
195 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
196         uint8_t index);
197 static void insertResourceInterface(OCResource *resource,
198         OCResourceInterface *resourceInterface);
199 static OCResourceInterface *findResourceInterfaceAtIndex(
200         OCResourceHandle handle, uint8_t index);
201 static void deleteResourceType(OCResourceType *resourceType);
202 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
203 static void deleteResourceElements(OCResource *resource);
204 static int deleteResource(OCResource *resource);
205 static void deleteAllResources();
206 static void incrementSequenceNumber(OCResource * resPtr);
207 static OCStackResult verifyUriQueryLength(const char * inputUri,
208         uint16_t uriLen);
209
210
211 //-----------------------------------------------------------------------------
212 // Public APIs
213 //-----------------------------------------------------------------------------
214
215 /**
216  * Initialize the OC Stack.  Must be called prior to starting the stack.
217  *
218  * @param ipAddr
219  *     IP Address of host device
220  * @param port
221  *     Port of host device
222  * @param mode
223  *     Host device is client, server, or client-server
224  *
225  * @return
226  *     OC_STACK_OK    - no errors
227  *     OC_STACK_ERROR - stack init error
228  */
229 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
230 {
231     OCStackResult result = OC_STACK_ERROR;
232     OC_LOG(INFO, TAG, PCF("Entering OCInit"));
233
234     if (ipAddr)
235     {
236         OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
237     }
238
239     switch (mode)
240     {
241     case OC_CLIENT:
242         OC_LOG(INFO, TAG, PCF("Client mode"));
243         break;
244     case OC_SERVER:
245         OC_LOG(INFO, TAG, PCF("Server mode"));
246         break;
247     case OC_CLIENT_SERVER:
248         OC_LOG(INFO, TAG, PCF("Client-server mode"));
249         break;
250     default:
251         OC_LOG(ERROR, TAG, PCF("Invalid mode"));
252         return OC_STACK_ERROR;
253         break;
254     }
255     myStackMode = mode;
256
257     defaultDeviceHandler = NULL;
258
259     // Make call to OCCoAP layer
260     result = OCInitCoAP(ipAddr, (uint16_t) port, myStackMode);
261     if (result == OC_STACK_OK)
262     {
263         stackState = OC_STACK_INITIALIZED;
264     }
265     // Initialize resource
266     if(result == OC_STACK_OK && myStackMode != OC_CLIENT)
267     {
268         result = initResources();
269     }
270     if(result != OC_STACK_OK)
271     {
272         OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
273     }
274     return result;
275 }
276
277 /**
278  * Stop the OC stack.  Use for a controlled shutdown.
279  * @return
280  *     OC_STACK_OK    - no errors
281  *     OC_STACK_ERROR - stack not initialized
282  */
283 OCStackResult OCStop()
284 {
285     OCStackResult result = OC_STACK_ERROR;
286
287     OC_LOG(INFO, TAG, PCF("Entering OCStop"));
288
289     if (stackState != OC_STACK_INITIALIZED)
290     {
291         OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
292         return OC_STACK_ERROR;
293     }
294
295     // Free memory dynamically allocated for resources
296     deleteAllResources();
297
298     // Make call to OCCoAP layer
299     if (OCStopCoAP() == OC_STACK_OK)
300     {
301         // Remove all observers
302         DeleteObserverList();
303         // Remove all the client callbacks
304         DeleteClientCBList();
305         stackState = OC_STACK_UNINITIALIZED;
306         result = OC_STACK_OK;
307     } else {
308         result = OC_STACK_ERROR;
309     }
310
311     if (result != OC_STACK_OK) {
312         OC_LOG(ERROR, TAG, PCF("Stack stop error"));
313     }
314
315     return result;
316 }
317
318 /**
319  * Verify the lengths of the URI and the query separately
320  *
321  * @param inputUri       - Input URI and query.
322  * @param uriLen         - The length of the initial URI with query.
323  *
324  * Note: The '?' that appears after the URI is not considered as
325  * a part of the query.
326  */
327 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
328 {
329     char *query;
330
331     query = strchr (inputUri, '?');
332
333     if (query != NULL)
334     {
335         if((query - inputUri) > MAX_URI_LENGTH)
336         {
337             return OC_STACK_INVALID_URI;
338         }
339
340         if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
341         {
342             return OC_STACK_INVALID_QUERY;
343         }
344     }
345     else if(uriLen > MAX_URI_LENGTH)
346     {
347         return OC_STACK_INVALID_URI;
348     }
349     return OC_STACK_OK;
350 }
351
352 /**
353  * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
354  *
355  * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
356  * @param method             - @ref OCMethod to perform on the resource
357  * @param requiredUri        - URI of the resource to interact with
358  * @param referenceUri       - URI of the reference resource
359  * @param request            - JSON encoded request
360  * @param qos                - quality of service
361  * @param cbData             - struct that contains asynchronous callback function that is invoked
362  *                             by the stack when discovery or resource interaction is complete
363  * @param options            - The address of an array containing the vendor specific header
364  *                             header options to be sent with the request
365  * @param numOptions         - Number of vendor specific header options to be included
366  *
367  * @return
368  *     OC_STACK_OK               - no errors
369  *     OC_STACK_INVALID_CALLBACK - invalid callback function pointer
370  *     OC_STACK_INVALID_METHOD   - invalid resource method
371  *     OC_STACK_INVALID_URI      - invalid required or reference URI
372  */
373
374 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
375                            const char *referenceUri, const char *request,
376                            OCQualityOfService qos, OCCallbackData *cbData,
377                            OCHeaderOption * options, uint8_t numOptions)
378 {
379     OCStackResult result = OC_STACK_ERROR;
380     OCCoAPToken token;
381     ClientCB *clientCB = NULL;
382     unsigned char * requestUri = NULL;
383     (void) referenceUri;
384
385     OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
386
387     // Validate input parameters
388     VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
389     VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
390
391     TODO ("Need to form the final query by concatenating require and reference URI's");
392     VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
393
394     uint16_t uriLen = strlen(requiredUri);
395
396     // ToDo: We should also check if the requiredUri has a mutlicast address, then qos has to be OC_Low_QOS
397     switch (method)
398     {
399         case OC_REST_GET:
400         case OC_REST_PUT:
401         case OC_REST_POST:
402         case OC_REST_DELETE:
403         case OC_REST_OBSERVE:
404         case OC_REST_OBSERVE_ALL:
405         case OC_REST_CANCEL_OBSERVE:
406             break;
407         #ifdef WITH_PRESENCE
408         case OC_REST_PRESENCE:
409             break;
410         #endif
411         default:
412             result = OC_STACK_INVALID_METHOD;
413             goto exit;
414     }
415
416     if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK)
417     {
418         goto exit;
419     }
420
421     if((request) && (strlen(request) > MAX_REQUEST_LENGTH))
422     {
423         result = OC_STACK_INVALID_PARAM;
424         goto exit;
425     }
426
427     requestUri = (unsigned char *) OCMalloc(uriLen + 1);
428     if(requestUri)
429     {
430         memcpy(requestUri, requiredUri, (uriLen + 1));
431     }
432     else
433     {
434         result = OC_STACK_NO_MEMORY;
435         goto exit;
436     }
437
438     *handle = GenerateInvocationHandle();
439     if(!*handle)
440     {
441         result = OC_STACK_NO_MEMORY;
442         goto exit;
443     }
444
445     // Generate token which will be used by OCStack to match responses received
446     // with the request
447     OCGenerateCoAPToken(&token);
448
449     if((result = AddClientCB(&clientCB, cbData, &token, *handle, method, requestUri)) != OC_STACK_OK)
450     {
451         result = OC_STACK_NO_MEMORY;
452         goto exit;
453     }
454
455     // Make call to OCCoAP layer
456     result = OCDoCoAPResource(method, qos, &token, requiredUri, request, options, numOptions);
457
458 exit:
459     if (result != OC_STACK_OK)
460     {
461         OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
462         FindAndDeleteClientCB(clientCB);
463     }
464     return result;
465 }
466
467 /**
468  * Cancel a request associated with a specific @ref OCDoResource invocation.
469  *
470  * @param handle - Used to identify a specific OCDoResource invocation.
471  * @param qos    - used to specify Quality of Service (read below for more info)
472  * @param options- used to specify vendor specific header options when sending
473  *                 explicit observe cancellation
474  * @param numOptions- Number of header options to be included
475  *
476  * @return
477  *     OC_STACK_OK               - No errors; Success
478  *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
479  */
480 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
481         uint8_t numOptions) {
482     /*
483      * This ftn is implemented one of two ways in the case of observation:
484      *
485      * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
486      *      Remove the callback associated on client side.
487      *      When the next notification comes in from server,
488      *      reply with RESET message to server.
489      *      Keep in mind that the server will react to RESET only
490      *      if the last notification was sent ans CON
491      *
492      * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
493      *      and it is associated with an observe request
494      *      (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
495      *      Send CON Observe request to server with
496      *      observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
497      *      Remove the callback associated on client side.
498      */
499     OCStackResult ret = OC_STACK_OK;
500
501     if(!handle) {
502         return OC_STACK_INVALID_PARAM;
503     }
504
505     OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
506
507     ClientCB *clientCB = GetClientCB(NULL, handle, NULL);
508
509     if(clientCB) {
510         switch (clientCB->method)
511         {
512             case OC_REST_OBSERVE:
513             case OC_REST_OBSERVE_ALL:
514                 if(qos == OC_HIGH_QOS)
515                 {
516                     ret = OCDoCoAPResource(OC_REST_CANCEL_OBSERVE, qos,
517                             &(clientCB->token), (const char *) clientCB->requestUri, NULL, options,
518                             numOptions);
519                 }
520                 else
521                 {
522                     FindAndDeleteClientCB(clientCB);
523                 }
524                 break;
525             #ifdef WITH_PRESENCE
526             case OC_REST_PRESENCE:
527                 FindAndDeleteClientCB(clientCB);
528                 break;
529             #endif
530             default:
531                 return OC_STACK_INVALID_METHOD;
532         }
533     }
534     return ret;
535 }
536 #ifdef WITH_PRESENCE
537 OCStackResult OCProcessPresence()
538 {
539     OCStackResult result = OC_STACK_OK;
540     uint8_t ipAddr[4] = { 0 };
541     uint16_t port = 0;
542
543     OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
544     ClientCB* cbNode = NULL;
545     OCDevAddr dst;
546     OCClientResponse clientResponse;
547     OCResponse * response = NULL;
548
549     LL_FOREACH(cbList, cbNode) {
550         if(OC_REST_PRESENCE == cbNode->method)
551         {
552             if(cbNode->presence)
553             {
554                 uint32_t now = GetTime(0);
555                 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
556                 OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
557                 if(cbNode->presence->TTLlevel != PresenceTimeOutSize){
558                     OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d",
559                             cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
560                 }
561                 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
562                 {
563                     OC_LOG(DEBUG, TAG, "----------------No more timeout ticks");
564                     if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
565                     {
566                         OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
567                                 &dst);
568                         result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_STOPPED,
569                                 (OCDevAddr *) &dst, 0, NULL);
570                         if(result != OC_STACK_OK)
571                         {
572                             goto exit;
573                         }
574                         result = FormOCResponse(&response, cbNode, 0, &clientResponse);
575                         if(result != OC_STACK_OK)
576                         {
577                             goto exit;
578                         }
579                     }
580                     else
581                     {
582                         result = OC_STACK_INVALID_IP;
583                         goto exit;
584                     }
585                     HandleStackResponses(response);
586                 }
587                 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
588                 {
589                     OC_LOG(DEBUG, TAG, "time to test server presence ==========");
590                     OCCoAPToken token;
591                     OCGenerateCoAPToken(&token);
592                     result = OCDoCoAPResource(OC_REST_GET, OC_LOW_QOS,
593                             &token, (const char *)cbNode->requestUri, NULL, NULL, 0);
594                     if(result != OC_STACK_OK)
595                     {
596                         goto exit;
597                     }
598                     cbNode->presence->TTLlevel++;
599                     OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d", cbNode->presence->TTLlevel);
600                 }
601             }
602         }
603     }
604 exit:
605     if (result != OC_STACK_OK)
606     {
607         OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
608     }
609     return result;
610 }
611 #endif
612
613 /**
614  * Called in main loop of OC client or server.  Allows low-level processing of
615  * stack services.
616  *
617  * @return
618  *     OC_STACK_OK    - no errors
619  *     OC_STACK_ERROR - stack process error
620  */
621 OCStackResult OCProcess() {
622
623     OC_LOG(INFO, TAG, PCF("Entering OCProcess"));
624     #ifdef WITH_PRESENCE
625     OCProcessPresence();
626     #endif
627     OCProcessCoAP();
628
629     return OC_STACK_OK;
630 }
631
632 #ifdef WITH_PRESENCE
633 /**
634  * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out
635  * presence notifications to clients via multicast. Once this API has been called with a success,
636  * clients may query for this server's presence and this server's stack will respond via multicast.
637  *
638  * Server can call this function when it comes online for the first time, or when it comes back
639  * online from offline mode, or when it re enters network.
640  *
641  * @param ttl - Time To Live in seconds
642  * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
643  *
644  * @return
645  *     OC_STACK_OK      - No errors; Success
646  */
647 OCStackResult OCStartPresence(const uint32_t ttl)
648 {
649     OCChangeResourceProperty(
650             &(((OCResource *)presenceResource.handle)->resourceProperties),
651             OC_ACTIVE, 1);
652
653     if(ttl > 0)
654     {
655         presenceResource.presenceTTL = ttl;
656     }
657
658     if(OC_PRESENCE_UNINITIALIZED == presenceState)
659     {
660         OCDevAddr multiCastAddr;
661         OCCoAPToken token;
662
663         presenceState = OC_PRESENCE_INITIALIZED;
664         OCGenerateCoAPToken(&token);
665         OCBuildIPv4Address(224, 0, 1, 187, 5683, &multiCastAddr);
666         //add the presence observer
667         AddObserver(OC_PRESENCE_URI, NULL, 0, &token, &multiCastAddr,
668             (OCResource *)presenceResource.handle, OC_LOW_QOS);
669     }
670
671     // Each time OCStartPresence is called
672     // a different random 32-bit integer number is used
673     ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
674
675     return OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
676 }
677
678 /**
679  * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out
680  * presence notifications to clients via multicast. Once this API has been called with a success,
681  * this server's stack will not respond to clients querying for this server's presence.
682  *
683  * Server can call this function when it is terminating, going offline, or when going
684  * away from network.
685  *
686  * @return
687  *     OC_STACK_OK      - No errors; Success
688  */
689 OCStackResult OCStopPresence()
690 {
691     OCStackResult result = OC_STACK_ERROR;
692     //make resource inactive
693     result = OCChangeResourceProperty(
694             &(((OCResource *) presenceResource.handle)->resourceProperties),
695             OC_ACTIVE, 0);
696     result = OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
697     return result;
698 }
699 #endif
700
701
702 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler)
703 {
704     defaultDeviceHandler = entityHandler;
705
706     return OC_STACK_OK;
707 }
708
709 /**
710  * Create a resource
711  *
712  * @param handle - pointer to handle to newly created resource.  Set by ocstack.  Used to refer to resource
713  * @param resourceTypeName - name of resource type.  Example: "core.led"
714  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
715  * @param uri - URI of the resource.  Example:  "/a/led"
716  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
717  *                        NULL for default entity handler
718  * @param resourceProperties - properties supported by resource.  Example: OC_DISCOVERABLE|OC_OBSERVABLE
719  *
720  * @return
721  *     OC_STACK_OK    - no errors
722  *     OC_STACK_ERROR - stack process error
723  */
724 OCStackResult OCCreateResource(OCResourceHandle *handle,
725         const char *resourceTypeName,
726         const char *resourceInterfaceName,
727         const char *uri, OCEntityHandler entityHandler,
728         uint8_t resourceProperties) {
729
730     OCResource *pointer = NULL;
731     char *str = NULL;
732     size_t size;
733     OCStackResult result = OC_STACK_ERROR;
734
735     OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
736
737     if(myStackMode == OC_CLIENT)
738     {
739         return result;
740     }
741     // Validate parameters
742     // Is it presented during resource discovery?
743     if (!handle || !resourceTypeName || !uri) {
744         OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
745         return OC_STACK_INVALID_PARAM;
746     }
747
748     if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0) {
749         resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
750     }
751
752     // Make sure resourceProperties bitmask has allowed properties specified
753     if (resourceProperties
754             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
755         OC_LOG(ERROR, TAG, PCF("Invalid property"));
756         return OC_STACK_INVALID_PARAM;
757     }
758
759     // If the headResource is NULL, then no resources have been created...
760     pointer = headResource;
761     if (pointer) {
762         // At least one resources is in the resource list, so we need to search for
763         // repeated URLs, which are not allowed.  If a repeat is found, exit with an error
764         while (pointer) {
765             if (strcmp(uri, pointer->uri) == 0) {
766                 OC_LOG(ERROR, TAG, PCF("URI already in use"));
767                 return OC_STACK_INVALID_PARAM;
768             }
769             pointer = pointer->next;
770         }
771     }
772     // Create the pointer and insert it into the resource list
773     pointer = (OCResource *) OCMalloc(sizeof(OCResource));
774     if (!pointer) {
775         goto exit;
776     }
777     memset(pointer, 0, sizeof(OCResource));
778     pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
779
780     insertResource(pointer);
781
782     // Set the uri
783     size = strlen(uri) + 1;
784     str = (char *) OCMalloc(size);
785     if (!str) {
786         goto exit;
787     }
788     strncpy(str, uri, size);
789     pointer->uri = str;
790
791     // Set properties.  Set OC_ACTIVE
792     pointer->resourceProperties = (OCResourceProperty) (resourceProperties
793             | OC_ACTIVE);
794
795     // Add the resourcetype to the resource
796     result = OCBindResourceTypeToResource((OCResourceHandle) pointer,
797             resourceTypeName);
798     if (result != OC_STACK_OK) {
799         OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
800         goto exit;
801     }
802
803     // Add the resourceinterface to the resource
804     result = OCBindResourceInterfaceToResource((OCResourceHandle) pointer,
805             resourceInterfaceName);
806     if (result != OC_STACK_OK) {
807         OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
808         goto exit;
809     }
810
811     // If an entity handler has been passed, attach it to the newly created
812     // resource.  Otherwise, set the default entity handler.
813     if (entityHandler)
814     {
815         pointer->entityHandler = entityHandler;
816     }
817     else
818     {
819         pointer->entityHandler = defaultResourceEHandler;
820     }
821
822     *handle = pointer;
823     result = OC_STACK_OK;
824
825     #ifdef WITH_PRESENCE
826     if(presenceResource.handle)
827     {
828         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
829         OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
830     }
831     #endif
832 exit:
833     if (result != OC_STACK_OK)
834     {
835         // Deep delete of resource and other dynamic elements that it contains
836         deleteResource(pointer);
837         OCFree(str);
838     }
839     return result;
840 }
841
842 /**
843  * Add a resource to a collection resource.
844  *
845  * @param collectionHandle - handle to the collection resource
846  * @param resourceHandle - handle to resource to be added to the collection resource
847  *
848  * @return
849  *     OC_STACK_OK    - no errors
850  *     OC_STACK_ERROR - stack process error
851  *     OC_STACK_INVALID_PARAM - invalid collectionhandle
852  */
853 OCStackResult OCBindResource(
854         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
855     OCResource *resource;
856     uint8_t i;
857
858     OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
859
860     // Validate parameters
861     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
862     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
863     // Container cannot contain itself
864     if (collectionHandle == resourceHandle) {
865         OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
866         return OC_STACK_INVALID_PARAM;
867     }
868
869     // Use the handle to find the resource in the resource linked list
870     resource = findResource((OCResource *) collectionHandle);
871     if (!resource) {
872         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
873         return OC_STACK_INVALID_PARAM;
874     }
875
876     // Look for an open slot to add add the child resource.
877     // If found, add it and return success
878     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
879         if (!resource->rsrcResources[i]) {
880             resource->rsrcResources[i] = (OCResource *) resourceHandle;
881             OC_LOG(INFO, TAG, PCF("resource bound"));
882             return OC_STACK_OK;
883         }
884     }
885
886     #ifdef WITH_PRESENCE
887     if(presenceResource.handle)
888     {
889         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
890         OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
891     }
892     #endif
893
894     // Unable to add resourceHandle, so return error
895     return OC_STACK_ERROR;
896 }
897
898 /**
899  * Remove a resource from a collection resource.
900  *
901  * @param collectionHandle - handle to the collection resource
902  * @param resourceHandle - handle to resource to be added to the collection resource
903  *
904  * @return
905  *     OC_STACK_OK    - no errors
906  *     OC_STACK_ERROR - stack process error
907  *     OC_STACK_INVALID_PARAM - invalid collectionHandle
908  */
909 OCStackResult OCUnBindResource(
910         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
911     OCResource *resource;
912     uint8_t i;
913
914     OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
915
916     // Validate parameters
917     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
918     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
919     // Container cannot contain itself
920     if (collectionHandle == resourceHandle) {
921         OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
922         return OC_STACK_INVALID_PARAM;
923     }
924
925     // Use the handle to find the resource in the resource linked list
926     resource = findResource((OCResource *) collectionHandle);
927     if (!resource) {
928         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
929         return OC_STACK_INVALID_PARAM;
930     }
931
932     // Look for an open slot to add add the child resource.
933     // If found, add it and return success
934     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
935         if (resourceHandle == resource->rsrcResources[i]) {
936             resource->rsrcResources[i] = (OCResource *) NULL;
937             OC_LOG(INFO, TAG, PCF("resource unbound"));
938             return OC_STACK_OK;
939         }
940     }
941
942     OC_LOG(INFO, TAG, PCF("resource not found in collection"));
943
944     #ifdef WITH_PRESENCE
945     if(presenceResource.handle)
946     {
947         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
948         OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
949     }
950     #endif
951
952     // Unable to add resourceHandle, so return error
953     return OC_STACK_ERROR;
954 }
955
956
957 /**
958  * Bind a resourcetype to a resource.
959  *
960  * @param handle - handle to the resource
961  * @param resourceTypeName - name of resource type.  Example: "core.led"
962  *
963  * @return
964  *     OC_STACK_OK    - no errors
965  *     OC_STACK_ERROR - stack process error
966  */
967 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
968         const char *resourceTypeName) {
969
970     OCResourceType *pointer = NULL;
971     char *str = NULL;
972     size_t size;
973     OCResource *resource;
974     OCStackResult result = OC_STACK_ERROR;
975
976     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceTypeToResource"));
977
978     // Validate parameters
979     VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
980     // TODO:  Does resource attribute resentation really have to be maintained in stack?
981     // Is it presented during resource discovery?
982
983     // Make sure resource exists
984     resource = findResource((OCResource *) handle);
985     if (!resource) {
986         OC_LOG(ERROR, TAG, PCF("Resource not found"));
987         return OC_STACK_ERROR;
988     }
989
990     TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
991
992     // Create the resourcetype and insert it into the resource list
993     pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
994     if (!pointer) {
995         goto exit;
996     }
997     memset(pointer, 0, sizeof(OCResourceType));
998
999     // Set the resourceTypeName
1000     size = strlen(resourceTypeName) + 1;
1001     str = (char *) OCMalloc(size);
1002     if (!str) {
1003         goto exit;
1004     }
1005     strncpy(str, resourceTypeName, size);
1006     pointer->resourcetypename = str;
1007
1008     insertResourceType(resource, pointer);
1009     result = OC_STACK_OK;
1010
1011     #ifdef WITH_PRESENCE
1012     if(presenceResource.handle)
1013     {
1014         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1015         OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1016     }
1017     #endif
1018
1019     exit: if (result != OC_STACK_OK) {
1020         OCFree(pointer);
1021         OCFree(str);
1022     }
1023     return result;
1024 }
1025
1026 /**
1027  * Bind a resourceinterface to a resource.
1028  *
1029  * @param handle - handle to the resource
1030  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
1031  *
1032  * @return
1033  *     OC_STACK_OK    - no errors
1034  *     OC_STACK_ERROR - stack process error
1035  */
1036 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
1037         const char *resourceInterfaceName) {
1038
1039     OCResourceInterface *pointer = NULL;
1040     char *str = NULL;
1041     size_t size;
1042     OCResource *resource;
1043     OCStackResult result = OC_STACK_ERROR;
1044
1045     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceInterfaceToResource"));
1046
1047     // Validate parameters
1048     VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
1049
1050     // Make sure resource exists
1051     resource = findResource((OCResource *) handle);
1052     if (!resource) {
1053         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1054         return OC_STACK_INVALID_PARAM;
1055     }
1056
1057     TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
1058
1059     // Create the resourceinterface and insert it into the resource list
1060     pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
1061     if (!pointer) {
1062         goto exit;
1063     }
1064     memset(pointer, 0, sizeof(OCResourceInterface));
1065
1066     // Set the resourceinterface name
1067     size = strlen(resourceInterfaceName) + 1;
1068     str = (char *) OCMalloc(size);
1069     if (!str) {
1070         goto exit;
1071     }
1072     strncpy(str, resourceInterfaceName, size);
1073     pointer->name = str;
1074
1075     // Bind the resourceinterface to the resource
1076     insertResourceInterface(resource, pointer);
1077
1078     result = OC_STACK_OK;
1079
1080     #ifdef WITH_PRESENCE
1081     if(presenceResource.handle)
1082     {
1083         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1084         OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1085     }
1086     #endif
1087
1088     exit: if (result != OC_STACK_OK) {
1089         OCFree(pointer);
1090         OCFree(str);
1091     }
1092     return result;
1093 }
1094
1095 /**
1096  * Get the number of resources that have been created in the stack.
1097  *
1098  * @param numResources - pointer to count variable
1099  *
1100  * @return
1101  *     OC_STACK_OK    - no errors
1102  *     OC_STACK_ERROR - stack process error
1103
1104  */
1105 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
1106     OCResource *pointer = headResource;
1107
1108     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
1109     VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
1110     *numResources = 0;
1111     while (pointer) {
1112         *numResources = *numResources + 1;
1113         pointer = pointer->next;
1114     }
1115     return OC_STACK_OK;
1116 }
1117
1118 /**
1119  * Get a resource handle by index.
1120  *
1121  * @param index - index of resource, 0 to Count - 1
1122  *
1123  * @return
1124  *    Resource handle - if found
1125  *    NULL - if not found
1126  */
1127 OCResourceHandle OCGetResourceHandle(uint8_t index) {
1128     OCResource *pointer = headResource;
1129     uint8_t i = 0;
1130
1131     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
1132
1133     // Iterate through the list
1134     while ((i < index) && pointer) {
1135         i++;
1136         pointer = pointer->next;
1137     }
1138     return (OCResourceHandle) pointer;
1139 }
1140
1141 /**
1142  * Delete resource specified by handle.  Deletes resource and all resourcetype and resourceinterface
1143  * linked lists.
1144  *
1145  * @param handle - handle of resource to be deleted
1146  *
1147  * @return
1148  *     OC_STACK_OK              - no errors
1149  *     OC_STACK_ERROR           - stack process error
1150  *     OC_STACK_NO_RESOURCE     - resource not found
1151  *     OC_STACK_INVALID_PARAM   - invalid param
1152  */
1153 OCStackResult OCDeleteResource(OCResourceHandle handle) {
1154     OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
1155
1156     if (!handle) {
1157         OC_LOG(ERROR, TAG, PCF("Invalid param"));
1158         return OC_STACK_INVALID_PARAM;
1159     }
1160     
1161     OCResource *resource = findResource((OCResource *) handle);
1162     if (resource == NULL) {
1163         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1164         return OC_STACK_NO_RESOURCE;
1165     }
1166
1167     if (deleteResource((OCResource *) handle) == 0) {
1168         OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
1169         return OC_STACK_ERROR;
1170     }
1171
1172     return OC_STACK_OK;
1173 }
1174
1175 /**
1176  * Get the URI of the resource specified by handle.
1177  *
1178  * @param handle - handle of resource
1179  * @return
1180  *    URI string - if resource found
1181  *    NULL - resource not found
1182  */
1183 const char *OCGetResourceUri(OCResourceHandle handle) {
1184     OCResource *resource;
1185     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
1186
1187     resource = findResource((OCResource *) handle);
1188     if (resource) {
1189         return resource->uri;
1190     }
1191     return (const char *) NULL;
1192 }
1193
1194 /**
1195  * Get the properties of the resource specified by handle.
1196  * NOTE: that after a resource is created, the OC_ACTIVE property is set
1197  * for the resource by the stack.
1198  *
1199  * @param handle - handle of resource
1200  * @return
1201  *    property bitmap - if resource found
1202  *    NULL - resource not found
1203  */
1204 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
1205     OCResource *resource;
1206     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
1207
1208     resource = findResource((OCResource *) handle);
1209     if (resource) {
1210         return resource->resourceProperties;
1211     }
1212     return 0;
1213 }
1214
1215 /**
1216  * Get the number of resource types of the resource.
1217  *
1218  * @param handle - handle of resource
1219  * @param numResourceTypes - pointer to count variable
1220  *
1221  * @return
1222  *     OC_STACK_OK    - no errors
1223  *     OC_STACK_ERROR - stack process error
1224  */
1225 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
1226         uint8_t *numResourceTypes) {
1227     OCResource *resource;
1228     OCResourceType *pointer;
1229
1230     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
1231     VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
1232     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1233
1234     *numResourceTypes = 0;
1235
1236     resource = findResource((OCResource *) handle);
1237     if (resource) {
1238         pointer = resource->rsrcType;
1239         while (pointer) {
1240             *numResourceTypes = *numResourceTypes + 1;
1241             pointer = pointer->next;
1242         }
1243     }
1244     return OC_STACK_OK;
1245 }
1246
1247 /**
1248  * Get name of resource type of the resource.
1249  *
1250  * @param handle - handle of resource
1251  * @param index - index of resource, 0 to Count - 1
1252  *
1253  * @return
1254  *    resource type name - if resource found
1255  *    NULL - resource not found
1256  */
1257 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
1258     OCResourceType *resourceType;
1259
1260     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
1261
1262     resourceType = findResourceTypeAtIndex(handle, index);
1263     if (resourceType) {
1264         return resourceType->resourcetypename;
1265     }
1266     return (const char *) NULL;
1267 }
1268
1269
1270
1271 /**
1272  * Get the number of resource interfaces of the resource.
1273  *
1274  * @param handle - handle of resource
1275  * @param numResources - pointer to count variable
1276  *
1277  * @return
1278  *     OC_STACK_OK    - no errors
1279  *     OC_STACK_ERROR - stack process error
1280  */
1281 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
1282         uint8_t *numResourceInterfaces) {
1283     OCResourceInterface *pointer;
1284     OCResource *resource;
1285
1286     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
1287
1288     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1289     VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
1290
1291     *numResourceInterfaces = 0;
1292     resource = findResource((OCResource *) handle);
1293     if (resource) {
1294         pointer = resource->rsrcInterface;
1295         while (pointer) {
1296             *numResourceInterfaces = *numResourceInterfaces + 1;
1297             pointer = pointer->next;
1298         }
1299     }
1300     return OC_STACK_OK;
1301 }
1302
1303 /**
1304  * Get name of resource interface of the resource.
1305  *
1306  * @param handle - handle of resource
1307  * @param index - index of resource, 0 to Count - 1
1308  *
1309  * @return
1310  *    resource interface name - if resource found
1311  *    NULL - resource not found
1312  */
1313 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
1314     OCResourceInterface *resourceInterface;
1315
1316     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
1317
1318     resourceInterface = findResourceInterfaceAtIndex(handle, index);
1319     if (resourceInterface) {
1320         return resourceInterface->name;
1321     }
1322     return (const char *) NULL;
1323 }
1324
1325 /**
1326  * Get resource handle from the collection resource by index.
1327  *
1328  * @param collectionHandle - handle of collection resource
1329  * @param index - index of contained resource, 0 to Count - 1
1330  *
1331  * @return
1332  *    handle to resource - if resource found
1333  *    NULL - resource not found
1334  */
1335 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
1336         uint8_t index) {
1337     OCResource *resource;
1338
1339     OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
1340
1341     if (index >= MAX_CONTAINED_RESOURCES) {
1342         return NULL;
1343     }
1344
1345     resource = findResource((OCResource *) collectionHandle);
1346     if (!resource) {
1347         return NULL;
1348     }
1349
1350     return resource->rsrcResources[index];
1351 }
1352
1353 /**
1354  * Bind an entity handler to the resource.
1355  *
1356  * @param handle - handle to the resource that the contained resource is to be bound
1357  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1358  * @return
1359  *     OC_STACK_OK    - no errors
1360  *     OC_STACK_ERROR - stack process error
1361  */
1362 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
1363         OCEntityHandler entityHandler) {
1364     OCResource *resource;
1365
1366     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
1367
1368     // Validate parameters
1369     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1370     //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
1371
1372     // Use the handle to find the resource in the resource linked list
1373     resource = findResource((OCResource *)handle);
1374     if (!resource) {
1375         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1376         return OC_STACK_ERROR;
1377     }
1378
1379     // Bind the handler
1380     resource->entityHandler = entityHandler;
1381
1382     #ifdef WITH_PRESENCE
1383     if(presenceResource.handle)
1384     {
1385         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1386         OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1387     }
1388     #endif
1389
1390     return OC_STACK_OK;
1391 }
1392
1393 /**
1394  * Get the entity handler for a resource.
1395  *
1396  * @param handle - handle of resource
1397  *
1398  * @return
1399  *    entity handler - if resource found
1400  *    NULL - resource not found
1401  */
1402 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
1403     OCResource *resource;
1404
1405     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
1406
1407     // Use the handle to find the resource in the resource linked list
1408     resource = findResource((OCResource *)handle);
1409     if (!resource) {
1410         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1411         return NULL;
1412     }
1413
1414     // Bind the handler
1415     return resource->entityHandler;
1416 }
1417
1418 void incrementSequenceNumber(OCResource * resPtr)
1419 {
1420     // Increment the sequence number
1421     resPtr->sequenceNum += 1;
1422     if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
1423     {
1424         resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
1425     }
1426     return;
1427 }
1428
1429 /**
1430  * Notify observers that an observed value has changed.
1431  *
1432  * @param handle - handle of resource
1433  *
1434  * @return
1435  *     OC_STACK_OK    - no errors
1436  *     OC_STACK_NO_RESOURCE - invalid resource handle
1437  *     OC_STACK_NO_OBSERVERS - no more observers intrested in resource
1438  */
1439 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
1440     OCResource *resPtr = NULL;
1441     OCStackResult result;
1442     OCMethod method = OC_REST_NOMETHOD;
1443     uint32_t maxAge = 0;
1444
1445     OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
1446
1447     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1448
1449     // Verify that the resource exists
1450     resPtr = findResource ((OCResource *) handle);
1451     if (NULL == resPtr || myStackMode == OC_CLIENT)
1452     {
1453         return OC_STACK_NO_RESOURCE;
1454     } else {
1455         #ifdef WITH_PRESENCE
1456         if(strcmp(resPtr->uri, OC_PRESENCE_URI))
1457         {
1458         #endif
1459             //only increment in the case of regular observing (not presence)
1460             incrementSequenceNumber(resPtr);
1461             method = OC_REST_OBSERVE;
1462             maxAge = 0x2FFFF;
1463         #ifdef WITH_PRESENCE
1464         }
1465         else
1466         {
1467             method = OC_REST_PRESENCE;
1468             if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
1469             {
1470                 maxAge = presenceResource.presenceTTL;
1471             }
1472             else
1473             {
1474                 maxAge = 0;
1475             }
1476
1477         }
1478         #endif
1479         result = SendObserverNotification (method, resPtr, maxAge, qos);
1480         return result;
1481     }
1482 }
1483
1484 OCStackResult
1485 OCNotifyListOfObservers (OCResourceHandle handle,
1486                          OCObservationId  *obsIdList,
1487                          uint8_t          numberOfIds,
1488                          unsigned char    *notificationJSONPayload,
1489                          OCQualityOfService qos)
1490 {
1491     OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
1492
1493     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1494     VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
1495     VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
1496
1497     uint8_t numIds = numberOfIds;
1498     ResourceObserver *observation;
1499     OCResource *resPtr = NULL;
1500     uint32_t maxAge = 0;
1501     unsigned char bufNotify[MAX_RESPONSE_LENGTH] = {0};
1502     unsigned char *currPtr;
1503     uint8_t numSentNotification = 0;
1504
1505     // Verify the notification payload length does not exceed the maximim
1506     // the stack can handle
1507     if ((strlen((char *)notificationJSONPayload) +
1508          OC_JSON_PREFIX_LEN + OC_JSON_SUFFIX_LEN) > MAX_RESPONSE_LENGTH)
1509     {
1510         OC_LOG(INFO, TAG, PCF("Observe notification message length too long"));
1511         return OC_STACK_ERROR;
1512     }
1513
1514     // Verify that the resource exists
1515     resPtr = findResource ((OCResource *) handle);
1516     if (NULL == resPtr || myStackMode == OC_CLIENT)
1517     {
1518         return OC_STACK_NO_RESOURCE;
1519     }
1520     else
1521     {
1522         incrementSequenceNumber(resPtr);
1523         //TODO: we should allow the serve to define thisl
1524         maxAge = 0x2FFFF;
1525     }
1526
1527     while (numIds)
1528     {
1529         OC_LOG_V(INFO, TAG, "Need to notify observation id %d", *obsIdList);
1530         observation = NULL;
1531         observation = GetObserverUsingId (*obsIdList);
1532         if (observation)
1533         {
1534             // Found observation - verify if it matches the resource handle
1535             if (observation->resource == resPtr)
1536             {
1537                 strcpy((char*)bufNotify, OC_JSON_PREFIX);
1538                 currPtr = bufNotify + OC_JSON_PREFIX_LEN;
1539                 memcpy (currPtr, notificationJSONPayload, strlen((char *)notificationJSONPayload));
1540                 currPtr += strlen((char *)notificationJSONPayload);
1541                 strcpy((char*)currPtr, OC_JSON_SUFFIX);
1542
1543                 // send notifications based on the qos of the request
1544                 // The qos passed as a parameter overrides what the client requested
1545                 // If we want the client preference taking high priority add:
1546                 // QoS = resourceObserver->qos;
1547                 if(qos == OC_NA_QOS){
1548                     qos = observation->qos;
1549                 }
1550                 if(qos != OC_HIGH_QOS)
1551                 {
1552                     OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
1553                             observation->lowQosCount);
1554                     if(observation->forceHighQos \
1555                             || observation->lowQosCount >= MAX_OBSERVER_NON_COUNT)
1556                     {
1557                         observation->lowQosCount = 0;
1558                         // at some point we have to to send CON to check on the
1559                         // availability of observer
1560                         OC_LOG(INFO, TAG, PCF("This time we are sending the \
1561                                 notification as High qos"));
1562                         qos = OC_HIGH_QOS;
1563                     }
1564                     else
1565                     {
1566                         observation->lowQosCount++;
1567                     }
1568                 }
1569                 OCSendCoAPNotification (observation->resUri, observation->addr,
1570                                         qos, &(observation->token),
1571                                         bufNotify, resPtr, maxAge);
1572                 numSentNotification++;
1573             }
1574         }
1575         obsIdList++;
1576         numIds--;
1577     }
1578     if(numSentNotification == numberOfIds)
1579     {
1580         return OC_STACK_OK;
1581     }
1582     else if(numSentNotification == 0)
1583     {
1584         return OC_STACK_NO_OBSERVERS;
1585     }
1586     else
1587     {
1588         //TODO: we need to signal that not every one in the
1589         // list got an update, should we also indicate who did not receive on?
1590         return OC_STACK_OK;
1591     }
1592 }
1593
1594 //-----------------------------------------------------------------------------
1595 // Private internal function definitions
1596 //-----------------------------------------------------------------------------
1597 /**
1598  * Generate handle of OCDoResource invocation for callback management.
1599  */
1600 static OCDoHandle GenerateInvocationHandle()
1601 {
1602     OCDoHandle handle = NULL;
1603     // Generate token here, it will be deleted when the transaction is deleted
1604     handle = (OCDoHandle) malloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1605     if (handle)
1606     {
1607         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1608     }
1609
1610     return handle;
1611 }
1612 #ifdef WITH_PRESENCE
1613 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
1614         OCResourceProperty resourceProperties, uint8_t enable)
1615 {
1616     if (resourceProperties
1617             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
1618         OC_LOG(ERROR, TAG, PCF("Invalid property"));
1619         return OC_STACK_INVALID_PARAM;
1620     }
1621     if(!enable)
1622     {
1623         *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
1624     }
1625     else
1626     {
1627         *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
1628     }
1629     return OC_STACK_OK;
1630 }
1631 #endif
1632
1633 /**
1634  * Initialize resource data structures, variables, etc.
1635  */
1636 OCStackResult initResources() {
1637     OCStackResult result = OC_STACK_OK;
1638     // Init application resource vars
1639     headResource = NULL;
1640     // Init Virtual Resources
1641     #ifdef WITH_PRESENCE
1642     presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
1643     //presenceResource.token = OCGenerateCoAPToken();
1644     result = OCCreateResource(&presenceResource.handle,
1645             "core.presence",
1646             "core.r",
1647             OC_PRESENCE_URI,
1648             NULL,
1649             OC_OBSERVABLE);
1650     //make resource inactive
1651     result = OCChangeResourceProperty(
1652             &(((OCResource *) presenceResource.handle)->resourceProperties),
1653             OC_ACTIVE, 0);
1654     #endif
1655     return result;
1656 }
1657
1658 /**
1659  * Add a resource to the end of the linked list of resources.
1660  *
1661  * @param resource - resource to be added
1662  */
1663 void insertResource(OCResource *resource) {
1664     OCResource *pointer;
1665
1666     if (!headResource) {
1667         headResource = resource;
1668     } else {
1669         pointer = headResource;
1670
1671         while (pointer->next) {
1672             pointer = pointer->next;
1673         }
1674         pointer->next = resource;
1675     }
1676     resource->next = NULL;
1677 }
1678
1679 /**
1680  * Find a resource in the linked list of resources.
1681  *
1682  * @param resource - resource to be found
1683  * @return
1684  *     NULL                - resource not found
1685  *     pointer to resource - pointer to resource that was found in the linked list
1686  */
1687 OCResource *findResource(OCResource *resource) {
1688     OCResource *pointer = headResource;
1689
1690     while (pointer) {
1691         if (pointer == resource) {
1692             return resource;
1693         }
1694         pointer = pointer->next;
1695     }
1696     return NULL;
1697 }
1698
1699 void deleteAllResources()
1700 {
1701     OCResource *pointer = headResource;
1702     OCResource *temp;
1703
1704     while (pointer)
1705     {
1706         temp = pointer->next;
1707         deleteResource(pointer);
1708         pointer = temp;
1709     }
1710 }
1711
1712 /**
1713  * Delete the resource from the linked list.
1714  *
1715  * @param resource - resource to be deleted
1716  * @return
1717  *    0 - error
1718  *    1 - success
1719  */
1720 int deleteResource(OCResource *resource) {
1721     OCResource *prev = NULL;
1722     OCResource *temp;
1723
1724     temp = headResource;
1725     while (temp) {
1726         if (temp == resource) {
1727             // Invalidate all Resource Properties.
1728             resource->resourceProperties = (OCResourceProperty) 0;
1729             OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
1730
1731             #ifdef WITH_PRESENCE
1732             if(presenceResource.handle)
1733             {
1734                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1735                 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1736             }
1737             #endif
1738
1739             if (temp == headResource) {
1740                 headResource = temp->next;
1741             } else {
1742                 prev->next = temp->next;
1743             }
1744
1745             deleteResourceElements(temp);
1746             OCFree(temp);
1747             return 1;
1748         } else {
1749             prev = temp;
1750             temp = temp->next;
1751         }
1752     }
1753
1754     return 0;
1755 }
1756
1757 /**
1758  * Delete all of the dynamically allocated elements that were created for the resource.
1759  *
1760  * @param resource - specified resource
1761  */
1762 void deleteResourceElements(OCResource *resource) {
1763     if (!resource) {
1764         return;
1765     }
1766
1767     // remove URI
1768     OCFree(resource->uri);
1769
1770     // Delete resourcetype linked list
1771     deleteResourceType(resource->rsrcType);
1772
1773     // Delete resourceinterface linked list
1774     deleteResourceInterface(resource->rsrcInterface);
1775 }
1776
1777 /**
1778  * Delete all of the dynamically allocated elements that were created for the resource type.
1779  *
1780  * @param resourceType - specified resource type
1781  */
1782 void deleteResourceType(OCResourceType *resourceType) {
1783     OCResourceType *pointer = resourceType;
1784     OCResourceType *next;
1785
1786     while (pointer) {
1787         next = pointer->next;
1788         OCFree(pointer->resourcetypename);
1789         OCFree(pointer);
1790         pointer = next;
1791     }
1792 }
1793
1794 /**
1795  * Delete all of the dynamically allocated elements that were created for the resource interface.
1796  *
1797  * @param resourceInterface - specified resource interface
1798  */
1799 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
1800     OCResourceInterface *pointer = resourceInterface;
1801     OCResourceInterface *next;
1802
1803     while (pointer) {
1804         next = pointer->next;
1805         OCFree(pointer->name);
1806         OCFree(pointer);
1807         pointer = next;
1808     }
1809 }
1810
1811 /**
1812  * Insert a resource type into a resource's resource type linked list.
1813  *
1814  * @param resource - resource where resource type is to be inserted
1815  * @param resourceType - resource type to be inserted
1816  */
1817 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
1818     OCResourceType *pointer;
1819
1820     if (!resource->rsrcType) {
1821         resource->rsrcType = resourceType;
1822     } else {
1823         pointer = resource->rsrcType;
1824         while (pointer->next) {
1825             pointer = pointer->next;
1826         }
1827         pointer->next = resourceType;
1828     }
1829     resourceType->next = NULL;
1830 }
1831
1832 /**
1833  * Get a resource type at the specified index within a resource.
1834  *
1835  * @param handle - handle of resource
1836  * @param index - index of resource type
1837  *
1838  * @return
1839  *    resourcetype - if found
1840  *    NULL - not found
1841  */
1842 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
1843     OCResource *resource;
1844     OCResourceType *pointer;
1845     uint8_t i;
1846
1847     // Find the specified resource
1848     resource = findResource((OCResource *) handle);
1849     if (!resource) {
1850         return NULL;
1851     }
1852
1853     // Make sure a resource has a resourcetype
1854     if (!resource->rsrcType) {
1855         return NULL;
1856     }
1857
1858     // Iterate through the list
1859     pointer = resource->rsrcType;
1860     i = 0;
1861     while ((i < index) && pointer) {
1862         i++;
1863         pointer = pointer->next;
1864     }
1865     return pointer;
1866 }
1867
1868 /**
1869  * Insert a resource interface into a resource's resource interface linked list.
1870  *
1871  * @param resource - resource where resource interface is to be inserted
1872  * @param resourceInterface - resource interface to be inserted
1873  */
1874 void insertResourceInterface(OCResource *resource,
1875         OCResourceInterface *resourceInterface) {
1876     OCResourceInterface *pointer;
1877
1878     if (!resource->rsrcInterface) {
1879         resource->rsrcInterface = resourceInterface;
1880     } else {
1881         pointer = resource->rsrcInterface;
1882         while (pointer->next) {
1883             pointer = pointer->next;
1884         }
1885         pointer->next = resourceInterface;
1886     }
1887     resourceInterface->next = NULL;
1888 }
1889
1890 /**
1891  * Get a resource interface at the specified index within a resource.
1892  *
1893  * @param handle - handle of resource
1894  * @param index - index of resource interface
1895  *
1896  * @return
1897  *    resourceinterface - if found
1898  *    NULL - not found
1899  */
1900 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
1901         uint8_t index) {
1902     OCResource *resource;
1903     OCResourceInterface *pointer;
1904     uint8_t i = 0;
1905
1906     // Find the specified resource
1907     resource = findResource((OCResource *) handle);
1908     if (!resource) {
1909         return NULL;
1910     }
1911
1912     // Make sure a resource has a resourceinterface
1913     if (!resource->rsrcInterface) {
1914         return NULL;
1915     }
1916
1917     // Iterate through the list
1918     pointer = resource->rsrcInterface;
1919
1920     while ((i < index) && pointer) {
1921         i++;
1922         pointer = pointer->next;
1923     }
1924     return pointer;
1925 }
1926
1927