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