f34a492d67f8e181180fe721005bc0ae6f2f20a0
[platform/upstream/iotivity.git] / csdk / stack / src / ocstack.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Corporation 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 "ocserverrequest.h"
28 #include "ocresource.h"
29 #include "occlientcb.h"
30 #include "ocobserve.h"
31 #include "ocrandom.h"
32 #include "debug.h"
33 #include "occoap.h"
34
35 //-----------------------------------------------------------------------------
36 // Typedefs
37 //-----------------------------------------------------------------------------
38 typedef enum {
39     OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED
40 } OCStackState;
41
42 //-----------------------------------------------------------------------------
43 // Private variables
44 //-----------------------------------------------------------------------------
45 static OCStackState stackState = OC_STACK_UNINITIALIZED;
46 OCResource *headResource = NULL;
47
48 //-----------------------------------------------------------------------------
49 // Macros
50 //-----------------------------------------------------------------------------
51 #define TAG  PCF("OCStack")
52 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
53              TAG, PCF(#arg " is NULL")); return (retVal); } }
54
55 //-----------------------------------------------------------------------------
56 // Internal API function
57 //-----------------------------------------------------------------------------
58
59 //This function will be called back by occoap layer when a request is received
60 OCStackResult HandleStackRequests(OCRequest * request) {
61     OC_LOG(INFO, TAG, "Entering OCStackHandleReceiveRequest (OCStack Layer)");
62
63     char *filterValue;
64     uint8_t filterOn;
65     OCStackResult result;
66
67     VERIFY_NON_NULL(request, ERROR, OC_STACK_ERROR);
68     VERIFY_NON_NULL(request->entityHandlerRequest, ERROR, OC_STACK_ERROR);
69
70     if (IsVirtualResource((const char*)request->resourceUrl))
71     {
72         result = ValidateUrlQuery(request->resourceUrl,
73                                   request->entityHandlerRequest->query, &filterOn,
74                                   &filterValue);
75
76         if (result == OC_STACK_OK)
77         {
78             result = ProcessResourceDiscoverReq(request->entityHandlerRequest,
79                                                 filterOn,
80                                                 filterValue);
81         }
82     }
83     else
84     {
85         OCResource* resource = FindResourceByUri((const char*)request->resourceUrl);
86         if (resource)
87         {
88             request->entityHandlerRequest->resource = (OCResourceHandle)resource;
89             result = resource->entityHandler(OC_REQUEST_FLAG, request->entityHandlerRequest);
90         }
91         else
92         {
93             OC_LOG(INFO, TAG, "Resource Not found");
94             result = OC_STACK_NO_RESOURCE;
95         }
96         if (request->observe != NULL)
97         {
98             result = ProcessObserveRequest (resource, request);
99         }
100     }
101
102     return result;
103 }
104
105 //This function will be called back by occoap layer when a response is received
106 void HandleStackResponses(OCResponse * response) {
107     OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
108     OC_LOG(INFO, TAG, "Entering HandleStackResponses (OCStack Layer)");
109
110     if (response->cbNode) {
111         OC_LOG(INFO, TAG, PCF("Calling into application address space"));
112         result = response->cbNode->callBack(response->cbNode->context, response->cbNode->handle, response->clientResponse);
113         if (result == OC_STACK_DELETE_TRANSACTION) {
114             FindAndDeleteClientCB(response->cbNode);
115         }
116     }
117 }
118
119 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr) {
120     size_t index = 0;
121     unsigned char *itr, *coap;
122     uint8_t dotCount = 0;
123
124     /* search for scheme */
125     itr = ipAddrStr;
126     if (!isdigit((unsigned char) *ipAddrStr)) {
127         coap = (unsigned char *) OC_COAP_SCHEME;
128         while (*coap && tolower(*itr) == *coap) {
129             coap++;
130             itr++;
131         }
132     }
133     ipAddrStr = itr;
134
135     while (*ipAddrStr) {
136         if (isdigit((unsigned char) *ipAddrStr)) {
137             ipAddr[index] *= 10;
138             ipAddr[index] += *ipAddrStr - '0';
139         } else if ((unsigned char) *ipAddrStr == '.') {
140             index++;
141             dotCount++;
142         } else {
143             break;
144         }
145         ipAddrStr++;
146     }
147
148     if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
149             && dotCount == 3) {
150         return 1;
151     } else {
152         return 0;
153     }
154 }
155 //-----------------------------------------------------------------------------
156 // Private internal function prototypes
157 //-----------------------------------------------------------------------------
158
159 static OCDoHandle GenerateInvocationHandle();
160 static void initResources();
161 static void insertResource(OCResource *resource);
162 static OCResource *findResource(OCResource *resource);
163 static void insertResourceType(OCResource *resource,
164         OCResourceType *resourceType);
165 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
166         uint8_t index);
167 static void insertResourceInterface(OCResource *resource,
168         OCResourceInterface *resourceInterface);
169 static OCResourceInterface *findResourceInterfaceAtIndex(
170         OCResourceHandle handle, uint8_t index);
171 static void deleteResourceType(OCResourceType *resourceType);
172 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
173 static void deleteResourceElements(OCResource *resource);
174 static int deleteResource(OCResource *resource);
175 static void deleteAllResources();
176
177 //-----------------------------------------------------------------------------
178 // Default resource entity handler function
179 //-----------------------------------------------------------------------------
180 void defaultResourceEHandler(OCEntityHandlerFlag flag,
181         OCEntityHandlerRequest * request) {
182     TODO ("Implement me!!!!");
183     // TODO:  remove silence unused param warnings
184     (void) flag;
185     (void) request;
186 }
187
188 //-----------------------------------------------------------------------------
189 // Public APIs
190 //-----------------------------------------------------------------------------
191
192 /**
193  * Initialize the OC Stack.  Must be called prior to starting the stack.
194  *
195  * @param ipAddr
196  *     IP Address of host device
197  * @param port
198  *     Port of host device
199  * @param mode
200  *     Host device is client, server, or client-server
201  *
202  * @return
203  *     OC_STACK_OK    - no errors
204  *     OC_STACK_ERROR - stack init error
205  */
206 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode) {
207     OC_LOG(INFO, TAG, PCF("Entering OCInit"));
208
209     if (ipAddr) {
210         OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
211     }
212
213     switch (mode) {
214     case OC_CLIENT:
215         OC_LOG(INFO, TAG, PCF("Client mode"));
216         break;
217     case OC_SERVER:
218         OC_LOG(INFO, TAG, PCF("Server mode"));
219         break;
220     case OC_CLIENT_SERVER:
221         OC_LOG(INFO, TAG, PCF("Client-server mode"));
222         break;
223     default:
224         OC_LOG(ERROR, TAG, PCF("Invalid mode"));
225         return OC_STACK_ERROR;
226         break;
227     }
228
229     // Initialize resource
230     initResources();
231
232     // Make call to OCCoAP layer
233     if (OCInitCoAP(ipAddr, (uint16_t) port, mode) == 0) {
234         stackState = OC_STACK_INITIALIZED;
235         return OC_STACK_OK;
236     }
237
238     OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
239     return OC_STACK_ERROR;
240 }
241
242 /**
243  * Stop the OC stack.  Use for a controlled shutdown.
244  * @return
245  *     OC_STACK_OK    - no errors
246  *     OC_STACK_ERROR - stack not initialized
247  */
248 OCStackResult OCStop() {
249     OCStackResult result = OC_STACK_ERROR;
250
251     OC_LOG(INFO, TAG, PCF("Entering OCStop"));
252
253     if (stackState != OC_STACK_INITIALIZED) {
254         OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
255         return OC_STACK_ERROR;
256     }
257
258     // Make call to OCCoAP layer
259     if (OCStopCoAP() == 0) {
260         // Remove all observers
261         DeleteObserverList();
262         // Remove all the client callbacks
263         DeleteClientCBList();
264         stackState = OC_STACK_UNINITIALIZED;
265         result = OC_STACK_OK;
266     } else {
267         result = OC_STACK_ERROR;
268     }
269
270     // Free memory dynamically allocated for resources
271     deleteAllResources();
272
273     if (result != OC_STACK_OK) {
274         OC_LOG(ERROR, TAG, PCF("Stack stop error"));
275     }
276
277     return result;
278 }
279
280 /**
281  * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
282  *
283  * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
284  * @param method             - @ref OCMethod to perform on the resource
285  * @param requiredUri        - URI of the resource to interact with
286  * @param referenceUri       - URI of the reference resource
287  * @param request            - JSON encoded request
288  * @param qos                - quality of service
289  * @param cbData             - struct that contains asynchronous callback function that is invoked
290  *                             by the stack when discovery or resource interaction is complete
291  *
292  * @return
293  *     OC_STACK_OK               - no errors
294  *     OC_STACK_INVALID_CALLBACK - invalid callback function pointer
295  *     OC_STACK_INVALID_METHOD   - invalid resource method
296  *     OC_STACK_INVALID_URI      - invalid required or reference URI
297  */
298
299 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
300                            const char *referenceUri, const char *request,
301                            OCQualityOfService qos, OCCallbackData *cbData)
302 {
303     OCStackResult result = OC_STACK_ERROR;
304     OCCoAPToken * token = NULL;
305     ClientCB *clientCB = NULL;
306     (void) referenceUri;
307
308     OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
309
310     // Validate input parameters
311     VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
312     VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
313
314     TODO ("Need to form the final query by concatenating require and reference URI's");
315     VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
316
317     switch (method)
318     {
319         case OC_REST_GET:
320         case OC_REST_PUT:
321             break;
322         case OC_REST_OBSERVE:
323         case OC_REST_OBSERVE_ALL:
324             break;
325         default:
326             return OC_STACK_INVALID_METHOD;
327     }
328
329     *handle = GenerateInvocationHandle();
330     VERIFY_NON_NULL(*handle, FATAL, OC_STACK_ERROR);
331     token = OCGenerateCoAPToken();
332     if (!token)
333     {
334         goto exit;
335     }
336     if((result = AddClientCB(&clientCB, cbData, token, *handle, method)) != OC_STACK_OK)
337     {
338         goto exit;
339     }
340
341     // Make call to OCCoAP layer
342     result = OCDoCoAPResource(method, qos, token, requiredUri, request);
343
344 exit:
345
346     if (result != OC_STACK_OK)
347     {
348         OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
349         if (clientCB)
350         {
351             DeleteClientCB(clientCB);
352         }
353         else
354         {
355             OCFree(token);
356             OCFree(*handle);
357         }
358     }
359     return result;
360 }
361
362 /**
363  * Cancel a request associated with a specific @ref OCDoResource invocation.
364  *
365  * @param handle - Used to identify a specific OCDoResource invocation.
366  *
367  * @return
368  *     OC_STACK_OK               - No errors; Success
369  *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
370  */
371 OCStackResult OCCancel(OCDoHandle handle) {
372     /*
373      * This ftn can be implemented one of two ways:
374      *
375      * 1. When observe is unobserved..Remove the callback associated on client side.
376      *      When the next notification comes in from server, reply with RST message to server.
377      *
378      * 2. When OCCancel is called, and it is associated with an observe request
379      *      (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
380      *      Send Observe request to server with observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
381      *      Remove the callback associated on client side.
382      *
383      *      Number 1 is implemented here.
384      */
385     if(!handle) {
386         return OC_STACK_INVALID_PARAM;
387     }
388
389     OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
390
391     ClientCB *clientCB = GetClientCB(NULL, handle);
392
393     if(clientCB) {
394         switch (clientCB->method)
395         {
396             case OC_REST_OBSERVE:
397             case OC_REST_OBSERVE_ALL:
398                 // Make call to OCCoAP layer
399                     DeleteClientCB(clientCB);
400                 break;
401             default:
402                 return OC_STACK_INVALID_METHOD;
403         }
404     }
405     return OC_STACK_OK;
406 }
407
408 /**
409  * Called in main loop of OC client or server.  Allows low-level processing of
410  * stack services.
411  *
412  * @return
413  *     OC_STACK_OK    - no errors
414  *     OC_STACK_ERROR - stack process error
415  */
416 OCStackResult OCProcess() {
417
418     OC_LOG(INFO, TAG, PCF("Entering OCProcess"));
419     OCProcessCoAP();
420
421     return OC_STACK_OK;
422 }
423 /**
424  * Create a resource
425  *
426  * @param handle - pointer to handle to newly created resource.  Set by ocstack.  Used to refer to resource
427  * @param resourceTypeName - name of resource type.  Example: "core.led"
428  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
429  * @param uri - URI of the resource.  Example:  "/a/led"
430  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
431  *                        NULL for default entity handler
432  * @param resourceProperties - properties supported by resource.  Example: OC_DISCOVERABLE|OC_OBSERVABLE
433  *
434  * @return
435  *     OC_STACK_OK    - no errors
436  *     OC_STACK_ERROR - stack process error
437  */
438 OCStackResult OCCreateResource(OCResourceHandle *handle,
439         const char *resourceTypeName,
440         const char *resourceInterfaceName,
441         const char *uri, OCEntityHandler entityHandler,
442         uint8_t resourceProperties) {
443
444     OCResource *pointer = NULL;
445     char *str = NULL;
446     size_t size;
447     OCStackResult result = OC_STACK_ERROR;
448
449     OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
450
451     // Validate parameters
452     // Is it presented during resource discovery?
453     if (!handle || !resourceTypeName || !resourceInterfaceName || !uri) {
454         OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
455         return OC_STACK_INVALID_PARAM;
456     }
457
458     // Make sure resourceProperties bitmask has allowed properties specified
459     if (resourceProperties
460             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
461         OC_LOG(ERROR, TAG, PCF("Invalid property"));
462         return OC_STACK_INVALID_PARAM;
463     }
464
465     // If the headResource is NULL, then no resources have been created...
466     pointer = headResource;
467     if (pointer) {
468         // At least one resources is in the resource list, so we need to search for
469         // repeated URLs, which are not allowed.  If a repeat is found, exit with an error
470         while (pointer) {
471             if (strcmp(uri, pointer->uri) == 0) {
472                 OC_LOG(ERROR, TAG, PCF("URI already in use"));
473                 return OC_STACK_INVALID_PARAM;
474             }
475             pointer = pointer->next;
476         }
477     }
478     // Create the pointer and insert it into the resource list
479     pointer = (OCResource *) OCMalloc(sizeof(OCResource));
480     if (!pointer) {
481         goto exit;
482     }
483     memset(pointer, 0, sizeof(OCResource));
484
485     insertResource(pointer);
486
487     // Set the uri
488     size = strlen(uri) + 1;
489     str = (char *) OCMalloc(size);
490     if (!str) {
491         goto exit;
492     }
493     strncpy(str, uri, size);
494     pointer->uri = str;
495
496     // Set properties.  Set OC_ACTIVE
497     pointer->resourceProperties = (OCResourceProperty) (resourceProperties
498             | OC_ACTIVE);
499
500     // Add the resourcetype to the resource
501     result = OCBindResourceTypeToResource((OCResourceHandle) pointer,
502             resourceTypeName);
503     if (result != OC_STACK_OK) {
504         OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
505         goto exit;
506     }
507
508     // Add the resourceinterface to the resource
509     result = OCBindResourceInterfaceToResource((OCResourceHandle) pointer,
510             resourceInterfaceName);
511     if (result != OC_STACK_OK) {
512         OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
513         goto exit;
514     }
515
516     // If an entity handler has been passed, attach it to the newly created
517     // resource.  Otherwise, set the default entity handler.
518     if (entityHandler)
519     {
520         pointer->entityHandler = entityHandler;
521     }
522     else
523     {
524         pointer->entityHandler = defaultResourceEHandler;
525     }
526
527     *handle = pointer;
528     result = OC_STACK_OK;
529
530 exit:
531     if (result != OC_STACK_OK)
532     {
533         // Deep delete of resource and other dynamic elements that it contains
534         deleteResource(pointer);
535         OCFree(str);
536     }
537     return result;
538 }
539
540 /**
541  * Add a resource to a collection resource.
542  *
543  * @param collectionHandle - handle to the collection resource
544  * @param resourceHandle - handle to resource to be added to the collection resource
545  *
546  * @return
547  *     OC_STACK_OK    - no errors
548  *     OC_STACK_ERROR - stack process error
549  *     OC_STACK_INVALID_PARAM - invalid collectionhandle
550  */
551 OCStackResult OCBindResource(
552         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
553     OCResource *resource;
554     uint8_t i;
555
556     OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
557
558     // Validate parameters
559     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
560     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
561     // Container cannot contain itself
562     if (collectionHandle == resourceHandle) {
563         OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
564         return OC_STACK_INVALID_PARAM;
565     }
566
567     // Use the handle to find the resource in the resource linked list
568     resource = findResource((OCResource *) collectionHandle);
569     if (!resource) {
570         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
571         return OC_STACK_INVALID_PARAM;
572     }
573
574     // Look for an open slot to add add the child resource.
575     // If found, add it and return success
576     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
577         if (!resource->rsrcResources[i]) {
578             resource->rsrcResources[i] = (OCResourceHandle) resourceHandle;
579             OC_LOG(INFO, TAG, PCF("resource bound"));
580             return OC_STACK_OK;
581         }
582     }
583
584     // Unable to add resourceHandle, so return error
585     return OC_STACK_ERROR;
586 }
587
588 /**
589  * Remove a resource from a collection resource.
590  *
591  * @param collectionHandle - handle to the collection resource
592  * @param resourceHandle - handle to resource to be added to the collection resource
593  *
594  * @return
595  *     OC_STACK_OK    - no errors
596  *     OC_STACK_ERROR - stack process error
597  *     OC_STACK_INVALID_PARAM - invalid collectionHandle
598  */
599 OCStackResult OCUnBindResource(
600         OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
601     OCResource *resource;
602     uint8_t i;
603
604     OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
605
606     // Validate parameters
607     VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
608     VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
609     // Container cannot contain itself
610     if (collectionHandle == resourceHandle) {
611         OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
612         return OC_STACK_INVALID_PARAM;
613     }
614
615     // Use the handle to find the resource in the resource linked list
616     resource = findResource((OCResource *) collectionHandle);
617     if (!resource) {
618         OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
619         return OC_STACK_INVALID_PARAM;
620     }
621
622     // Look for an open slot to add add the child resource.
623     // If found, add it and return success
624     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
625         if (resourceHandle == resource->rsrcResources[i]) {
626             resource->rsrcResources[i] = (OCResourceHandle) 0;
627             OC_LOG(INFO, TAG, PCF("resource unbound"));
628             return OC_STACK_OK;
629         }
630     }
631
632     OC_LOG(INFO, TAG, PCF("resource not found in collection"));
633
634     // Unable to add resourceHandle, so return error
635     return OC_STACK_ERROR;
636 }
637
638
639 /**
640  * Bind a resourcetype to a resource.
641  *
642  * @param handle - handle to the resource
643  * @param resourceTypeName - name of resource type.  Example: "core.led"
644  *
645  * @return
646  *     OC_STACK_OK    - no errors
647  *     OC_STACK_ERROR - stack process error
648  */
649 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
650         const char *resourceTypeName) {
651
652     OCResourceType *pointer = NULL;
653     char *str = NULL;
654     size_t size;
655     OCResource *resource;
656     OCStackResult result = OC_STACK_ERROR;
657
658     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceTypeToResource"));
659
660     // Validate parameters
661     VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
662     // TODO:  Does resource attribute resentation really have to be maintained in stack?
663     // Is it presented during resource discovery?
664
665     // Make sure resource exists
666     resource = findResource((OCResource *) handle);
667     if (!resource) {
668         OC_LOG(ERROR, TAG, PCF("Resource not found"));
669         return OC_STACK_ERROR;
670     }
671
672     TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
673
674     // Create the resourcetype and insert it into the resource list
675     pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
676     if (!pointer) {
677         goto exit;
678     }
679     memset(pointer, 0, sizeof(OCResourceType));
680
681     // Set the resourceTypeName
682     size = strlen(resourceTypeName) + 1;
683     str = (char *) OCMalloc(size);
684     if (!str) {
685         goto exit;
686     }
687     strncpy(str, resourceTypeName, size);
688     pointer->resourcetypename = str;
689
690    // Bind the resourcetype to the resource
691     insertResourceType(resource, pointer);
692
693     result = OC_STACK_OK;
694
695     exit: if (result != OC_STACK_OK) {
696         OCFree(pointer);
697         OCFree(str);
698     }
699     return result;
700 }
701
702 /**
703  * Bind a resourceinterface to a resource.
704  *
705  * @param handle - handle to the resource
706  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
707  *
708  * @return
709  *     OC_STACK_OK    - no errors
710  *     OC_STACK_ERROR - stack process error
711  */
712 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
713         const char *resourceInterfaceName) {
714
715     OCResourceInterface *pointer = NULL;
716     char *str = NULL;
717     size_t size;
718     OCResource *resource;
719     OCStackResult result = OC_STACK_ERROR;
720
721     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceInterfaceToResource"));
722
723     // Validate parameters
724     VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
725
726     // Make sure resource exists
727     resource = findResource((OCResource *) handle);
728     if (!resource) {
729         OC_LOG(ERROR, TAG, PCF("Resource not found"));
730         return OC_STACK_INVALID_PARAM;
731     }
732
733     TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
734
735     // Create the resourceinterface and insert it into the resource list
736     pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
737     if (!pointer) {
738         goto exit;
739     }
740     memset(pointer, 0, sizeof(OCResourceInterface));
741
742     // Set the resourceinterface name
743     size = strlen(resourceInterfaceName) + 1;
744     str = (char *) OCMalloc(size);
745     if (!str) {
746         goto exit;
747     }
748     strncpy(str, resourceInterfaceName, size);
749     pointer->name = str;
750
751     // Bind the resourceinterface to the resource
752     insertResourceInterface(resource, pointer);
753
754     result = OC_STACK_OK;
755     exit: if (result != OC_STACK_OK) {
756         OCFree(pointer);
757         OCFree(str);
758     }
759     return result;
760 }
761
762 /**
763  * Get the number of resources that have been created in the stack.
764  *
765  * @param numResources - pointer to count variable
766  *
767  * @return
768  *     OC_STACK_OK    - no errors
769  *     OC_STACK_ERROR - stack process error
770
771  */
772 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
773     OCResource *pointer = headResource;
774
775     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
776     VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
777     *numResources = 0;
778     while (pointer) {
779         *numResources = *numResources + 1;
780         pointer = pointer->next;
781     }
782     return OC_STACK_OK;
783 }
784
785 /**
786  * Get a resource handle by index.
787  *
788  * @param index - index of resource, 0 to Count - 1
789  *
790  * @return
791  *    Resource handle - if found
792  *    NULL - if not found
793  */
794 OCResourceHandle OCGetResourceHandle(uint8_t index) {
795     OCResource *pointer = headResource;
796     uint8_t i = 0;
797
798     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
799
800     // Iterate through the list
801     while ((i < index) && pointer) {
802         i++;
803         pointer = pointer->next;
804     }
805     return (OCResourceHandle) pointer;
806 }
807
808 /**
809  * Delete resource specified by handle.  Deletes resource and all resourcetype and resourceinterface
810  * linked lists.
811  *
812  * @param handle - handle of resource to be deleted
813  *
814  * @return
815  *     OC_STACK_OK    - no errors
816  *     OC_STACK_ERROR - stack process error
817  */
818 OCStackResult OCDeleteResource(OCResourceHandle handle) {
819     OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
820
821     if (!handle) {
822         OC_LOG(ERROR, TAG, PCF("Resource not found"));
823         return OC_STACK_INVALID_PARAM;
824     }
825
826     if (deleteResource((OCResource *) handle) == 0) {
827         OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
828         return OC_STACK_ERROR;
829     }
830
831     return OC_STACK_OK;
832 }
833
834 /**
835  * Get the URI of the resource specified by handle.
836  *
837  * @param handle - handle of resource
838  * @return
839  *    URI string - if resource found
840  *    NULL - resource not found
841  */
842 const char *OCGetResourceUri(OCResourceHandle handle) {
843     OCResource *resource;
844     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
845
846     resource = findResource((OCResource *) handle);
847     if (resource) {
848         return resource->uri;
849     }
850     return (const char *) NULL;
851 }
852
853 /**
854  * Get the properties of the resource specified by handle.
855  * NOTE: that after a resource is created, the OC_ACTIVE property is set
856  * for the resource by the stack.
857  *
858  * @param handle - handle of resource
859  * @return
860  *    property bitmap - if resource found
861  *    NULL - resource not found
862  */
863 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
864     OCResource *resource;
865     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
866
867     resource = findResource((OCResource *) handle);
868     if (resource) {
869         return resource->resourceProperties;
870     }
871     return 0;
872 }
873
874 /**
875  * Get the number of resource types of the resource.
876  *
877  * @param handle - handle of resource
878  * @param numResourceTypes - pointer to count variable
879  *
880  * @return
881  *     OC_STACK_OK    - no errors
882  *     OC_STACK_ERROR - stack process error
883  */
884 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
885         uint8_t *numResourceTypes) {
886     OCResource *resource;
887     OCResourceType *pointer;
888
889     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
890     VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
891     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
892
893     *numResourceTypes = 0;
894
895     resource = findResource((OCResource *) handle);
896     if (resource) {
897         pointer = resource->rsrcType;
898         while (pointer) {
899             *numResourceTypes = *numResourceTypes + 1;
900             pointer = pointer->next;
901         }
902     }
903     return OC_STACK_OK;
904 }
905
906 /**
907  * Get name of resource type of the resource.
908  *
909  * @param handle - handle of resource
910  * @param index - index of resource, 0 to Count - 1
911  *
912  * @return
913  *    resource type name - if resource found
914  *    NULL - resource not found
915  */
916 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
917     OCResourceType *resourceType;
918
919     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
920
921     resourceType = findResourceTypeAtIndex(handle, index);
922     if (resourceType) {
923         return resourceType->resourcetypename;
924     }
925     return (const char *) NULL;
926 }
927
928
929
930 /**
931  * Get the number of resource interfaces of the resource.
932  *
933  * @param handle - handle of resource
934  * @param numResources - pointer to count variable
935  *
936  * @return
937  *     OC_STACK_OK    - no errors
938  *     OC_STACK_ERROR - stack process error
939
940  */
941 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
942         uint8_t *numResourceInterfaces) {
943     OCResourceInterface *pointer;
944     OCResource *resource;
945
946     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
947
948     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
949     VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
950
951     *numResourceInterfaces = 0;
952     resource = findResource((OCResource *) handle);
953     if (resource) {
954         pointer = resource->rsrcInterface;
955         while (pointer) {
956             *numResourceInterfaces = *numResourceInterfaces + 1;
957             pointer = pointer->next;
958         }
959     }
960     return OC_STACK_OK;
961 }
962
963 /**
964  * Get name of resource interface of the resource.
965  *
966  * @param handle - handle of resource
967  * @param index - index of resource, 0 to Count - 1
968  *
969  * @return
970  *    resource interface name - if resource found
971  *    NULL - resource not found
972  */
973 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
974     OCResourceInterface *resourceInterface;
975
976     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
977
978     resourceInterface = findResourceInterfaceAtIndex(handle, index);
979     if (resourceInterface) {
980         return resourceInterface->name;
981     }
982     return (const char *) NULL;
983 }
984
985 /**
986  * Get resource handle from the collection resource by index.
987  *
988  * @param collectionHandle - handle of collection resource
989  * @param index - index of contained resource, 0 to Count - 1
990  *
991  * @return
992  *    handle to resource - if resource found
993  *    NULL - resource not found
994  */
995 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
996         uint8_t index) {
997     OCResource *resource;
998
999     OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
1000
1001     if (index >= MAX_CONTAINED_RESOURCES) {
1002         return NULL;
1003     }
1004
1005     resource = findResource((OCResource *) collectionHandle);
1006     if (!resource) {
1007         return NULL;
1008     }
1009
1010     return resource->rsrcResources[index];
1011 }
1012
1013 /**
1014  * Bind an entity handler to the resource.
1015  *
1016  * @param handle - handle to the resource that the contained resource is to be bound
1017  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1018  * @return
1019  *     OC_STACK_OK    - no errors
1020  *     OC_STACK_ERROR - stack process error
1021  */
1022 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
1023         OCEntityHandler entityHandler) {
1024     OCResource *resource;
1025
1026     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
1027
1028     // Validate parameters
1029     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1030     VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
1031
1032     // Use the handle to find the resource in the resource linked list
1033     resource = findResource(handle);
1034     if (!resource) {
1035         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1036         return OC_STACK_ERROR;
1037     }
1038
1039     // Bind the handler
1040     resource->entityHandler = entityHandler;
1041
1042     return OC_STACK_OK;
1043 }
1044
1045 /**
1046  * Get the entity handler for a resource.
1047  *
1048  * @param handle - handle of resource
1049  *
1050  * @return
1051  *    entity handler - if resource found
1052  *    NULL - resource not found
1053  */
1054 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
1055     OCResource *resource;
1056
1057     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
1058
1059     // Use the handle to find the resource in the resource linked list
1060     resource = findResource(handle);
1061     if (!resource) {
1062         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1063         return NULL;
1064     }
1065
1066     // Bind the handler
1067     return resource->entityHandler;
1068 }
1069
1070 /**
1071  * Notify observers that an observed value has changed.
1072  *
1073  *
1074  * @param handle - handle of resource
1075  *
1076  * @return
1077  *     OC_STACK_OK    - no errors
1078  *     OC_STACK_ERROR - stack not initialized
1079  */
1080 OCStackResult OCNotifyObservers(OCResourceHandle handle) {
1081     OCResource *resPtr = NULL;
1082     OCStackResult result;
1083
1084     OC_LOG(INFO, TAG, PCF("Entering OCNotifyObservers"));
1085
1086     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1087
1088     // Verify that the resource exists
1089     resPtr = findResource ((OCResource *) handle);
1090     if (NULL == resPtr)
1091     {
1092         return OC_STACK_NO_RESOURCE;
1093     } else {
1094         result = SendObserverNotification (handle, resPtr);
1095         return result;
1096     }
1097 }
1098
1099 //-----------------------------------------------------------------------------
1100 // Private internal function definitions
1101 //-----------------------------------------------------------------------------
1102 /**
1103  * Generate handle of OCDoResource invocation for callback management.
1104  */
1105 static OCDoHandle GenerateInvocationHandle()
1106 {
1107     OCDoHandle handle = NULL;
1108     // Generate token here, it will be deleted when the transaction is deleted
1109     handle = (OCDoHandle) malloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1110     if (handle)
1111     {
1112         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1113     }
1114
1115     return handle;
1116 }
1117
1118 /**
1119  * Initialize resource data structures, variables, etc.
1120  */
1121 void initResources() {
1122     TODO ("Do we need to create a resource for /oc/core???");
1123     // Init resource vars
1124     headResource = NULL;
1125 }
1126
1127 /**
1128  * Add a resource to the end of the linked list of resources.
1129  *
1130  * @param resource - resource to be added
1131  */
1132 void insertResource(OCResource *resource) {
1133     OCResource *pointer;
1134
1135     if (!headResource) {
1136         headResource = resource;
1137     } else {
1138         pointer = headResource;
1139
1140         while (pointer->next) {
1141             pointer = pointer->next;
1142         }
1143         pointer->next = resource;
1144     }
1145     resource->next = NULL;
1146 }
1147
1148 /**
1149  * Find a resource in the linked list of resources.
1150  *
1151  * @param resource - resource to be found
1152  * @return
1153  *     NULL                - resource not found
1154  *     pointer to resource - pointer to resource that was found in the linked list
1155  */
1156 OCResource *findResource(OCResource *resource) {
1157     OCResource *pointer = headResource;
1158
1159     while (pointer) {
1160         if (pointer == resource) {
1161             return resource;
1162         }
1163         pointer = pointer->next;
1164     }
1165     return NULL;
1166 }
1167
1168 void deleteAllResources()
1169 {
1170     OCResource *pointer = headResource;
1171     OCResource *temp;
1172
1173     while (pointer)
1174     {
1175         temp = pointer->next;
1176         deleteResource(pointer);
1177         pointer = temp;
1178     }
1179 }
1180
1181 /**
1182  * Delete the resource from the linked list.
1183  *
1184  * @param resource - resource to be deleted
1185  * @return
1186  *    0 - error
1187  *    1 - success
1188  */
1189 int deleteResource(OCResource *resource) {
1190     OCResource *prev = NULL;
1191     OCResource *temp;
1192
1193     temp = headResource;
1194     while (temp) {
1195         if (temp == resource) {
1196             if (temp == headResource) {
1197                 headResource = temp->next;
1198             } else {
1199                 prev->next = temp->next;
1200             }
1201             deleteResourceElements(temp);
1202             OCFree(temp);
1203             return 1;
1204         } else {
1205             prev = temp;
1206             temp = temp->next;
1207         }
1208     }
1209
1210     return 0;
1211 }
1212
1213 /**
1214  * Delete all of the dynamically allocated elements that were created for the resource.
1215  *
1216  * @param resource - specified resource
1217  */
1218 void deleteResourceElements(OCResource *resource) {
1219     if (!resource) {
1220         return;
1221     }
1222
1223     // remove URI
1224     OCFree(resource->uri);
1225
1226     // Delete resourcetype linked list
1227     deleteResourceType(resource->rsrcType);
1228
1229     // Delete resourceinterface linked list
1230     deleteResourceInterface(resource->rsrcInterface);
1231 }
1232
1233 /**
1234  * Delete all of the dynamically allocated elements that were created for the resource type.
1235  *
1236  * @param resourceType - specified resource type
1237  */
1238 void deleteResourceType(OCResourceType *resourceType) {
1239     OCResourceType *pointer = resourceType;
1240     OCResourceType *next;
1241
1242     while (pointer) {
1243         next = pointer->next;
1244         OCFree(pointer->resourcetypename);
1245         OCFree(pointer);
1246         pointer = next;
1247     }
1248 }
1249
1250 /**
1251  * Delete all of the dynamically allocated elements that were created for the resource interface.
1252  *
1253  * @param resourceInterface - specified resource interface
1254  */
1255 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
1256     OCResourceInterface *pointer = resourceInterface;
1257     OCResourceInterface *next;
1258
1259     while (pointer) {
1260         next = pointer->next;
1261         OCFree(pointer->name);
1262         OCFree(pointer);
1263         pointer = next;
1264     }
1265 }
1266
1267 /**
1268  * Insert a resource type into a resource's resource type linked list.
1269  *
1270  * @param resource - resource where resource type is to be inserted
1271  * @param resourceType - resource type to be inserted
1272  */
1273 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
1274     OCResourceType *pointer;
1275
1276     if (!resource->rsrcType) {
1277         resource->rsrcType = resourceType;
1278     } else {
1279         pointer = resource->rsrcType;
1280         while (pointer->next) {
1281             pointer = pointer->next;
1282         }
1283         pointer->next = resourceType;
1284     }
1285     resourceType->next = NULL;
1286 }
1287
1288 /**
1289  * Get a resource type at the specified index within a resource.
1290  *
1291  * @param handle - handle of resource
1292  * @param index - index of resource type
1293  *
1294  * @return
1295  *    resourcetype - if found
1296  *    NULL - not found
1297  */
1298 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
1299     OCResource *resource;
1300     OCResourceType *pointer;
1301     uint8_t i;
1302
1303     // Find the specified resource
1304     resource = findResource((OCResource *) handle);
1305     if (!resource) {
1306         return NULL;
1307     }
1308
1309     // Make sure a resource has a resourcetype
1310     if (!resource->rsrcType) {
1311         return NULL;
1312     }
1313
1314     // Iterate through the list
1315     pointer = resource->rsrcType;
1316     i = 0;
1317     while ((i < index) && pointer) {
1318         i++;
1319         pointer = pointer->next;
1320     }
1321     return pointer;
1322 }
1323
1324 /**
1325  * Insert a resource interface into a resource's resource interface linked list.
1326  *
1327  * @param resource - resource where resource interface is to be inserted
1328  * @param resourceInterface - resource interface to be inserted
1329  */
1330 void insertResourceInterface(OCResource *resource,
1331         OCResourceInterface *resourceInterface) {
1332     OCResourceInterface *pointer;
1333
1334     if (!resource->rsrcInterface) {
1335         resource->rsrcInterface = resourceInterface;
1336     } else {
1337         pointer = resource->rsrcInterface;
1338         while (pointer->next) {
1339             pointer = pointer->next;
1340         }
1341         pointer->next = resourceInterface;
1342     }
1343     resourceInterface->next = NULL;
1344 }
1345
1346 /**
1347  * Get a resource interface at the specified index within a resource.
1348  *
1349  * @param handle - handle of resource
1350  * @param index - index of resource interface
1351  *
1352  * @return
1353  *    resourceinterface - if found
1354  *    NULL - not found
1355  */
1356 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
1357         uint8_t index) {
1358     OCResource *resource;
1359     OCResourceInterface *pointer;
1360     uint8_t i = 0;
1361
1362     // Find the specified resource
1363     resource = findResource((OCResource *) handle);
1364     if (!resource) {
1365         return NULL;
1366     }
1367
1368     // Make sure a resource has a resourceinterface
1369     if (!resource->rsrcInterface) {
1370         return NULL;
1371     }
1372
1373     // Iterate through the list
1374     pointer = resource->rsrcInterface;
1375
1376     while ((i < index) && pointer) {
1377         i++;
1378         pointer = pointer->next;
1379     }
1380     return pointer;
1381 }
1382
1383 // TODO: Remove these!  Should be in an ocmalloc module
1384 void *OCMalloc(size_t size) {
1385     TODO ("This should be moved into an ocmalloc dir and implemented as a separate OC module");
1386     return malloc(size);
1387 }
1388
1389 void OCFree(void *ptr) {
1390     TODO ("This should be moved into an ocmalloc dir and implemented as a separate OC module");
1391     free(ptr);
1392 }
1393