1 //******************************************************************
3 // Copyright 2014 Intel Corporation All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 //-----------------------------------------------------------------------------
24 //-----------------------------------------------------------------------------
26 #include "ocstackinternal.h"
27 #include "ocserverrequest.h"
28 #include "ocresource.h"
29 #include "occlientcb.h"
30 #include "ocobserve.h"
35 //-----------------------------------------------------------------------------
37 //-----------------------------------------------------------------------------
39 OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED
42 //-----------------------------------------------------------------------------
44 //-----------------------------------------------------------------------------
45 static OCStackState stackState = OC_STACK_UNINITIALIZED;
46 OCResource *headResource = NULL;
48 //-----------------------------------------------------------------------------
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); } }
55 //-----------------------------------------------------------------------------
56 // Internal API function
57 //-----------------------------------------------------------------------------
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)");
67 VERIFY_NON_NULL(request, ERROR, OC_STACK_ERROR);
68 VERIFY_NON_NULL(request->entityHandlerRequest, ERROR, OC_STACK_ERROR);
70 if (IsVirtualResource((const char*)request->resourceUrl))
72 result = ValidateUrlQuery(request->resourceUrl,
73 request->entityHandlerRequest->query, &filterOn,
76 if (result == OC_STACK_OK)
78 result = ProcessResourceDiscoverReq(
79 (const unsigned char*) request->entityHandlerRequest->reqJSONPayload,
80 (unsigned char *) request->entityHandlerRequest->resJSONPayload, filterOn,
86 OCResource* resource = FindResourceByUri((const char*)request->resourceUrl);
89 request->entityHandlerRequest->resource = (OCResourceHandle)resource;
90 result = resource->entityHandler(OC_REQUEST_FLAG, request->entityHandlerRequest);
94 OC_LOG(INFO, TAG, "Resource Not found");
95 result = OC_STACK_NO_RESOURCE;
97 if (request->observe != NULL)
99 result = ProcessObserveRequest (resource, request);
106 //This function will be called back by occoap layer when a response is received
107 void HandleStackResponses(OCResponse * response) {
108 OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
109 OC_LOG(INFO, TAG, "Entering HandleStackResponses (OCStack Layer)");
111 if (response->cbNode) {
112 OC_LOG(INFO, TAG, PCF("Calling into application address space"));
113 result = response->cbNode->callBack(response->cbNode->context, response->cbNode->handle, response->clientResponse);
114 if (result == OC_STACK_DELETE_TRANSACTION) {
115 DeleteClientCB(response->cbNode);
120 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr) {
122 unsigned char *itr, *coap;
123 uint8_t dotCount = 0;
125 /* search for scheme */
127 if (!isdigit((unsigned char) *ipAddrStr)) {
128 coap = (unsigned char *) OC_COAP_SCHEME;
129 while (*coap && tolower(*itr) == *coap) {
137 if (isdigit((unsigned char) *ipAddrStr)) {
139 ipAddr[index] += *ipAddrStr - '0';
140 } else if ((unsigned char) *ipAddrStr == '.') {
149 if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
156 //-----------------------------------------------------------------------------
157 // Private internal function prototypes
158 //-----------------------------------------------------------------------------
160 static OCDoHandle GenerateInvocationHandle();
161 static void initResources();
162 static void insertResource(OCResource *resource);
163 static OCResource *findResource(OCResource *resource);
164 static void insertResourceType(OCResource *resource,
165 OCResourceType *resourceType);
166 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
168 static void insertResourceInterface(OCResource *resource,
169 OCResourceInterface *resourceInterface);
170 static OCResourceInterface *findResourceInterfaceAtIndex(
171 OCResourceHandle handle, uint8_t index);
172 static void deleteResourceType(OCResourceType *resourceType);
173 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
174 static void deleteResourceElements(OCResource *resource);
175 static int deleteResource(OCResource *resource);
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
188 //-----------------------------------------------------------------------------
190 //-----------------------------------------------------------------------------
193 * Initialize the OC Stack. Must be called prior to starting the stack.
196 * IP Address of host device
198 * Port of host device
200 * Host device is client, server, or client-server
203 * OC_STACK_OK - no errors
204 * OC_STACK_ERROR - stack init error
206 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode) {
207 OC_LOG(INFO, TAG, PCF("Entering OCInit"));
210 OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
215 OC_LOG(INFO, TAG, PCF("Client mode"));
218 OC_LOG(INFO, TAG, PCF("Server mode"));
220 case OC_CLIENT_SERVER:
221 OC_LOG(INFO, TAG, PCF("Client-server mode"));
224 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
225 return OC_STACK_ERROR;
229 // Initialize resource
232 // Make call to OCCoAP layer
233 if (OCInitCoAP(ipAddr, (uint16_t) port, mode) == 0) {
234 stackState = OC_STACK_INITIALIZED;
238 OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
239 return OC_STACK_ERROR;
243 * Stop the OC stack. Use for a controlled shutdown.
245 * OC_STACK_OK - no errors
246 * OC_STACK_ERROR - stack not initialized
248 OCStackResult OCStop() {
249 OC_LOG(INFO, TAG, PCF("Entering OCStop"));
251 if (stackState != OC_STACK_INITIALIZED) {
252 OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
253 return OC_STACK_ERROR;
256 // Make call to OCCoAP layer
257 if (OCStopCoAP() == 0) {
258 // Remove all observers
259 DeleteObserverList();
260 // Remove all the client callbacks
261 DeleteClientCBList();
262 stackState = OC_STACK_UNINITIALIZED;
266 OC_LOG(ERROR, TAG, PCF("Stack stop error"));
267 return OC_STACK_ERROR;
271 * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
273 * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
274 * @param method - @ref OCMethod to perform on the resource
275 * @param requiredUri - URI of the resource to interact with
276 * @param referenceUri - URI of the reference resource
277 * @param request - JSON encoded request
278 * @param qos - quality of service
279 * @param cbData - struct that contains asynchronous callback function that is invoked
280 * by the stack when discovery or resource interaction is complete
283 * OC_STACK_OK - no errors
284 * OC_STACK_INVALID_CALLBACK - invalid callback function pointer
285 * OC_STACK_INVALID_METHOD - invalid resource method
286 * OC_STACK_INVALID_URI - invalid required or reference URI
289 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
290 const char *referenceUri, const char *request,
291 OCQualityOfService qos, OCCallbackData *cbData)
293 OCStackResult result = OC_STACK_ERROR;
294 OCCoAPToken * token = NULL;
295 ClientCB *clientCB = NULL;
298 OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
300 // Validate input parameters
301 VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
302 VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
304 TODO ("Need to form the final query by concatenating require and reference URI's");
305 VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
312 case OC_REST_OBSERVE:
313 case OC_REST_OBSERVE_ALL:
316 DeleteClientCB(clientCB);
317 return OC_STACK_INVALID_METHOD;
320 *handle = GenerateInvocationHandle();
321 VERIFY_NON_NULL(*handle, FATAL, OC_STACK_ERROR);
322 token = OCGenerateCoAPToken();
327 if((result = AddClientCB(&clientCB, cbData, token, *handle, method)) != OC_STACK_OK)
332 // Make call to OCCoAP layer
333 result = OCDoCoAPResource(method, qos, token, requiredUri, request);
337 if (result != OC_STACK_OK)
339 OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
342 DeleteClientCB(clientCB);
354 * Cancel a request associated with a specific @ref OCDoResource invocation.
356 * @param handle - Used to identify a specific OCDoResource invocation.
359 * OC_STACK_OK - No errors; Success
360 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
362 OCStackResult OCCancel(OCDoHandle handle) {
364 * This ftn can be implemented one of two ways:
366 * 1. When observe is unobserved..Remove the callback associated on client side.
367 * When the next notification comes in from server, reply with RST message to server.
369 * 2. When OCCancel is called, and it is associated with an observe request
370 * (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
371 * Send Observe request to server with observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
372 * Remove the callback associated on client side.
374 * Number 1 is implemented here.
377 return OC_STACK_INVALID_PARAM;
380 OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
382 ClientCB *clientCB = GetClientCB(NULL, handle);
385 switch (clientCB->method)
387 case OC_REST_OBSERVE:
388 case OC_REST_OBSERVE_ALL:
389 // Make call to OCCoAP layer
390 DeleteClientCB(clientCB);
393 return OC_STACK_INVALID_METHOD;
400 * Called in main loop of OC client or server. Allows low-level processing of
404 * OC_STACK_OK - no errors
405 * OC_STACK_ERROR - stack process error
407 OCStackResult OCProcess() {
409 OC_LOG(INFO, TAG, PCF("Entering OCProcess"));
417 * @param handle - pointer to handle to newly created resource. Set by ocstack. Used to refer to resource
418 * @param resourceTypeName - name of resource type. Example: "core.led"
419 * @param resourceAttributeRepresentation - attribute representation. list of attributes:type, with each pair
420 * separated by semicolons. Example: "state:oc.bt.b;power:oc.bt.i"
421 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
422 * @param allowedMethods - methods permitted on interface. Example: OC_REST_GET|OC_REST_PUT
423 * @param uri - URI of the resource. Example: "/a/led"
424 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
425 * @param resourceProperties - properties supported by resource. Example: OC_DISCOVERABLE|OC_OBSERVABLE
428 * OC_STACK_OK - no errors
429 * OC_STACK_ERROR - stack process error
431 OCStackResult OCCreateResource(OCResourceHandle *handle,
432 const char *resourceTypeName,
433 const char *resourceAttributeRepresentation,
434 const char *resourceInterfaceName, uint8_t allowedMethods,
435 const char *uri, OCEntityHandler entityHandler,
436 uint8_t resourceProperties) {
438 OCResource *pointer = NULL;
441 OCStackResult result = OC_STACK_ERROR;
443 OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
445 // Validate parameters
446 // TODO: Does resource attribute representation really have to be maintained in stack?
447 // Is it presented during resource discovery?
448 // VERIFY_NON_NULL(resourceAttributeRepresentation, ERROR, OC_STACK_ERROR);
449 if (!handle || !resourceTypeName || !resourceInterfaceName || !uri) {
450 OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
451 return OC_STACK_INVALID_PARAM;
454 // Make sure allowedMethods bitmask has allowed methods specified
456 > (OC_REST_GET | OC_REST_PUT | OC_REST_POST | OC_REST_DELETE
458 || (allowedMethods == OC_REST_NOMETHOD)) {
459 OC_LOG(ERROR, TAG, PCF("Invalid method"));
460 return OC_STACK_INVALID_PARAM;
463 // Make sure resourceProperties bitmask has allowed properties specified
464 if (resourceProperties
465 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
466 OC_LOG(ERROR, TAG, PCF("Invalid property"));
467 return OC_STACK_INVALID_PARAM;
470 // If the headResource is NULL, then no resources have been created...
471 pointer = headResource;
473 // At least one resources is in the resource list, so we need to search for
474 // repeated URLs, which are not allowed. If a repeat is found, exit with an error
476 if (strcmp(uri, pointer->uri) == 0) {
477 OC_LOG(ERROR, TAG, PCF("URI already in use"));
478 return OC_STACK_INVALID_PARAM;
480 pointer = pointer->next;
483 // Create the pointer and insert it into the resource list
484 pointer = (OCResource *) OCMalloc(sizeof(OCResource));
488 memset(pointer, 0, sizeof(OCResource));
490 insertResource(pointer);
493 size = strlen(uri) + 1;
494 str = (char *) OCMalloc(size);
498 strncpy(str, uri, size);
501 // Set properties. Set OC_ACTIVE
502 pointer->resourceProperties = (OCResourceProperty) (resourceProperties
505 // Add the resourcetype to the resource
506 result = OCBindResourceTypeToResource((OCResourceHandle) pointer,
507 resourceTypeName, resourceAttributeRepresentation);
508 if (result != OC_STACK_OK) {
509 OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
513 // Add the resourceinterface to the resource
514 result = OCBindResourceInterfaceToResource((OCResourceHandle) pointer,
515 resourceInterfaceName, allowedMethods);
516 if (result != OC_STACK_OK) {
517 OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
522 result = OCBindResourceHandler((OCResourceHandle) pointer, entityHandler);
523 if (result != OC_STACK_OK) {
524 OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
529 result = OC_STACK_OK;
532 if (result != OC_STACK_OK)
541 * Add a resource to a container resource.
543 * @param containerHandle - handle to the container resource
544 * @param addedResourceHandle - handle to resource to be added to the container resource
547 * OC_STACK_OK - no errors
548 * OC_STACK_ERROR - stack process error
550 OCStackResult OCBindContainedResourceToResource(
551 OCResourceHandle containerHandle, OCResourceHandle addedResourceHandle) {
552 OCResource *resource;
555 OC_LOG(INFO, TAG, PCF("Entering OCBindContainedResourceToResource"));
557 // Validate parameters
558 VERIFY_NON_NULL(containerHandle, ERROR, OC_STACK_ERROR);
559 VERIFY_NON_NULL(addedResourceHandle, ERROR, OC_STACK_ERROR);
560 // Container cannot contain itself
561 if (containerHandle == addedResourceHandle) {
562 OC_LOG(ERROR, TAG, PCF("Added handle equals container handle"));
563 return OC_STACK_INVALID_PARAM;
566 // Use the handle to find the resource in the resource linked list
567 resource = findResource((OCResource *) containerHandle);
569 OC_LOG(ERROR, TAG, PCF("Resource not found"));
570 return OC_STACK_INVALID_PARAM;
573 // Look for an open slot to add add the child resource.
574 // If found, add it and return success
575 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
576 if (!resource->rsrcResources[i]) {
577 resource->rsrcResources[i] = (OCResourceHandle) addedResourceHandle;
578 OC_LOG(INFO, TAG, PCF("resource bound"));
583 // Unable to add addedResourceHandle, so return error
584 return OC_STACK_ERROR;
588 * Bind a resourcetype to a resource.
590 * @param handle - handle to the container resource
591 * @param resourceTypeName - name of resource type. Example: "core.led"
592 * @param resourceAttributeRepresentation - attribute representation. list of attributes:type, with each pair
593 * separated by semicolons. Example: "state:oc.bt.b;power:oc.bt.i"
596 * OC_STACK_OK - no errors
597 * OC_STACK_ERROR - stack process error
599 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
600 const char *resourceTypeName,
601 const char *resourceAttributeRepresentation) {
603 OCResourceType *pointer = NULL;
606 OCResource *resource;
607 OCStackResult result = OC_STACK_ERROR;
609 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceTypeToResource"));
611 // Validate parameters
612 VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
613 // TODO: Does resource attribute resentation really have to be maintained in stack?
614 // Is it presented during resource discovery?
615 // VERIFY_NON_NULL(resourceAttributeRepresentation, ERROR, OC_STACK_ERROR);
617 // Make sure resource exists
618 resource = findResource((OCResource *) handle);
620 OC_LOG(ERROR, TAG, PCF("Resource not found"));
621 return OC_STACK_ERROR;
624 TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
626 // Create the resourcetype and insert it into the resource list
627 pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
631 memset(pointer, 0, sizeof(OCResourceType));
633 // Set the resourceTypeName
634 size = strlen(resourceTypeName) + 1;
635 str = (char *) OCMalloc(size);
639 strncpy(str, resourceTypeName, size);
640 pointer->resourcetypename = str;
642 // If the resourceAttributeRepresentation is defined, add it.
643 if (resourceAttributeRepresentation) {
644 size = strlen(resourceAttributeRepresentation) + 1;
645 str = (char *) OCMalloc(size);
649 strncpy(str, resourceAttributeRepresentation, size);
650 pointer->typerepresentation = str;
652 // Bind the resourcetype to the resource
653 insertResourceType(resource, pointer);
655 result = OC_STACK_OK;
657 exit: if (result != OC_STACK_OK) {
665 * Bind a resourceinterface to a resource.
667 * @param handle - handle to the container resource
668 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
669 * @param allowedMethods - methods permitted on interface. Example: OC_REST_GET|OC_REST_PUT
672 * OC_STACK_OK - no errors
673 * OC_STACK_ERROR - stack process error
675 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
676 const char *resourceInterfaceName, uint8_t allowedMethods) {
678 OCResourceInterface *pointer = NULL;
681 OCResource *resource;
682 OCStackResult result = OC_STACK_ERROR;
684 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceInterfaceToResource"));
686 // Validate parameters
687 VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
689 // Make sure allowedMethods bitmask has allowed methods specified
691 > (OC_REST_GET | OC_REST_PUT | OC_REST_POST | OC_REST_DELETE
693 || (allowedMethods == OC_REST_NOMETHOD)) {
694 OC_LOG(ERROR, TAG, PCF("Invalid method"));
695 return OC_STACK_INVALID_PARAM;
698 // Make sure resource exists
699 resource = findResource((OCResource *) handle);
701 OC_LOG(ERROR, TAG, PCF("Resource not found"));
702 return OC_STACK_INVALID_PARAM;
705 TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
707 // Create the resourceinterface and insert it into the resource list
708 pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
712 memset(pointer, 0, sizeof(OCResourceInterface));
714 // Set the resourceinterface name
715 size = strlen(resourceInterfaceName) + 1;
716 str = (char *) OCMalloc(size);
720 strncpy(str, resourceInterfaceName, size);
723 pointer->allowedMethods = allowedMethods;
725 // Bind the resourceinterface to the resource
726 insertResourceInterface(resource, pointer);
728 result = OC_STACK_OK;
729 exit: if (result != OC_STACK_OK) {
737 * Get the number of resources that have been created in the stack.
739 * @param numResources - pointer to count variable
742 * OC_STACK_OK - no errors
743 * OC_STACK_ERROR - stack process error
746 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
747 OCResource *pointer = headResource;
749 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
750 VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
753 *numResources = *numResources + 1;
754 pointer = pointer->next;
760 * Get a resource handle by index.
762 * @param index - index of resource, 0 to Count - 1
765 * Resource handle - if found
766 * NULL - if not found
768 OCResourceHandle OCGetResourceHandle(uint8_t index) {
769 OCResource *pointer = headResource;
772 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
774 // Iterate through the list
775 while ((i < index) && pointer) {
777 pointer = pointer->next;
779 return (OCResourceHandle) pointer;
783 * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
786 * @param handle - handle of resource to be deleted
789 * OC_STACK_OK - no errors
790 * OC_STACK_ERROR - stack process error
792 OCStackResult OCDeleteResource(OCResourceHandle handle) {
793 OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
796 OC_LOG(ERROR, TAG, PCF("Resource not found"));
797 return OC_STACK_INVALID_PARAM;
800 if (deleteResource((OCResource *) handle) == 0) {
801 OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
802 return OC_STACK_ERROR;
809 * Get the URI of the resource specified by handle.
811 * @param handle - handle of resource
813 * URI string - if resource found
814 * NULL - resource not found
816 const char *OCGetResourceUri(OCResourceHandle handle) {
817 OCResource *resource;
818 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
820 resource = findResource((OCResource *) handle);
822 return resource->uri;
824 return (const char *) NULL;
828 * Get the properties of the resource specified by handle.
829 * NOTE: that after a resource is created, the OC_ACTIVE property is set
830 * for the resource by the stack.
832 * @param handle - handle of resource
834 * property bitmap - if resource found
835 * NULL - resource not found
837 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
838 OCResource *resource;
839 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
841 resource = findResource((OCResource *) handle);
843 return resource->resourceProperties;
849 * Get the number of resource types of the resource.
851 * @param handle - handle of resource
852 * @param numResourceTypes - pointer to count variable
855 * OC_STACK_OK - no errors
856 * OC_STACK_ERROR - stack process error
858 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
859 uint8_t *numResourceTypes) {
860 OCResource *resource;
861 OCResourceType *pointer;
863 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
864 VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
865 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
867 *numResourceTypes = 0;
869 resource = findResource((OCResource *) handle);
871 pointer = resource->rsrcType;
873 *numResourceTypes = *numResourceTypes + 1;
874 pointer = pointer->next;
881 * Get name of resource type of the resource.
883 * @param handle - handle of resource
884 * @param index - index of resource, 0 to Count - 1
887 * resource type name - if resource found
888 * NULL - resource not found
890 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
891 OCResourceType *resourceType;
893 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
895 resourceType = findResourceTypeAtIndex(handle, index);
897 return resourceType->resourcetypename;
899 return (const char *) NULL;
903 * Get attributes of resource type of the resource.
905 * @param handle - handle of resource
906 * @param index - index of resource, 0 to Count - 1
909 * resource type attributes - if resource found
910 * NULL - resource not found
912 const char *OCGetResourceAttributeRepresentation(OCResourceHandle handle,
914 OCResourceType *resourceType;
916 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceAttributeRepresentation"));
918 resourceType = findResourceTypeAtIndex(handle, index);
920 return resourceType->typerepresentation;
922 return (const char *) NULL;
926 * Get the number of resource interfaces of the resource.
928 * @param handle - handle of resource
929 * @param numResources - pointer to count variable
932 * OC_STACK_OK - no errors
933 * OC_STACK_ERROR - stack process error
936 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
937 uint8_t *numResourceInterfaces) {
938 OCResourceInterface *pointer;
939 OCResource *resource;
941 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
943 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
944 VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
946 *numResourceInterfaces = 0;
947 resource = findResource((OCResource *) handle);
949 pointer = resource->rsrcInterface;
951 *numResourceInterfaces = *numResourceInterfaces + 1;
952 pointer = pointer->next;
959 * Get name of resource interface of the resource.
961 * @param handle - handle of resource
962 * @param index - index of resource, 0 to Count - 1
965 * resource interface name - if resource found
966 * NULL - resource not found
968 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
969 OCResourceInterface *resourceInterface;
971 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
973 resourceInterface = findResourceInterfaceAtIndex(handle, index);
974 if (resourceInterface) {
975 return resourceInterface->name;
977 return (const char *) NULL;
981 * Get methods of resource interface of the resource.
983 * @param handle - handle of resource
984 * @param index - index of resource, 0 to Count - 1
987 * allowed methods - if resource found
988 * NULL - resource not found
990 uint8_t OCGetResourceInterfaceAllowedMethods(OCResourceHandle handle,
992 OCResourceInterface *resourceInterface;
994 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceAllowedMethods"));
996 resourceInterface = findResourceInterfaceAtIndex(handle, index);
997 if (resourceInterface) {
998 return resourceInterface->allowedMethods;
1004 * Get name of resource interface of the resource.
1006 * @param containerHandle - handle of container resource
1007 * @param index - index of contained resource, 0 to Count - 1
1010 * handle to contained resource - if resource found
1011 * NULL - resource not found
1013 OCResourceHandle OCGetContainedResourceHandle(OCResourceHandle containerHandle,
1015 OCResource *resource;
1017 OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
1019 if (index >= MAX_CONTAINED_RESOURCES) {
1023 resource = findResource((OCResource *) containerHandle);
1028 return resource->rsrcResources[index];
1032 * Bind an entity handler to the resource.
1034 * @param handle - handle to the resource that the contained resource is to be bound
1035 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1037 * OC_STACK_OK - no errors
1038 * OC_STACK_ERROR - stack process error
1040 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
1041 OCEntityHandler entityHandler) {
1042 OCResource *resource;
1044 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
1046 // Validate parameters
1047 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1048 VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
1050 // Use the handle to find the resource in the resource linked list
1051 resource = findResource(handle);
1053 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1054 return OC_STACK_ERROR;
1058 resource->entityHandler = entityHandler;
1064 * Get the entity handler for a resource.
1066 * @param handle - handle of resource
1069 * entity handler - if resource found
1070 * NULL - resource not found
1072 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
1073 OCResource *resource;
1075 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
1077 // Use the handle to find the resource in the resource linked list
1078 resource = findResource(handle);
1080 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1085 return resource->entityHandler;
1089 * Notify observers that an observed value has changed.
1092 * @param handle - handle of resource
1095 * OC_STACK_OK - no errors
1096 * OC_STACK_ERROR - stack not initialized
1098 OCStackResult OCNotifyObservers(OCResourceHandle handle) {
1099 OCResource *resPtr = NULL;
1100 OCStackResult result;
1102 OC_LOG(INFO, TAG, PCF("Entering OCNotifyObservers"));
1104 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1106 // Verify that the resource exists
1107 resPtr = findResource ((OCResource *) handle);
1110 return OC_STACK_NO_RESOURCE;
1112 result = SendObserverNotification (handle, resPtr);
1117 //-----------------------------------------------------------------------------
1118 // Private internal function definitions
1119 //-----------------------------------------------------------------------------
1121 * Generate handle of OCDoResource invocation for callback management.
1123 static OCDoHandle GenerateInvocationHandle()
1125 OCDoHandle handle = NULL;
1126 // Generate token here, it will be deleted when the transaction is deleted
1127 handle = (OCDoHandle) malloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1130 OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1137 * Initialize resource data structures, variables, etc.
1139 void initResources() {
1140 TODO ("Do we need to create a resource for /oc/core???");
1141 // Init resource vars
1142 headResource = NULL;
1146 * Add a resource to the end of the linked list of resources.
1148 * @param resource - resource to be added
1150 void insertResource(OCResource *resource) {
1151 OCResource *pointer;
1153 if (!headResource) {
1154 headResource = resource;
1156 pointer = headResource;
1158 while (pointer->next) {
1159 pointer = pointer->next;
1161 pointer->next = resource;
1163 resource->next = NULL;
1167 * Find a resource in the linked list of resources.
1169 * @param resource - resource to be found
1171 * NULL - resource not found
1172 * pointer to resource - pointer to resource that was found in the linked list
1174 OCResource *findResource(OCResource *resource) {
1175 OCResource *pointer = headResource;
1178 if (pointer == resource) {
1181 pointer = pointer->next;
1187 * Delete the resource from the linked list.
1189 * @param resource - resource to be deleted
1194 int deleteResource(OCResource *resource) {
1195 OCResource *prev = NULL;
1198 temp = headResource;
1200 if (temp == resource) {
1201 if (temp == headResource) {
1202 headResource = temp->next;
1204 prev->next = temp->next;
1206 deleteResourceElements(temp);
1219 * Delete all of the dynamically allocated elements that were created for the resource.
1221 * @param resource - specified resource
1223 void deleteResourceElements(OCResource *resource) {
1229 OCFree(resource->uri);
1231 // Delete resourcetype linked list
1232 deleteResourceType(resource->rsrcType);
1234 // Delete resourceinterface linked list
1235 deleteResourceInterface(resource->rsrcInterface);
1239 * Delete all of the dynamically allocated elements that were created for the resource type.
1241 * @param resourceType - specified resource type
1243 void deleteResourceType(OCResourceType *resourceType) {
1244 OCResourceType *pointer = resourceType;
1245 OCResourceType *next;
1248 next = pointer->next;
1249 OCFree(pointer->resourcetypename);
1250 OCFree(pointer->typerepresentation);
1257 * Delete all of the dynamically allocated elements that were created for the resource interface.
1259 * @param resourceInterface - specified resource interface
1261 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
1262 OCResourceInterface *pointer = resourceInterface;
1263 OCResourceInterface *next;
1266 next = pointer->next;
1267 OCFree(pointer->name);
1274 * Insert a resource type into a resource's resource type linked list.
1276 * @param resource - resource where resource type is to be inserted
1277 * @param resourceType - resource type to be inserted
1279 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
1280 OCResourceType *pointer;
1282 if (!resource->rsrcType) {
1283 resource->rsrcType = resourceType;
1285 pointer = resource->rsrcType;
1286 while (pointer->next) {
1287 pointer = pointer->next;
1289 pointer->next = resourceType;
1291 resourceType->next = NULL;
1295 * Get a resource type at the specified index within a resource.
1297 * @param handle - handle of resource
1298 * @param index - index of resource type
1301 * resourcetype - if found
1304 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
1305 OCResource *resource;
1306 OCResourceType *pointer;
1309 // Find the specified resource
1310 resource = findResource((OCResource *) handle);
1315 // Make sure a resource has a resourcetype
1316 if (!resource->rsrcType) {
1320 // Iterate through the list
1321 pointer = resource->rsrcType;
1323 while ((i < index) && pointer) {
1325 pointer = pointer->next;
1331 * Insert a resource interface into a resource's resource interface linked list.
1333 * @param resource - resource where resource interface is to be inserted
1334 * @param resourceInterface - resource interface to be inserted
1336 void insertResourceInterface(OCResource *resource,
1337 OCResourceInterface *resourceInterface) {
1338 OCResourceInterface *pointer;
1340 if (!resource->rsrcInterface) {
1341 resource->rsrcInterface = resourceInterface;
1343 pointer = resource->rsrcInterface;
1344 while (pointer->next) {
1345 pointer = pointer->next;
1347 pointer->next = resourceInterface;
1349 resourceInterface->next = NULL;
1353 * Get a resource interface at the specified index within a resource.
1355 * @param handle - handle of resource
1356 * @param index - index of resource interface
1359 * resourceinterface - if found
1362 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
1364 OCResource *resource;
1365 OCResourceInterface *pointer;
1368 // Find the specified resource
1369 resource = findResource((OCResource *) handle);
1374 // Make sure a resource has a resourceinterface
1375 if (!resource->rsrcInterface) {
1379 // Iterate through the list
1380 pointer = resource->rsrcInterface;
1382 while ((i < index) && pointer) {
1384 pointer = pointer->next;
1389 // TODO: Remove these! Should be in an ocmalloc module
1390 void *OCMalloc(size_t size) {
1391 TODO ("This should be moved into an ocmalloc dir and implemented as a separate OC module");
1392 return malloc(size);
1395 void OCFree(void *ptr) {
1396 TODO ("This should be moved into an ocmalloc dir and implemented as a separate OC module");