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, PCF("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(request->entityHandlerRequest,
85 OCResource* resource = FindResourceByUri((const char*)request->resourceUrl);
88 request->entityHandlerRequest->resource = (OCResourceHandle)resource;
89 result = resource->entityHandler(OC_REQUEST_FLAG, request->entityHandlerRequest);
93 OC_LOG(INFO, TAG, PCF("Resource Not found"));
94 result = OC_STACK_NO_RESOURCE;
96 if (request->observe != NULL)
98 result = ProcessObserveRequest (resource, request);
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)"));
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);
119 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr) {
121 unsigned char *itr, *coap;
122 uint8_t dotCount = 0;
124 /* search for scheme */
126 if (!isdigit((unsigned char) *ipAddrStr)) {
127 coap = (unsigned char *) OC_COAP_SCHEME;
128 while (*coap && tolower(*itr) == *coap) {
136 if (isdigit((unsigned char) *ipAddrStr)) {
138 ipAddr[index] += *ipAddrStr - '0';
139 } else if ((unsigned char) *ipAddrStr == '.') {
148 if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
155 //-----------------------------------------------------------------------------
156 // Private internal function prototypes
157 //-----------------------------------------------------------------------------
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,
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();
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
189 //-----------------------------------------------------------------------------
191 //-----------------------------------------------------------------------------
194 * Initialize the OC Stack. Must be called prior to starting the stack.
197 * IP Address of host device
199 * Port of host device
201 * Host device is client, server, or client-server
204 * OC_STACK_OK - no errors
205 * OC_STACK_ERROR - stack init error
207 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode) {
208 OC_LOG(INFO, TAG, PCF("Entering OCInit"));
211 OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
216 OC_LOG(INFO, TAG, PCF("Client mode"));
219 OC_LOG(INFO, TAG, PCF("Server mode"));
221 case OC_CLIENT_SERVER:
222 OC_LOG(INFO, TAG, PCF("Client-server mode"));
225 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
226 return OC_STACK_ERROR;
230 // Initialize resource
233 // Make call to OCCoAP layer
234 if (OCInitCoAP(ipAddr, (uint16_t) port, mode) == 0) {
235 stackState = OC_STACK_INITIALIZED;
239 OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
240 return OC_STACK_ERROR;
244 * Stop the OC stack. Use for a controlled shutdown.
246 * OC_STACK_OK - no errors
247 * OC_STACK_ERROR - stack not initialized
249 OCStackResult OCStop() {
250 OCStackResult result = OC_STACK_ERROR;
252 OC_LOG(INFO, TAG, PCF("Entering OCStop"));
254 if (stackState != OC_STACK_INITIALIZED) {
255 OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
256 return OC_STACK_ERROR;
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;
268 result = OC_STACK_ERROR;
271 // Free memory dynamically allocated for resources
272 deleteAllResources();
274 if (result != OC_STACK_OK) {
275 OC_LOG(ERROR, TAG, PCF("Stack stop error"));
282 * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
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
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
300 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
301 const char *referenceUri, const char *request,
302 OCQualityOfService qos, OCCallbackData *cbData)
304 OCStackResult result = OC_STACK_ERROR;
305 OCCoAPToken * token = NULL;
306 ClientCB *clientCB = NULL;
309 OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
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);
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);
323 case OC_REST_OBSERVE:
324 case OC_REST_OBSERVE_ALL:
327 return OC_STACK_INVALID_METHOD;
330 *handle = GenerateInvocationHandle();
331 VERIFY_NON_NULL(*handle, FATAL, OC_STACK_ERROR);
332 token = OCGenerateCoAPToken();
337 if((result = AddClientCB(&clientCB, cbData, token, *handle, method)) != OC_STACK_OK)
342 // Make call to OCCoAP layer
343 result = (OCStackResult)OCDoCoAPResource(method, qos, token, requiredUri, request);
347 if (result != OC_STACK_OK)
349 OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
352 DeleteClientCB(clientCB);
364 * Cancel a request associated with a specific @ref OCDoResource invocation.
366 * @param handle - Used to identify a specific OCDoResource invocation.
369 * OC_STACK_OK - No errors; Success
370 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
372 OCStackResult OCCancel(OCDoHandle handle) {
374 * This ftn can be implemented one of two ways:
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.
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.
384 * Number 1 is implemented here.
387 return OC_STACK_INVALID_PARAM;
390 OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
392 ClientCB *clientCB = GetClientCB(NULL, &handle);
395 switch (clientCB->method)
397 case OC_REST_OBSERVE:
398 case OC_REST_OBSERVE_ALL:
399 // Make call to OCCoAP layer
400 DeleteClientCB(clientCB);
403 return OC_STACK_INVALID_METHOD;
410 * Called in main loop of OC client or server. Allows low-level processing of
414 * OC_STACK_OK - no errors
415 * OC_STACK_ERROR - stack process error
417 OCStackResult OCProcess() {
419 OC_LOG(INFO, TAG, PCF("Entering OCProcess"));
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
436 * OC_STACK_OK - no errors
437 * OC_STACK_ERROR - stack process error
439 OCStackResult OCCreateResource(OCResourceHandle *handle,
440 const char *resourceTypeName,
441 const char *resourceInterfaceName,
442 const char *uri, OCEntityHandler entityHandler,
443 uint8_t resourceProperties) {
445 OCResource *pointer = NULL;
448 OCStackResult result = OC_STACK_ERROR;
450 OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
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;
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;
466 // If the headResource is NULL, then no resources have been created...
467 pointer = headResource;
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
472 if (strcmp(uri, pointer->uri) == 0) {
473 OC_LOG(ERROR, TAG, PCF("URI already in use"));
474 return OC_STACK_INVALID_PARAM;
476 pointer = pointer->next;
479 // Create the pointer and insert it into the resource list
480 pointer = (OCResource *) OCMalloc(sizeof(OCResource));
484 memset(pointer, 0, sizeof(OCResource));
486 insertResource(pointer);
489 size = strlen(uri) + 1;
490 str = (char *) OCMalloc(size);
494 strncpy(str, uri, size);
497 // Set properties. Set OC_ACTIVE
498 pointer->resourceProperties = (OCResourceProperty) (resourceProperties
501 // Add the resourcetype to the resource
502 result = OCBindResourceTypeToResource((OCResourceHandle) pointer,
504 if (result != OC_STACK_OK) {
505 OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
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"));
517 // If an entity handler has been passed, attach it to the newly created
518 // resource. Otherwise, set the default entity handler.
521 pointer->entityHandler = entityHandler;
525 pointer->entityHandler = defaultResourceEHandler;
529 result = OC_STACK_OK;
532 if (result != OC_STACK_OK)
534 // Deep delete of resource and other dynamic elements that it contains
535 deleteResource(pointer);
542 * Add a resource to a collection resource.
544 * @param collectionHandle - handle to the collection resource
545 * @param resourceHandle - handle to resource to be added to the collection resource
548 * OC_STACK_OK - no errors
549 * OC_STACK_ERROR - stack process error
550 * OC_STACK_INVALID_PARAM - invalid collectionhandle
552 OCStackResult OCBindResource(
553 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
554 OCResource *resource;
557 OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
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;
568 // Use the handle to find the resource in the resource linked list
569 resource = findResource((OCResource *) collectionHandle);
571 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
572 return OC_STACK_INVALID_PARAM;
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"));
585 // Unable to add resourceHandle, so return error
586 return OC_STACK_ERROR;
590 * Remove a resource from a collection resource.
592 * @param collectionHandle - handle to the collection resource
593 * @param resourceHandle - handle to resource to be added to the collection resource
596 * OC_STACK_OK - no errors
597 * OC_STACK_ERROR - stack process error
598 * OC_STACK_INVALID_PARAM - invalid collectionHandle
600 OCStackResult OCUnBindResource(
601 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
602 OCResource *resource;
605 OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
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;
616 // Use the handle to find the resource in the resource linked list
617 resource = findResource((OCResource *) collectionHandle);
619 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
620 return OC_STACK_INVALID_PARAM;
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"));
633 OC_LOG(INFO, TAG, PCF("resource not found in collection"));
635 // Unable to add resourceHandle, so return error
636 return OC_STACK_ERROR;
641 * Bind a resourcetype to a resource.
643 * @param handle - handle to the resource
644 * @param resourceTypeName - name of resource type. Example: "core.led"
647 * OC_STACK_OK - no errors
648 * OC_STACK_ERROR - stack process error
650 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
651 const char *resourceTypeName) {
653 OCResourceType *pointer = NULL;
656 OCResource *resource;
657 OCStackResult result = OC_STACK_ERROR;
659 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceTypeToResource"));
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?
666 // Make sure resource exists
667 resource = findResource((OCResource *) handle);
669 OC_LOG(ERROR, TAG, PCF("Resource not found"));
670 return OC_STACK_ERROR;
673 TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
675 // Create the resourcetype and insert it into the resource list
676 pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
680 memset(pointer, 0, sizeof(OCResourceType));
682 // Set the resourceTypeName
683 size = strlen(resourceTypeName) + 1;
684 str = (char *) OCMalloc(size);
688 strncpy(str, resourceTypeName, size);
689 pointer->resourcetypename = str;
691 // Bind the resourcetype to the resource
692 insertResourceType(resource, pointer);
694 result = OC_STACK_OK;
696 exit: if (result != OC_STACK_OK) {
704 * Bind a resourceinterface to a resource.
706 * @param handle - handle to the resource
707 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
710 * OC_STACK_OK - no errors
711 * OC_STACK_ERROR - stack process error
713 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
714 const char *resourceInterfaceName) {
716 OCResourceInterface *pointer = NULL;
719 OCResource *resource;
720 OCStackResult result = OC_STACK_ERROR;
722 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceInterfaceToResource"));
724 // Validate parameters
725 VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
727 // Make sure resource exists
728 resource = findResource((OCResource *) handle);
730 OC_LOG(ERROR, TAG, PCF("Resource not found"));
731 return OC_STACK_INVALID_PARAM;
734 TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
736 // Create the resourceinterface and insert it into the resource list
737 pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
741 memset(pointer, 0, sizeof(OCResourceInterface));
743 // Set the resourceinterface name
744 size = strlen(resourceInterfaceName) + 1;
745 str = (char *) OCMalloc(size);
749 strncpy(str, resourceInterfaceName, size);
752 // Bind the resourceinterface to the resource
753 insertResourceInterface(resource, pointer);
755 result = OC_STACK_OK;
756 exit: if (result != OC_STACK_OK) {
764 * Get the number of resources that have been created in the stack.
766 * @param numResources - pointer to count variable
769 * OC_STACK_OK - no errors
770 * OC_STACK_ERROR - stack process error
773 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
774 OCResource *pointer = headResource;
776 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
777 VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
780 *numResources = *numResources + 1;
781 pointer = pointer->next;
787 * Get a resource handle by index.
789 * @param index - index of resource, 0 to Count - 1
792 * Resource handle - if found
793 * NULL - if not found
795 OCResourceHandle OCGetResourceHandle(uint8_t index) {
796 OCResource *pointer = headResource;
799 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
801 // Iterate through the list
802 while ((i < index) && pointer) {
804 pointer = pointer->next;
806 return (OCResourceHandle) pointer;
810 * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
813 * @param handle - handle of resource to be deleted
816 * OC_STACK_OK - no errors
817 * OC_STACK_ERROR - stack process error
819 OCStackResult OCDeleteResource(OCResourceHandle handle) {
820 OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
823 OC_LOG(ERROR, TAG, PCF("Resource not found"));
824 return OC_STACK_INVALID_PARAM;
827 if (deleteResource((OCResource *) handle) == 0) {
828 OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
829 return OC_STACK_ERROR;
836 * Get the URI of the resource specified by handle.
838 * @param handle - handle of resource
840 * URI string - if resource found
841 * NULL - resource not found
843 const char *OCGetResourceUri(OCResourceHandle handle) {
844 OCResource *resource;
845 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
847 resource = findResource((OCResource *) handle);
849 return resource->uri;
851 return (const char *) NULL;
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.
859 * @param handle - handle of resource
861 * property bitmap - if resource found
862 * NULL - resource not found
864 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
865 OCResource *resource;
866 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
868 resource = findResource((OCResource *) handle);
870 return resource->resourceProperties;
876 * Get the number of resource types of the resource.
878 * @param handle - handle of resource
879 * @param numResourceTypes - pointer to count variable
882 * OC_STACK_OK - no errors
883 * OC_STACK_ERROR - stack process error
885 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
886 uint8_t *numResourceTypes) {
887 OCResource *resource;
888 OCResourceType *pointer;
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);
894 *numResourceTypes = 0;
896 resource = findResource((OCResource *) handle);
898 pointer = resource->rsrcType;
900 *numResourceTypes = *numResourceTypes + 1;
901 pointer = pointer->next;
908 * Get name of resource type of the resource.
910 * @param handle - handle of resource
911 * @param index - index of resource, 0 to Count - 1
914 * resource type name - if resource found
915 * NULL - resource not found
917 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
918 OCResourceType *resourceType;
920 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
922 resourceType = findResourceTypeAtIndex(handle, index);
924 return resourceType->resourcetypename;
926 return (const char *) NULL;
932 * Get the number of resource interfaces of the resource.
934 * @param handle - handle of resource
935 * @param numResources - pointer to count variable
938 * OC_STACK_OK - no errors
939 * OC_STACK_ERROR - stack process error
942 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
943 uint8_t *numResourceInterfaces) {
944 OCResourceInterface *pointer;
945 OCResource *resource;
947 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
949 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
950 VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
952 *numResourceInterfaces = 0;
953 resource = findResource((OCResource *) handle);
955 pointer = resource->rsrcInterface;
957 *numResourceInterfaces = *numResourceInterfaces + 1;
958 pointer = pointer->next;
965 * Get name of resource interface of the resource.
967 * @param handle - handle of resource
968 * @param index - index of resource, 0 to Count - 1
971 * resource interface name - if resource found
972 * NULL - resource not found
974 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
975 OCResourceInterface *resourceInterface;
977 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
979 resourceInterface = findResourceInterfaceAtIndex(handle, index);
980 if (resourceInterface) {
981 return resourceInterface->name;
983 return (const char *) NULL;
987 * Get resource handle from the collection resource by index.
989 * @param collectionHandle - handle of collection resource
990 * @param index - index of contained resource, 0 to Count - 1
993 * handle to resource - if resource found
994 * NULL - resource not found
996 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
998 OCResource *resource;
1000 OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
1002 if (index >= MAX_CONTAINED_RESOURCES) {
1006 resource = findResource((OCResource *) collectionHandle);
1011 return resource->rsrcResources[index];
1015 * Bind an entity handler to the resource.
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
1020 * OC_STACK_OK - no errors
1021 * OC_STACK_ERROR - stack process error
1023 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
1024 OCEntityHandler entityHandler) {
1025 OCResource *resource;
1027 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
1029 // Validate parameters
1030 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1031 VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
1033 // Use the handle to find the resource in the resource linked list
1034 resource = findResource((OCResource *)handle);
1036 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1037 return OC_STACK_ERROR;
1041 resource->entityHandler = entityHandler;
1047 * Get the entity handler for a resource.
1049 * @param handle - handle of resource
1052 * entity handler - if resource found
1053 * NULL - resource not found
1055 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
1056 OCResource *resource;
1058 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
1060 // Use the handle to find the resource in the resource linked list
1061 resource = findResource((OCResource *)handle);
1063 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1068 return resource->entityHandler;
1072 * Notify observers that an observed value has changed.
1075 * @param handle - handle of resource
1078 * OC_STACK_OK - no errors
1079 * OC_STACK_ERROR - stack not initialized
1081 OCStackResult OCNotifyObservers(OCResourceHandle handle) {
1082 OCResource *resPtr = NULL;
1083 OCStackResult result;
1085 OC_LOG(INFO, TAG, PCF("Entering OCNotifyObservers"));
1087 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1089 // Verify that the resource exists
1090 resPtr = findResource ((OCResource *) handle);
1093 return OC_STACK_NO_RESOURCE;
1095 result = SendObserverNotification (handle, resPtr);
1100 //-----------------------------------------------------------------------------
1101 // Private internal function definitions
1102 //-----------------------------------------------------------------------------
1104 * Generate handle of OCDoResource invocation for callback management.
1106 static OCDoHandle GenerateInvocationHandle()
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]));
1113 OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1120 * Initialize resource data structures, variables, etc.
1122 void initResources() {
1123 TODO ("Do we need to create a resource for /oc/core???");
1124 // Init resource vars
1125 headResource = NULL;
1129 * Add a resource to the end of the linked list of resources.
1131 * @param resource - resource to be added
1133 void insertResource(OCResource *resource) {
1134 OCResource *pointer;
1136 if (!headResource) {
1137 headResource = resource;
1139 pointer = headResource;
1141 while (pointer->next) {
1142 pointer = pointer->next;
1144 pointer->next = resource;
1146 resource->next = NULL;
1150 * Find a resource in the linked list of resources.
1152 * @param resource - resource to be found
1154 * NULL - resource not found
1155 * pointer to resource - pointer to resource that was found in the linked list
1157 OCResource *findResource(OCResource *resource) {
1158 OCResource *pointer = headResource;
1161 if (pointer == resource) {
1164 pointer = pointer->next;
1169 void deleteAllResources()
1171 OCResource *pointer = headResource;
1176 temp = pointer->next;
1177 deleteResource(pointer);
1183 * Delete the resource from the linked list.
1185 * @param resource - resource to be deleted
1190 int deleteResource(OCResource *resource) {
1191 OCResource *prev = NULL;
1194 temp = headResource;
1196 if (temp == resource) {
1197 if (temp == headResource) {
1198 headResource = temp->next;
1200 prev->next = temp->next;
1202 deleteResourceElements(temp);
1215 * Delete all of the dynamically allocated elements that were created for the resource.
1217 * @param resource - specified resource
1219 void deleteResourceElements(OCResource *resource) {
1225 OCFree(resource->uri);
1227 // Delete resourcetype linked list
1228 deleteResourceType(resource->rsrcType);
1230 // Delete resourceinterface linked list
1231 deleteResourceInterface(resource->rsrcInterface);
1235 * Delete all of the dynamically allocated elements that were created for the resource type.
1237 * @param resourceType - specified resource type
1239 void deleteResourceType(OCResourceType *resourceType) {
1240 OCResourceType *pointer = resourceType;
1241 OCResourceType *next;
1244 next = pointer->next;
1245 OCFree(pointer->resourcetypename);
1252 * Delete all of the dynamically allocated elements that were created for the resource interface.
1254 * @param resourceInterface - specified resource interface
1256 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
1257 OCResourceInterface *pointer = resourceInterface;
1258 OCResourceInterface *next;
1261 next = pointer->next;
1262 OCFree(pointer->name);
1269 * Insert a resource type into a resource's resource type linked list.
1271 * @param resource - resource where resource type is to be inserted
1272 * @param resourceType - resource type to be inserted
1274 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
1275 OCResourceType *pointer;
1277 if (!resource->rsrcType) {
1278 resource->rsrcType = resourceType;
1280 pointer = resource->rsrcType;
1281 while (pointer->next) {
1282 pointer = pointer->next;
1284 pointer->next = resourceType;
1286 resourceType->next = NULL;
1290 * Get a resource type at the specified index within a resource.
1292 * @param handle - handle of resource
1293 * @param index - index of resource type
1296 * resourcetype - if found
1299 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
1300 OCResource *resource;
1301 OCResourceType *pointer;
1304 // Find the specified resource
1305 resource = findResource((OCResource *) handle);
1310 // Make sure a resource has a resourcetype
1311 if (!resource->rsrcType) {
1315 // Iterate through the list
1316 pointer = resource->rsrcType;
1318 while ((i < index) && pointer) {
1320 pointer = pointer->next;
1326 * Insert a resource interface into a resource's resource interface linked list.
1328 * @param resource - resource where resource interface is to be inserted
1329 * @param resourceInterface - resource interface to be inserted
1331 void insertResourceInterface(OCResource *resource,
1332 OCResourceInterface *resourceInterface) {
1333 OCResourceInterface *pointer;
1335 if (!resource->rsrcInterface) {
1336 resource->rsrcInterface = resourceInterface;
1338 pointer = resource->rsrcInterface;
1339 while (pointer->next) {
1340 pointer = pointer->next;
1342 pointer->next = resourceInterface;
1344 resourceInterface->next = NULL;
1348 * Get a resource interface at the specified index within a resource.
1350 * @param handle - handle of resource
1351 * @param index - index of resource interface
1354 * resourceinterface - if found
1357 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
1359 OCResource *resource;
1360 OCResourceInterface *pointer;
1363 // Find the specified resource
1364 resource = findResource((OCResource *) handle);
1369 // Make sure a resource has a resourceinterface
1370 if (!resource->rsrcInterface) {
1374 // Iterate through the list
1375 pointer = resource->rsrcInterface;
1377 while ((i < index) && pointer) {
1379 pointer = pointer->next;
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);
1390 void OCFree(void *ptr) {
1391 TODO ("This should be moved into an ocmalloc dir and implemented as a separate OC module");