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