Merge "fix coding standard problem"
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocstack.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21
22 //-----------------------------------------------------------------------------
23 // Includes
24 //-----------------------------------------------------------------------------
25 #include "ocstack.h"
26 #include "ocstackinternal.h"
27 #include "ocresource.h"
28 #include "occlientcb.h"
29 #include "ocobserve.h"
30 #include "ocrandom.h"
31 #include "debug.h"
32 #include "occoap.h"
33 #include "ocmalloc.h"
34
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
844 /**
845  * Create a resource. with host ip address for remote resource
846  *
847  * @param handle - pointer to handle to newly created resource.  Set by ocstack.
848  *                 Used to refer to resource
849  * @param resourceTypeName - name of resource type.  Example: "core.led"
850  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
851  * @param host - HOST address of the remote resource.  Example:  "coap://xxx.xxx.xxx.xxx:xxxxx"
852  * @param uri - URI of the resource.  Example:  "/a/led"
853  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
854  *                        NULL for default entity handler
855  * @param resourceProperties - properties supported by resource.
856  *                             Example: OC_DISCOVERABLE|OC_OBSERVABLE
857  *
858  * @return
859  *     OC_STACK_OK    - no errors
860  *     OC_STACK_ERROR - stack process error
861  */
862
863 OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle,
864         const char *resourceTypeName,
865         const char *resourceInterfaceName,
866         const char *host,
867         const char *uri,
868         OCEntityHandler entityHandler,
869         uint8_t resourceProperties)
870 {
871     char *str = NULL;
872     size_t size;
873     OCStackResult result = OC_STACK_ERROR;
874
875     result = OCCreateResource(handle, resourceTypeName, resourceInterfaceName,
876                                 uri, entityHandler, resourceProperties);
877
878     if (result != OC_STACK_ERROR)
879     {
880         // Set the uri
881         size = strlen(host) + 1;
882         str = (char *) OCMalloc(size);
883         if (!str)
884         {
885             return OC_STACK_ERROR;
886         }
887         strncpy(str, host, size);
888         ((OCResource *) *handle)->host = str;
889     }
890
891     return result;
892 }
893
894 /**
895  * Add a resource to a collection resource.
896  *
897  * @param collectionHandle - handle to the collection resource
898  * @param resourceHandle - handle to resource to be added to the collection resource
899  *
900  * @return
901  *     OC_STACK_OK    - no errors
902  *     OC_STACK_ERROR - stack process error
903  *     OC_STACK_INVALID_PARAM - invalid collectionhandle
904  */
905 OCStackResult OCBindResource(
906         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
907     OCResource *resource;
908     uint8_t i;
909
910     OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
911
912     // Validate parameters
913     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
914     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
915     // Container cannot contain itself
916     if (collectionHandle == resourceHandle) {
917         OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
918         return OC_STACK_INVALID_PARAM;
919     }
920
921     // Use the handle to find the resource in the resource linked list
922     resource = findResource((OCResource *) collectionHandle);
923     if (!resource) {
924         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
925         return OC_STACK_INVALID_PARAM;
926     }
927
928     // Look for an open slot to add add the child resource.
929     // If found, add it and return success
930     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
931         if (!resource->rsrcResources[i]) {
932             resource->rsrcResources[i] = (OCResource *) resourceHandle;
933             OC_LOG(INFO, TAG, PCF("resource bound"));
934             return OC_STACK_OK;
935         }
936     }
937
938     #ifdef WITH_PRESENCE
939     if(presenceResource.handle)
940     {
941         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
942         OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
943     }
944     #endif
945
946     // Unable to add resourceHandle, so return error
947     return OC_STACK_ERROR;
948 }
949
950 /**
951  * Remove a resource from a collection resource.
952  *
953  * @param collectionHandle - handle to the collection resource
954  * @param resourceHandle - handle to resource to be added to the collection resource
955  *
956  * @return
957  *     OC_STACK_OK    - no errors
958  *     OC_STACK_ERROR - stack process error
959  *     OC_STACK_INVALID_PARAM - invalid collectionHandle
960  */
961 OCStackResult OCUnBindResource(
962         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
963     OCResource *resource;
964     uint8_t i;
965
966     OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
967
968     // Validate parameters
969     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
970     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
971     // Container cannot contain itself
972     if (collectionHandle == resourceHandle) {
973         OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
974         return OC_STACK_INVALID_PARAM;
975     }
976
977     // Use the handle to find the resource in the resource linked list
978     resource = findResource((OCResource *) collectionHandle);
979     if (!resource) {
980         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
981         return OC_STACK_INVALID_PARAM;
982     }
983
984     // Look for an open slot to add add the child resource.
985     // If found, add it and return success
986     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
987         if (resourceHandle == resource->rsrcResources[i]) {
988             resource->rsrcResources[i] = (OCResource *) NULL;
989             OC_LOG(INFO, TAG, PCF("resource unbound"));
990             return OC_STACK_OK;
991         }
992     }
993
994     OC_LOG(INFO, TAG, PCF("resource not found in collection"));
995
996     #ifdef WITH_PRESENCE
997     if(presenceResource.handle)
998     {
999         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1000         OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1001     }
1002     #endif
1003
1004     // Unable to add resourceHandle, so return error
1005     return OC_STACK_ERROR;
1006 }
1007
1008
1009 /**
1010  * Bind a resourcetype to a resource.
1011  *
1012  * @param handle - handle to the resource
1013  * @param resourceTypeName - name of resource type.  Example: "core.led"
1014  *
1015  * @return
1016  *     OC_STACK_OK    - no errors
1017  *     OC_STACK_ERROR - stack process error
1018  */
1019 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
1020         const char *resourceTypeName) {
1021
1022     OCResourceType *pointer = NULL;
1023     char *str = NULL;
1024     size_t size;
1025     OCResource *resource;
1026     OCStackResult result = OC_STACK_ERROR;
1027
1028     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceTypeToResource"));
1029
1030     // Validate parameters
1031     VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
1032     // TODO:  Does resource attribute resentation really have to be maintained in stack?
1033     // Is it presented during resource discovery?
1034
1035     // Make sure resource exists
1036     resource = findResource((OCResource *) handle);
1037     if (!resource) {
1038         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1039         return OC_STACK_ERROR;
1040     }
1041
1042     TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
1043
1044     // Create the resourcetype and insert it into the resource list
1045     pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
1046     if (!pointer) {
1047         goto exit;
1048     }
1049     memset(pointer, 0, sizeof(OCResourceType));
1050
1051     // Set the resourceTypeName
1052     size = strlen(resourceTypeName) + 1;
1053     str = (char *) OCMalloc(size);
1054     if (!str) {
1055         goto exit;
1056     }
1057     strncpy(str, resourceTypeName, size);
1058     pointer->resourcetypename = str;
1059
1060     insertResourceType(resource, pointer);
1061     result = OC_STACK_OK;
1062
1063     #ifdef WITH_PRESENCE
1064     if(presenceResource.handle)
1065     {
1066         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1067         OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1068     }
1069     #endif
1070
1071     exit: if (result != OC_STACK_OK) {
1072         OCFree(pointer);
1073         OCFree(str);
1074     }
1075     return result;
1076 }
1077
1078 /**
1079  * Bind a resourceinterface to a resource.
1080  *
1081  * @param handle - handle to the resource
1082  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
1083  *
1084  * @return
1085  *     OC_STACK_OK    - no errors
1086  *     OC_STACK_ERROR - stack process error
1087  */
1088 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
1089         const char *resourceInterfaceName) {
1090
1091     OCResourceInterface *pointer = NULL;
1092     char *str = NULL;
1093     size_t size;
1094     OCResource *resource;
1095     OCStackResult result = OC_STACK_ERROR;
1096
1097     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceInterfaceToResource"));
1098
1099     // Validate parameters
1100     VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
1101
1102     // Make sure resource exists
1103     resource = findResource((OCResource *) handle);
1104     if (!resource) {
1105         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1106         return OC_STACK_INVALID_PARAM;
1107     }
1108
1109     TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
1110
1111     // Create the resourceinterface and insert it into the resource list
1112     pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
1113     if (!pointer) {
1114         goto exit;
1115     }
1116     memset(pointer, 0, sizeof(OCResourceInterface));
1117
1118     // Set the resourceinterface name
1119     size = strlen(resourceInterfaceName) + 1;
1120     str = (char *) OCMalloc(size);
1121     if (!str) {
1122         goto exit;
1123     }
1124     strncpy(str, resourceInterfaceName, size);
1125     pointer->name = str;
1126
1127     // Bind the resourceinterface to the resource
1128     insertResourceInterface(resource, pointer);
1129
1130     result = OC_STACK_OK;
1131
1132     #ifdef WITH_PRESENCE
1133     if(presenceResource.handle)
1134     {
1135         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1136         OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1137     }
1138     #endif
1139
1140     exit: if (result != OC_STACK_OK) {
1141         OCFree(pointer);
1142         OCFree(str);
1143     }
1144     return result;
1145 }
1146
1147 /**
1148  * Get the number of resources that have been created in the stack.
1149  *
1150  * @param numResources - pointer to count variable
1151  *
1152  * @return
1153  *     OC_STACK_OK    - no errors
1154  *     OC_STACK_ERROR - stack process error
1155
1156  */
1157 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
1158     OCResource *pointer = headResource;
1159
1160     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
1161     VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
1162     *numResources = 0;
1163     while (pointer) {
1164         *numResources = *numResources + 1;
1165         pointer = pointer->next;
1166     }
1167     return OC_STACK_OK;
1168 }
1169
1170 /**
1171  * Get a resource handle by index.
1172  *
1173  * @param index - index of resource, 0 to Count - 1
1174  *
1175  * @return
1176  *    Resource handle - if found
1177  *    NULL - if not found
1178  */
1179 OCResourceHandle OCGetResourceHandle(uint8_t index) {
1180     OCResource *pointer = headResource;
1181     uint8_t i = 0;
1182
1183     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
1184
1185     // Iterate through the list
1186     while ((i < index) && pointer) {
1187         i++;
1188         pointer = pointer->next;
1189     }
1190     return (OCResourceHandle) pointer;
1191 }
1192
1193 /**
1194  * Delete resource specified by handle.  Deletes resource and all resourcetype and resourceinterface
1195  * linked lists.
1196  *
1197  * @param handle - handle of resource to be deleted
1198  *
1199  * @return
1200  *     OC_STACK_OK              - no errors
1201  *     OC_STACK_ERROR           - stack process error
1202  *     OC_STACK_NO_RESOURCE     - resource not found
1203  *     OC_STACK_INVALID_PARAM   - invalid param
1204  */
1205 OCStackResult OCDeleteResource(OCResourceHandle handle) {
1206     OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
1207
1208     if (!handle) {
1209         OC_LOG(ERROR, TAG, PCF("Invalid param"));
1210         return OC_STACK_INVALID_PARAM;
1211     }
1212
1213     OCResource *resource = findResource((OCResource *) handle);
1214     if (resource == NULL) {
1215         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1216         return OC_STACK_NO_RESOURCE;
1217     }
1218
1219     if (deleteResource((OCResource *) handle) == 0) {
1220         OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
1221         return OC_STACK_ERROR;
1222     }
1223
1224     return OC_STACK_OK;
1225 }
1226
1227 /**
1228  * Get the URI of the resource specified by handle.
1229  *
1230  * @param handle - handle of resource
1231  * @return
1232  *    URI string - if resource found
1233  *    NULL - resource not found
1234  */
1235 const char *OCGetResourceUri(OCResourceHandle handle) {
1236     OCResource *resource;
1237     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
1238
1239     resource = findResource((OCResource *) handle);
1240     if (resource) {
1241         return resource->uri;
1242     }
1243     return (const char *) NULL;
1244 }
1245
1246 /**
1247  * Get the properties of the resource specified by handle.
1248  * NOTE: that after a resource is created, the OC_ACTIVE property is set
1249  * for the resource by the stack.
1250  *
1251  * @param handle - handle of resource
1252  * @return
1253  *    property bitmap - if resource found
1254  *    NULL - resource not found
1255  */
1256 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
1257     OCResource *resource;
1258     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
1259
1260     resource = findResource((OCResource *) handle);
1261     if (resource) {
1262         return resource->resourceProperties;
1263     }
1264     return 0;
1265 }
1266
1267 /**
1268  * Get the number of resource types of the resource.
1269  *
1270  * @param handle - handle of resource
1271  * @param numResourceTypes - pointer to count variable
1272  *
1273  * @return
1274  *     OC_STACK_OK    - no errors
1275  *     OC_STACK_ERROR - stack process error
1276  */
1277 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
1278         uint8_t *numResourceTypes) {
1279     OCResource *resource;
1280     OCResourceType *pointer;
1281
1282     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
1283     VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
1284     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1285
1286     *numResourceTypes = 0;
1287
1288     resource = findResource((OCResource *) handle);
1289     if (resource) {
1290         pointer = resource->rsrcType;
1291         while (pointer) {
1292             *numResourceTypes = *numResourceTypes + 1;
1293             pointer = pointer->next;
1294         }
1295     }
1296     return OC_STACK_OK;
1297 }
1298
1299 /**
1300  * Get name of resource type of the resource.
1301  *
1302  * @param handle - handle of resource
1303  * @param index - index of resource, 0 to Count - 1
1304  *
1305  * @return
1306  *    resource type name - if resource found
1307  *    NULL - resource not found
1308  */
1309 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
1310     OCResourceType *resourceType;
1311
1312     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
1313
1314     resourceType = findResourceTypeAtIndex(handle, index);
1315     if (resourceType) {
1316         return resourceType->resourcetypename;
1317     }
1318     return (const char *) NULL;
1319 }
1320
1321
1322
1323 /**
1324  * Get the number of resource interfaces of the resource.
1325  *
1326  * @param handle - handle of resource
1327  * @param numResources - pointer to count variable
1328  *
1329  * @return
1330  *     OC_STACK_OK    - no errors
1331  *     OC_STACK_ERROR - stack process error
1332  */
1333 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
1334         uint8_t *numResourceInterfaces) {
1335     OCResourceInterface *pointer;
1336     OCResource *resource;
1337
1338     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
1339
1340     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1341     VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
1342
1343     *numResourceInterfaces = 0;
1344     resource = findResource((OCResource *) handle);
1345     if (resource) {
1346         pointer = resource->rsrcInterface;
1347         while (pointer) {
1348             *numResourceInterfaces = *numResourceInterfaces + 1;
1349             pointer = pointer->next;
1350         }
1351     }
1352     return OC_STACK_OK;
1353 }
1354
1355 /**
1356  * Get name of resource interface of the resource.
1357  *
1358  * @param handle - handle of resource
1359  * @param index - index of resource, 0 to Count - 1
1360  *
1361  * @return
1362  *    resource interface name - if resource found
1363  *    NULL - resource not found
1364  */
1365 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
1366     OCResourceInterface *resourceInterface;
1367
1368     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
1369
1370     resourceInterface = findResourceInterfaceAtIndex(handle, index);
1371     if (resourceInterface) {
1372         return resourceInterface->name;
1373     }
1374     return (const char *) NULL;
1375 }
1376
1377 /**
1378  * Get resource handle from the collection resource by index.
1379  *
1380  * @param collectionHandle - handle of collection resource
1381  * @param index - index of contained resource, 0 to Count - 1
1382  *
1383  * @return
1384  *    handle to resource - if resource found
1385  *    NULL - resource not found
1386  */
1387 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
1388         uint8_t index) {
1389     OCResource *resource;
1390
1391     OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
1392
1393     if (index >= MAX_CONTAINED_RESOURCES) {
1394         return NULL;
1395     }
1396
1397     resource = findResource((OCResource *) collectionHandle);
1398     if (!resource) {
1399         return NULL;
1400     }
1401
1402     return resource->rsrcResources[index];
1403 }
1404
1405 /**
1406  * Bind an entity handler to the resource.
1407  *
1408  * @param handle - handle to the resource that the contained resource is to be bound
1409  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1410  * @return
1411  *     OC_STACK_OK    - no errors
1412  *     OC_STACK_ERROR - stack process error
1413  */
1414 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
1415         OCEntityHandler entityHandler) {
1416     OCResource *resource;
1417
1418     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
1419
1420     // Validate parameters
1421     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1422     //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
1423
1424     // Use the handle to find the resource in the resource linked list
1425     resource = findResource((OCResource *)handle);
1426     if (!resource) {
1427         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1428         return OC_STACK_ERROR;
1429     }
1430
1431     // Bind the handler
1432     resource->entityHandler = entityHandler;
1433
1434     #ifdef WITH_PRESENCE
1435     if(presenceResource.handle)
1436     {
1437         ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1438         OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1439     }
1440     #endif
1441
1442     return OC_STACK_OK;
1443 }
1444
1445 /**
1446  * Get the entity handler for a resource.
1447  *
1448  * @param handle - handle of resource
1449  *
1450  * @return
1451  *    entity handler - if resource found
1452  *    NULL - resource not found
1453  */
1454 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
1455     OCResource *resource;
1456
1457     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
1458
1459     // Use the handle to find the resource in the resource linked list
1460     resource = findResource((OCResource *)handle);
1461     if (!resource) {
1462         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1463         return NULL;
1464     }
1465
1466     // Bind the handler
1467     return resource->entityHandler;
1468 }
1469
1470 void incrementSequenceNumber(OCResource * resPtr)
1471 {
1472     // Increment the sequence number
1473     resPtr->sequenceNum += 1;
1474     if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
1475     {
1476         resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
1477     }
1478     return;
1479 }
1480
1481 /**
1482  * Notify observers that an observed value has changed.
1483  *
1484  * @param handle - handle of resource
1485  *
1486  * @return
1487  *     OC_STACK_OK    - no errors
1488  *     OC_STACK_NO_RESOURCE - invalid resource handle
1489  *     OC_STACK_NO_OBSERVERS - no more observers intrested in resource
1490  */
1491 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
1492     OCResource *resPtr = NULL;
1493     OCStackResult result;
1494     OCMethod method = OC_REST_NOMETHOD;
1495     uint32_t maxAge = 0;
1496
1497     OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
1498
1499     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1500
1501     // Verify that the resource exists
1502     resPtr = findResource ((OCResource *) handle);
1503     if (NULL == resPtr || myStackMode == OC_CLIENT)
1504     {
1505         return OC_STACK_NO_RESOURCE;
1506     } else {
1507         #ifdef WITH_PRESENCE
1508         if(strcmp(resPtr->uri, OC_PRESENCE_URI))
1509         {
1510         #endif
1511             //only increment in the case of regular observing (not presence)
1512             incrementSequenceNumber(resPtr);
1513             method = OC_REST_OBSERVE;
1514             maxAge = 0x2FFFF;
1515         #ifdef WITH_PRESENCE
1516         }
1517         else
1518         {
1519             method = OC_REST_PRESENCE;
1520             if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
1521             {
1522                 maxAge = presenceResource.presenceTTL;
1523             }
1524             else
1525             {
1526                 maxAge = 0;
1527             }
1528
1529         }
1530         #endif
1531         result = SendObserverNotification (method, resPtr, maxAge, qos);
1532         return result;
1533     }
1534 }
1535
1536 OCStackResult
1537 OCNotifyListOfObservers (OCResourceHandle handle,
1538                          OCObservationId  *obsIdList,
1539                          uint8_t          numberOfIds,
1540                          unsigned char    *notificationJSONPayload,
1541                          OCQualityOfService qos)
1542 {
1543     OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
1544
1545     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1546     VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
1547     VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
1548
1549     uint8_t numIds = numberOfIds;
1550     ResourceObserver *observation;
1551     OCResource *resPtr = NULL;
1552     uint32_t maxAge = 0;
1553     unsigned char bufNotify[MAX_RESPONSE_LENGTH] = {0};
1554     unsigned char *currPtr;
1555     uint8_t numSentNotification = 0;
1556
1557     // Verify the notification payload length does not exceed the maximim
1558     // the stack can handle
1559     if ((strlen((char *)notificationJSONPayload) +
1560          OC_JSON_PREFIX_LEN + OC_JSON_SUFFIX_LEN) > MAX_RESPONSE_LENGTH)
1561     {
1562         OC_LOG(INFO, TAG, PCF("Observe notification message length too long"));
1563         return OC_STACK_ERROR;
1564     }
1565
1566     // Verify that the resource exists
1567     resPtr = findResource ((OCResource *) handle);
1568     if (NULL == resPtr || myStackMode == OC_CLIENT)
1569     {
1570         return OC_STACK_NO_RESOURCE;
1571     }
1572     else
1573     {
1574         incrementSequenceNumber(resPtr);
1575         //TODO: we should allow the serve to define thisl
1576         maxAge = 0x2FFFF;
1577     }
1578
1579     while (numIds)
1580     {
1581         OC_LOG_V(INFO, TAG, "Need to notify observation id %d", *obsIdList);
1582         observation = NULL;
1583         observation = GetObserverUsingId (*obsIdList);
1584         if (observation)
1585         {
1586             // Found observation - verify if it matches the resource handle
1587             if (observation->resource == resPtr)
1588             {
1589                 strcpy((char*)bufNotify, OC_JSON_PREFIX);
1590                 currPtr = bufNotify + OC_JSON_PREFIX_LEN;
1591                 memcpy (currPtr, notificationJSONPayload, strlen((char *)notificationJSONPayload));
1592                 currPtr += strlen((char *)notificationJSONPayload);
1593                 strcpy((char*)currPtr, OC_JSON_SUFFIX);
1594
1595                 // send notifications based on the qos of the request
1596                 // The qos passed as a parameter overrides what the client requested
1597                 // If we want the client preference taking high priority add:
1598                 // QoS = resourceObserver->qos;
1599                 if(qos == OC_NA_QOS){
1600                     qos = observation->qos;
1601                 }
1602                 if(qos != OC_HIGH_QOS)
1603                 {
1604                     OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
1605                             observation->lowQosCount);
1606                     if(observation->forceHighQos \
1607                             || observation->lowQosCount >= MAX_OBSERVER_NON_COUNT)
1608                     {
1609                         observation->lowQosCount = 0;
1610                         // at some point we have to to send CON to check on the
1611                         // availability of observer
1612                         OC_LOG(INFO, TAG, PCF("This time we are sending the \
1613                                 notification as High qos"));
1614                         qos = OC_HIGH_QOS;
1615                     }
1616                     else
1617                     {
1618                         observation->lowQosCount++;
1619                     }
1620                 }
1621                 OCSendCoAPNotification (observation->resUri, observation->addr,
1622                                         qos, &(observation->token),
1623                                         bufNotify, resPtr, maxAge);
1624                 numSentNotification++;
1625             }
1626         }
1627         obsIdList++;
1628         numIds--;
1629     }
1630     if(numSentNotification == numberOfIds)
1631     {
1632         return OC_STACK_OK;
1633     }
1634     else if(numSentNotification == 0)
1635     {
1636         return OC_STACK_NO_OBSERVERS;
1637     }
1638     else
1639     {
1640         //TODO: we need to signal that not every one in the
1641         // list got an update, should we also indicate who did not receive on?
1642         return OC_STACK_OK;
1643     }
1644 }
1645
1646 //-----------------------------------------------------------------------------
1647 // Private internal function definitions
1648 //-----------------------------------------------------------------------------
1649 /**
1650  * Generate handle of OCDoResource invocation for callback management.
1651  */
1652 static OCDoHandle GenerateInvocationHandle()
1653 {
1654     OCDoHandle handle = NULL;
1655     // Generate token here, it will be deleted when the transaction is deleted
1656     handle = (OCDoHandle) malloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1657     if (handle)
1658     {
1659         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1660     }
1661
1662     return handle;
1663 }
1664 #ifdef WITH_PRESENCE
1665 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
1666         OCResourceProperty resourceProperties, uint8_t enable)
1667 {
1668     if (resourceProperties
1669             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
1670         OC_LOG(ERROR, TAG, PCF("Invalid property"));
1671         return OC_STACK_INVALID_PARAM;
1672     }
1673     if(!enable)
1674     {
1675         *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
1676     }
1677     else
1678     {
1679         *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
1680     }
1681     return OC_STACK_OK;
1682 }
1683 #endif
1684
1685 /**
1686  * Initialize resource data structures, variables, etc.
1687  */
1688 OCStackResult initResources() {
1689     OCStackResult result = OC_STACK_OK;
1690     // Init application resource vars
1691     headResource = NULL;
1692     // Init Virtual Resources
1693     #ifdef WITH_PRESENCE
1694     presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
1695     //presenceResource.token = OCGenerateCoAPToken();
1696     result = OCCreateResource(&presenceResource.handle,
1697             "core.presence",
1698             "core.r",
1699             OC_PRESENCE_URI,
1700             NULL,
1701             OC_OBSERVABLE);
1702     //make resource inactive
1703     result = OCChangeResourceProperty(
1704             &(((OCResource *) presenceResource.handle)->resourceProperties),
1705             OC_ACTIVE, 0);
1706     #endif
1707     return result;
1708 }
1709
1710 /**
1711  * Add a resource to the end of the linked list of resources.
1712  *
1713  * @param resource - resource to be added
1714  */
1715 void insertResource(OCResource *resource) {
1716     OCResource *pointer;
1717
1718     if (!headResource) {
1719         headResource = resource;
1720     } else {
1721         pointer = headResource;
1722
1723         while (pointer->next) {
1724             pointer = pointer->next;
1725         }
1726         pointer->next = resource;
1727     }
1728     resource->next = NULL;
1729 }
1730
1731 /**
1732  * Find a resource in the linked list of resources.
1733  *
1734  * @param resource - resource to be found
1735  * @return
1736  *     NULL                - resource not found
1737  *     pointer to resource - pointer to resource that was found in the linked list
1738  */
1739 OCResource *findResource(OCResource *resource) {
1740     OCResource *pointer = headResource;
1741
1742     while (pointer) {
1743         if (pointer == resource) {
1744             return resource;
1745         }
1746         pointer = pointer->next;
1747     }
1748     return NULL;
1749 }
1750
1751 void deleteAllResources()
1752 {
1753     OCResource *pointer = headResource;
1754     OCResource *temp;
1755
1756     while (pointer)
1757     {
1758         temp = pointer->next;
1759         deleteResource(pointer);
1760         pointer = temp;
1761     }
1762 }
1763
1764 /**
1765  * Delete the resource from the linked list.
1766  *
1767  * @param resource - resource to be deleted
1768  * @return
1769  *    0 - error
1770  *    1 - success
1771  */
1772 int deleteResource(OCResource *resource) {
1773     OCResource *prev = NULL;
1774     OCResource *temp;
1775
1776     temp = headResource;
1777     while (temp) {
1778         if (temp == resource) {
1779             // Invalidate all Resource Properties.
1780             resource->resourceProperties = (OCResourceProperty) 0;
1781             OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
1782
1783             #ifdef WITH_PRESENCE
1784             if(presenceResource.handle)
1785             {
1786                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1787                 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1788             }
1789             #endif
1790
1791             if (temp == headResource) {
1792                 headResource = temp->next;
1793             } else {
1794                 prev->next = temp->next;
1795             }
1796
1797             deleteResourceElements(temp);
1798             OCFree(temp);
1799             return 1;
1800         } else {
1801             prev = temp;
1802             temp = temp->next;
1803         }
1804     }
1805
1806     return 0;
1807 }
1808
1809 /**
1810  * Delete all of the dynamically allocated elements that were created for the resource.
1811  *
1812  * @param resource - specified resource
1813  */
1814 void deleteResourceElements(OCResource *resource) {
1815     if (!resource) {
1816         return;
1817     }
1818
1819     // remove URI
1820     OCFree(resource->uri);
1821
1822     // Delete resourcetype linked list
1823     deleteResourceType(resource->rsrcType);
1824
1825     // Delete resourceinterface linked list
1826     deleteResourceInterface(resource->rsrcInterface);
1827 }
1828
1829 /**
1830  * Delete all of the dynamically allocated elements that were created for the resource type.
1831  *
1832  * @param resourceType - specified resource type
1833  */
1834 void deleteResourceType(OCResourceType *resourceType) {
1835     OCResourceType *pointer = resourceType;
1836     OCResourceType *next;
1837
1838     while (pointer) {
1839         next = pointer->next;
1840         OCFree(pointer->resourcetypename);
1841         OCFree(pointer);
1842         pointer = next;
1843     }
1844 }
1845
1846 /**
1847  * Delete all of the dynamically allocated elements that were created for the resource interface.
1848  *
1849  * @param resourceInterface - specified resource interface
1850  */
1851 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
1852     OCResourceInterface *pointer = resourceInterface;
1853     OCResourceInterface *next;
1854
1855     while (pointer) {
1856         next = pointer->next;
1857         OCFree(pointer->name);
1858         OCFree(pointer);
1859         pointer = next;
1860     }
1861 }
1862
1863 /**
1864  * Insert a resource type into a resource's resource type linked list.
1865  *
1866  * @param resource - resource where resource type is to be inserted
1867  * @param resourceType - resource type to be inserted
1868  */
1869 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
1870     OCResourceType *pointer;
1871
1872     if (!resource->rsrcType) {
1873         resource->rsrcType = resourceType;
1874     } else {
1875         pointer = resource->rsrcType;
1876         while (pointer->next) {
1877             pointer = pointer->next;
1878         }
1879         pointer->next = resourceType;
1880     }
1881     resourceType->next = NULL;
1882 }
1883
1884 /**
1885  * Get a resource type at the specified index within a resource.
1886  *
1887  * @param handle - handle of resource
1888  * @param index - index of resource type
1889  *
1890  * @return
1891  *    resourcetype - if found
1892  *    NULL - not found
1893  */
1894 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
1895     OCResource *resource;
1896     OCResourceType *pointer;
1897     uint8_t i;
1898
1899     // Find the specified resource
1900     resource = findResource((OCResource *) handle);
1901     if (!resource) {
1902         return NULL;
1903     }
1904
1905     // Make sure a resource has a resourcetype
1906     if (!resource->rsrcType) {
1907         return NULL;
1908     }
1909
1910     // Iterate through the list
1911     pointer = resource->rsrcType;
1912     i = 0;
1913     while ((i < index) && pointer) {
1914         i++;
1915         pointer = pointer->next;
1916     }
1917     return pointer;
1918 }
1919
1920 /**
1921  * Insert a resource interface into a resource's resource interface linked list.
1922  *
1923  * @param resource - resource where resource interface is to be inserted
1924  * @param resourceInterface - resource interface to be inserted
1925  */
1926 void insertResourceInterface(OCResource *resource,
1927         OCResourceInterface *resourceInterface) {
1928     OCResourceInterface *pointer;
1929
1930     if (!resource->rsrcInterface) {
1931         resource->rsrcInterface = resourceInterface;
1932     } else {
1933         pointer = resource->rsrcInterface;
1934         while (pointer->next) {
1935             pointer = pointer->next;
1936         }
1937         pointer->next = resourceInterface;
1938     }
1939     resourceInterface->next = NULL;
1940 }
1941
1942 /**
1943  * Get a resource interface at the specified index within a resource.
1944  *
1945  * @param handle - handle of resource
1946  * @param index - index of resource interface
1947  *
1948  * @return
1949  *    resourceinterface - if found
1950  *    NULL - not found
1951  */
1952 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
1953         uint8_t index) {
1954     OCResource *resource;
1955     OCResourceInterface *pointer;
1956     uint8_t i = 0;
1957
1958     // Find the specified resource
1959     resource = findResource((OCResource *) handle);
1960     if (!resource) {
1961         return NULL;
1962     }
1963
1964     // Make sure a resource has a resourceinterface
1965     if (!resource->rsrcInterface) {
1966         return NULL;
1967     }
1968
1969     // Iterate through the list
1970     pointer = resource->rsrcInterface;
1971
1972     while ((i < index) && pointer) {
1973         i++;
1974         pointer = pointer->next;
1975     }
1976     return pointer;
1977 }
1978
1979