1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH 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 "ocresource.h"
28 #include "occlientcb.h"
29 #include "ocobserve.h"
35 //-----------------------------------------------------------------------------
37 //-----------------------------------------------------------------------------
39 OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED
44 OC_PRESENCE_UNINITIALIZED = 0, OC_PRESENCE_INITIALIZED
48 //-----------------------------------------------------------------------------
50 //-----------------------------------------------------------------------------
51 static OCStackState stackState = OC_STACK_UNINITIALIZED;
53 OCResource *headResource = NULL;
55 static OCPresenceState presenceState = OC_PRESENCE_UNINITIALIZED;
56 static PresenceResource presenceResource;
57 uint8_t PresenceTimeOutSize = 4;
58 uint32_t PresenceTimeOut[] = {50, 75, 85, 95, 100};
62 OCDeviceEntityHandler defaultDeviceHandler;
64 //-----------------------------------------------------------------------------
66 //-----------------------------------------------------------------------------
67 #define TAG PCF("OCStack")
68 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
69 TAG, PCF(#arg " is NULL")); return (retVal); } }
71 //-----------------------------------------------------------------------------
72 // Internal API function
73 //-----------------------------------------------------------------------------
75 //This function will be called back by occoap layer when a request is received
76 OCStackResult HandleStackRequests(OCRequest * request)
78 OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
80 OCStackResult result = OC_STACK_ERROR;
81 ResourceHandling resHandling;
84 VERIFY_NON_NULL(request, ERROR, OC_STACK_ERROR);
85 VERIFY_NON_NULL(request->entityHandlerRequest, ERROR, OC_STACK_ERROR);
87 result = DetermineResourceHandling (request, &resHandling, &resource);
89 if (result == OC_STACK_OK)
91 result = BuildJSONResponse(resHandling, resource, request);
97 //This function will be called back by occoap layer when a response is received
98 void HandleStackResponses(OCResponse * response)
100 OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
101 OC_LOG(INFO, TAG, PCF("Entering HandleStackResponses (OCStack Layer)"));
103 if (response->cbNode)
105 OC_LOG(INFO, TAG, PCF("Calling into application address space"));
106 result = response->cbNode->callBack(response->cbNode->context,
107 response->cbNode->handle, response->clientResponse);
108 if (result == OC_STACK_DELETE_TRANSACTION ||
109 response->clientResponse->result == OC_STACK_COMM_ERROR ||
110 response->clientResponse->result == OC_STACK_RESOURCE_DELETED)
112 FindAndDeleteClientCB(response->cbNode);
117 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port)
120 unsigned char *itr, *coap;
121 uint8_t dotCount = 0;
125 /* search for scheme */
127 if (!isdigit((unsigned char) *ipAddrStr))
129 coap = (unsigned char *) OC_COAP_SCHEME;
130 while (*coap && tolower(*itr) == *coap)
139 if (isdigit((unsigned char) *ipAddrStr))
142 ipAddr[index] += *ipAddrStr - '0';
144 else if ((unsigned char) *ipAddrStr == '.')
156 if(*ipAddrStr == ':')
160 if (isdigit((unsigned char) *ipAddrStr))
163 *port += *ipAddrStr - '0';
174 if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
185 //-----------------------------------------------------------------------------
186 // Private internal function prototypes
187 //-----------------------------------------------------------------------------
189 static OCDoHandle GenerateInvocationHandle();
190 static OCStackResult initResources();
191 static void insertResource(OCResource *resource);
192 static OCResource *findResource(OCResource *resource);
193 static void insertResourceType(OCResource *resource,
194 OCResourceType *resourceType);
195 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
197 static void insertResourceInterface(OCResource *resource,
198 OCResourceInterface *resourceInterface);
199 static OCResourceInterface *findResourceInterfaceAtIndex(
200 OCResourceHandle handle, uint8_t index);
201 static void deleteResourceType(OCResourceType *resourceType);
202 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
203 static void deleteResourceElements(OCResource *resource);
204 static int deleteResource(OCResource *resource);
205 static void deleteAllResources();
206 static void incrementSequenceNumber(OCResource * resPtr);
207 static OCStackResult verifyUriQueryLength(const char * inputUri,
211 //-----------------------------------------------------------------------------
213 //-----------------------------------------------------------------------------
216 * Initialize the OC Stack. Must be called prior to starting the stack.
219 * IP Address of host device
221 * Port of host device
223 * Host device is client, server, or client-server
226 * OC_STACK_OK - no errors
227 * OC_STACK_ERROR - stack init error
229 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
231 OCStackResult result = OC_STACK_ERROR;
232 OC_LOG(INFO, TAG, PCF("Entering OCInit"));
236 OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
242 OC_LOG(INFO, TAG, PCF("Client mode"));
245 OC_LOG(INFO, TAG, PCF("Server mode"));
247 case OC_CLIENT_SERVER:
248 OC_LOG(INFO, TAG, PCF("Client-server mode"));
251 OC_LOG(ERROR, TAG, PCF("Invalid mode"));
252 return OC_STACK_ERROR;
257 defaultDeviceHandler = NULL;
259 // Make call to OCCoAP layer
260 result = OCInitCoAP(ipAddr, (uint16_t) port, myStackMode);
261 if (result == OC_STACK_OK)
263 stackState = OC_STACK_INITIALIZED;
265 // Initialize resource
266 if(result == OC_STACK_OK && myStackMode != OC_CLIENT)
268 result = initResources();
270 if(result != OC_STACK_OK)
272 OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
278 * Stop the OC stack. Use for a controlled shutdown.
280 * OC_STACK_OK - no errors
281 * OC_STACK_ERROR - stack not initialized
283 OCStackResult OCStop()
285 OCStackResult result = OC_STACK_ERROR;
287 OC_LOG(INFO, TAG, PCF("Entering OCStop"));
289 if (stackState != OC_STACK_INITIALIZED)
291 OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
292 return OC_STACK_ERROR;
295 // Free memory dynamically allocated for resources
296 deleteAllResources();
298 // Make call to OCCoAP layer
299 if (OCStopCoAP() == OC_STACK_OK)
301 // Remove all observers
302 DeleteObserverList();
303 // Remove all the client callbacks
304 DeleteClientCBList();
305 stackState = OC_STACK_UNINITIALIZED;
306 result = OC_STACK_OK;
308 result = OC_STACK_ERROR;
311 if (result != OC_STACK_OK) {
312 OC_LOG(ERROR, TAG, PCF("Stack stop error"));
319 * Verify the lengths of the URI and the query separately
321 * @param inputUri - Input URI and query.
322 * @param uriLen - The length of the initial URI with query.
324 * Note: The '?' that appears after the URI is not considered as
325 * a part of the query.
327 OCStackResult verifyUriQueryLength(const char *inputUri, uint16_t uriLen)
331 query = strchr (inputUri, '?');
335 if((query - inputUri) > MAX_URI_LENGTH)
337 return OC_STACK_INVALID_URI;
340 if((inputUri + uriLen - 1 - query) > MAX_QUERY_LENGTH)
342 return OC_STACK_INVALID_QUERY;
345 else if(uriLen > MAX_URI_LENGTH)
347 return OC_STACK_INVALID_URI;
353 * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
355 * @param handle - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
356 * @param method - @ref OCMethod to perform on the resource
357 * @param requiredUri - URI of the resource to interact with
358 * @param referenceUri - URI of the reference resource
359 * @param request - JSON encoded request
360 * @param qos - quality of service
361 * @param cbData - struct that contains asynchronous callback function that is invoked
362 * by the stack when discovery or resource interaction is complete
363 * @param options - The address of an array containing the vendor specific header
364 * header options to be sent with the request
365 * @param numOptions - Number of vendor specific header options to be included
368 * OC_STACK_OK - no errors
369 * OC_STACK_INVALID_CALLBACK - invalid callback function pointer
370 * OC_STACK_INVALID_METHOD - invalid resource method
371 * OC_STACK_INVALID_URI - invalid required or reference URI
374 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
375 const char *referenceUri, const char *request,
376 OCQualityOfService qos, OCCallbackData *cbData,
377 OCHeaderOption * options, uint8_t numOptions)
379 OCStackResult result = OC_STACK_ERROR;
381 ClientCB *clientCB = NULL;
382 unsigned char * requestUri = NULL;
385 OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
387 // Validate input parameters
388 VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
389 VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
391 TODO ("Need to form the final query by concatenating require and reference URI's");
392 VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
394 uint16_t uriLen = strlen(requiredUri);
396 // ToDo: We should also check if the requiredUri has a mutlicast address, then qos has to be OC_Low_QOS
403 case OC_REST_OBSERVE:
404 case OC_REST_OBSERVE_ALL:
405 case OC_REST_CANCEL_OBSERVE:
408 case OC_REST_PRESENCE:
412 result = OC_STACK_INVALID_METHOD;
416 if((result = verifyUriQueryLength(requiredUri, uriLen)) != OC_STACK_OK)
421 if((request) && (strlen(request) > MAX_REQUEST_LENGTH))
423 result = OC_STACK_INVALID_PARAM;
427 requestUri = (unsigned char *) OCMalloc(uriLen + 1);
430 memcpy(requestUri, requiredUri, (uriLen + 1));
434 result = OC_STACK_NO_MEMORY;
438 *handle = GenerateInvocationHandle();
441 result = OC_STACK_NO_MEMORY;
445 // Generate token which will be used by OCStack to match responses received
447 OCGenerateCoAPToken(&token);
449 if((result = AddClientCB(&clientCB, cbData, &token, *handle, method, requestUri)) != OC_STACK_OK)
451 result = OC_STACK_NO_MEMORY;
455 // Make call to OCCoAP layer
456 result = OCDoCoAPResource(method, qos, &token, requiredUri, request, options, numOptions);
459 if (result != OC_STACK_OK)
461 OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
462 FindAndDeleteClientCB(clientCB);
468 * Cancel a request associated with a specific @ref OCDoResource invocation.
470 * @param handle - Used to identify a specific OCDoResource invocation.
471 * @param qos - used to specify Quality of Service (read below for more info)
472 * @param options- used to specify vendor specific header options when sending
473 * explicit observe cancellation
474 * @param numOptions- Number of header options to be included
477 * OC_STACK_OK - No errors; Success
478 * OC_STACK_INVALID_PARAM - The handle provided is invalid.
480 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
481 uint8_t numOptions) {
483 * This ftn is implemented one of two ways in the case of observation:
485 * 1. qos == OC_NON_CONFIRMABLE. When observe is unobserved..
486 * Remove the callback associated on client side.
487 * When the next notification comes in from server,
488 * reply with RESET message to server.
489 * Keep in mind that the server will react to RESET only
490 * if the last notification was sent ans CON
492 * 2. qos == OC_CONFIRMABLE. When OCCancel is called,
493 * and it is associated with an observe request
494 * (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
495 * Send CON Observe request to server with
496 * observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
497 * Remove the callback associated on client side.
499 OCStackResult ret = OC_STACK_OK;
502 return OC_STACK_INVALID_PARAM;
505 OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
507 ClientCB *clientCB = GetClientCB(NULL, handle, NULL);
510 switch (clientCB->method)
512 case OC_REST_OBSERVE:
513 case OC_REST_OBSERVE_ALL:
514 if(qos == OC_HIGH_QOS)
516 ret = OCDoCoAPResource(OC_REST_CANCEL_OBSERVE, qos,
517 &(clientCB->token), (const char *) clientCB->requestUri, NULL, options,
522 FindAndDeleteClientCB(clientCB);
526 case OC_REST_PRESENCE:
527 FindAndDeleteClientCB(clientCB);
531 return OC_STACK_INVALID_METHOD;
537 OCStackResult OCProcessPresence()
539 OCStackResult result = OC_STACK_OK;
540 uint8_t ipAddr[4] = { 0 };
543 OC_LOG(INFO, TAG, PCF("Entering RequestPresence"));
544 ClientCB* cbNode = NULL;
546 OCClientResponse clientResponse;
547 OCResponse * response = NULL;
549 LL_FOREACH(cbList, cbNode) {
550 if(OC_REST_PRESENCE == cbNode->method)
554 uint32_t now = GetTime(0);
555 OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
556 OC_LOG_V(DEBUG, TAG, "----------------current ticks %d", now);
557 if(cbNode->presence->TTLlevel != PresenceTimeOutSize){
558 OC_LOG_V(DEBUG, TAG, "----------------timeout ticks %d",
559 cbNode->presence->timeOut[cbNode->presence->TTLlevel]);
561 if(cbNode->presence->TTLlevel >= PresenceTimeOutSize)
563 OC_LOG(DEBUG, TAG, "----------------No more timeout ticks");
564 if (ParseIPv4Address( cbNode->requestUri, ipAddr, &port))
566 OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
568 result = FormOCClientResponse(&clientResponse, OC_STACK_PRESENCE_STOPPED,
569 (OCDevAddr *) &dst, 0, NULL);
570 if(result != OC_STACK_OK)
574 result = FormOCResponse(&response, cbNode, 0, &clientResponse);
575 if(result != OC_STACK_OK)
582 result = OC_STACK_INVALID_IP;
585 HandleStackResponses(response);
587 if(now >= cbNode->presence->timeOut[cbNode->presence->TTLlevel])
589 OC_LOG(DEBUG, TAG, "time to test server presence ==========");
591 OCGenerateCoAPToken(&token);
592 result = OCDoCoAPResource(OC_REST_GET, OC_LOW_QOS,
593 &token, (const char *)cbNode->requestUri, NULL, NULL, 0);
594 if(result != OC_STACK_OK)
598 cbNode->presence->TTLlevel++;
599 OC_LOG_V(DEBUG, TAG, "----------------moving to TTL level %d", cbNode->presence->TTLlevel);
605 if (result != OC_STACK_OK)
607 OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
614 * Called in main loop of OC client or server. Allows low-level processing of
618 * OC_STACK_OK - no errors
619 * OC_STACK_ERROR - stack process error
621 OCStackResult OCProcess() {
623 OC_LOG(INFO, TAG, PCF("Entering OCProcess"));
634 * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out
635 * presence notifications to clients via multicast. Once this API has been called with a success,
636 * clients may query for this server's presence and this server's stack will respond via multicast.
638 * Server can call this function when it comes online for the first time, or when it comes back
639 * online from offline mode, or when it re enters network.
641 * @param ttl - Time To Live in seconds
642 * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
645 * OC_STACK_OK - No errors; Success
647 OCStackResult OCStartPresence(const uint32_t ttl)
649 OCChangeResourceProperty(
650 &(((OCResource *)presenceResource.handle)->resourceProperties),
655 presenceResource.presenceTTL = ttl;
658 if(OC_PRESENCE_UNINITIALIZED == presenceState)
660 OCDevAddr multiCastAddr;
663 presenceState = OC_PRESENCE_INITIALIZED;
664 OCGenerateCoAPToken(&token);
665 OCBuildIPv4Address(224, 0, 1, 187, 5683, &multiCastAddr);
666 //add the presence observer
667 AddObserver(OC_PRESENCE_URI, NULL, 0, &token, &multiCastAddr,
668 (OCResource *)presenceResource.handle, OC_LOW_QOS);
671 // Each time OCStartPresence is called
672 // a different random 32-bit integer number is used
673 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
675 return OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
679 * When operating in @ref OCServer or @ref OCClientServer mode, this API will stop sending out
680 * presence notifications to clients via multicast. Once this API has been called with a success,
681 * this server's stack will not respond to clients querying for this server's presence.
683 * Server can call this function when it is terminating, going offline, or when going
687 * OC_STACK_OK - No errors; Success
689 OCStackResult OCStopPresence()
691 OCStackResult result = OC_STACK_ERROR;
692 //make resource inactive
693 result = OCChangeResourceProperty(
694 &(((OCResource *) presenceResource.handle)->resourceProperties),
696 result = OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
702 OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandler)
704 defaultDeviceHandler = entityHandler;
712 * @param handle - pointer to handle to newly created resource. Set by ocstack. Used to refer to resource
713 * @param resourceTypeName - name of resource type. Example: "core.led"
714 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
715 * @param uri - URI of the resource. Example: "/a/led"
716 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
717 * NULL for default entity handler
718 * @param resourceProperties - properties supported by resource. Example: OC_DISCOVERABLE|OC_OBSERVABLE
721 * OC_STACK_OK - no errors
722 * OC_STACK_ERROR - stack process error
724 OCStackResult OCCreateResource(OCResourceHandle *handle,
725 const char *resourceTypeName,
726 const char *resourceInterfaceName,
727 const char *uri, OCEntityHandler entityHandler,
728 uint8_t resourceProperties) {
730 OCResource *pointer = NULL;
733 OCStackResult result = OC_STACK_ERROR;
735 OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
737 if(myStackMode == OC_CLIENT)
741 // Validate parameters
742 // Is it presented during resource discovery?
743 if (!handle || !resourceTypeName || !uri) {
744 OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
745 return OC_STACK_INVALID_PARAM;
748 if(!resourceInterfaceName || strlen(resourceInterfaceName) == 0) {
749 resourceInterfaceName = OC_RSRVD_INTERFACE_DEFAULT;
752 // Make sure resourceProperties bitmask has allowed properties specified
753 if (resourceProperties
754 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE)) {
755 OC_LOG(ERROR, TAG, PCF("Invalid property"));
756 return OC_STACK_INVALID_PARAM;
759 // If the headResource is NULL, then no resources have been created...
760 pointer = headResource;
762 // At least one resources is in the resource list, so we need to search for
763 // repeated URLs, which are not allowed. If a repeat is found, exit with an error
765 if (strcmp(uri, pointer->uri) == 0) {
766 OC_LOG(ERROR, TAG, PCF("URI already in use"));
767 return OC_STACK_INVALID_PARAM;
769 pointer = pointer->next;
772 // Create the pointer and insert it into the resource list
773 pointer = (OCResource *) OCMalloc(sizeof(OCResource));
777 memset(pointer, 0, sizeof(OCResource));
778 pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
780 insertResource(pointer);
783 size = strlen(uri) + 1;
784 str = (char *) OCMalloc(size);
788 strncpy(str, uri, size);
791 // Set properties. Set OC_ACTIVE
792 pointer->resourceProperties = (OCResourceProperty) (resourceProperties
795 // Add the resourcetype to the resource
796 result = OCBindResourceTypeToResource((OCResourceHandle) pointer,
798 if (result != OC_STACK_OK) {
799 OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
803 // Add the resourceinterface to the resource
804 result = OCBindResourceInterfaceToResource((OCResourceHandle) pointer,
805 resourceInterfaceName);
806 if (result != OC_STACK_OK) {
807 OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
811 // If an entity handler has been passed, attach it to the newly created
812 // resource. Otherwise, set the default entity handler.
815 pointer->entityHandler = entityHandler;
819 pointer->entityHandler = defaultResourceEHandler;
823 result = OC_STACK_OK;
826 if(presenceResource.handle)
828 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
829 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
833 if (result != OC_STACK_OK)
835 // Deep delete of resource and other dynamic elements that it contains
836 deleteResource(pointer);
843 * Add a resource to a collection resource.
845 * @param collectionHandle - handle to the collection resource
846 * @param resourceHandle - handle to resource to be added to the collection resource
849 * OC_STACK_OK - no errors
850 * OC_STACK_ERROR - stack process error
851 * OC_STACK_INVALID_PARAM - invalid collectionhandle
853 OCStackResult OCBindResource(
854 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
855 OCResource *resource;
858 OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
860 // Validate parameters
861 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
862 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
863 // Container cannot contain itself
864 if (collectionHandle == resourceHandle) {
865 OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
866 return OC_STACK_INVALID_PARAM;
869 // Use the handle to find the resource in the resource linked list
870 resource = findResource((OCResource *) collectionHandle);
872 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
873 return OC_STACK_INVALID_PARAM;
876 // Look for an open slot to add add the child resource.
877 // If found, add it and return success
878 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
879 if (!resource->rsrcResources[i]) {
880 resource->rsrcResources[i] = (OCResource *) resourceHandle;
881 OC_LOG(INFO, TAG, PCF("resource bound"));
887 if(presenceResource.handle)
889 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
890 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
894 // Unable to add resourceHandle, so return error
895 return OC_STACK_ERROR;
899 * Remove a resource from a collection resource.
901 * @param collectionHandle - handle to the collection resource
902 * @param resourceHandle - handle to resource to be added to the collection resource
905 * OC_STACK_OK - no errors
906 * OC_STACK_ERROR - stack process error
907 * OC_STACK_INVALID_PARAM - invalid collectionHandle
909 OCStackResult OCUnBindResource(
910 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
911 OCResource *resource;
914 OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
916 // Validate parameters
917 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
918 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
919 // Container cannot contain itself
920 if (collectionHandle == resourceHandle) {
921 OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
922 return OC_STACK_INVALID_PARAM;
925 // Use the handle to find the resource in the resource linked list
926 resource = findResource((OCResource *) collectionHandle);
928 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
929 return OC_STACK_INVALID_PARAM;
932 // Look for an open slot to add add the child resource.
933 // If found, add it and return success
934 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
935 if (resourceHandle == resource->rsrcResources[i]) {
936 resource->rsrcResources[i] = (OCResource *) NULL;
937 OC_LOG(INFO, TAG, PCF("resource unbound"));
942 OC_LOG(INFO, TAG, PCF("resource not found in collection"));
945 if(presenceResource.handle)
947 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
948 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
952 // Unable to add resourceHandle, so return error
953 return OC_STACK_ERROR;
958 * Bind a resourcetype to a resource.
960 * @param handle - handle to the resource
961 * @param resourceTypeName - name of resource type. Example: "core.led"
964 * OC_STACK_OK - no errors
965 * OC_STACK_ERROR - stack process error
967 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
968 const char *resourceTypeName) {
970 OCResourceType *pointer = NULL;
973 OCResource *resource;
974 OCStackResult result = OC_STACK_ERROR;
976 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceTypeToResource"));
978 // Validate parameters
979 VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
980 // TODO: Does resource attribute resentation really have to be maintained in stack?
981 // Is it presented during resource discovery?
983 // Make sure resource exists
984 resource = findResource((OCResource *) handle);
986 OC_LOG(ERROR, TAG, PCF("Resource not found"));
987 return OC_STACK_ERROR;
990 TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
992 // Create the resourcetype and insert it into the resource list
993 pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
997 memset(pointer, 0, sizeof(OCResourceType));
999 // Set the resourceTypeName
1000 size = strlen(resourceTypeName) + 1;
1001 str = (char *) OCMalloc(size);
1005 strncpy(str, resourceTypeName, size);
1006 pointer->resourcetypename = str;
1008 insertResourceType(resource, pointer);
1009 result = OC_STACK_OK;
1011 #ifdef WITH_PRESENCE
1012 if(presenceResource.handle)
1014 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1015 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1019 exit: if (result != OC_STACK_OK) {
1027 * Bind a resourceinterface to a resource.
1029 * @param handle - handle to the resource
1030 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
1033 * OC_STACK_OK - no errors
1034 * OC_STACK_ERROR - stack process error
1036 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
1037 const char *resourceInterfaceName) {
1039 OCResourceInterface *pointer = NULL;
1042 OCResource *resource;
1043 OCStackResult result = OC_STACK_ERROR;
1045 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceInterfaceToResource"));
1047 // Validate parameters
1048 VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
1050 // Make sure resource exists
1051 resource = findResource((OCResource *) handle);
1053 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1054 return OC_STACK_INVALID_PARAM;
1057 TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
1059 // Create the resourceinterface and insert it into the resource list
1060 pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
1064 memset(pointer, 0, sizeof(OCResourceInterface));
1066 // Set the resourceinterface name
1067 size = strlen(resourceInterfaceName) + 1;
1068 str = (char *) OCMalloc(size);
1072 strncpy(str, resourceInterfaceName, size);
1073 pointer->name = str;
1075 // Bind the resourceinterface to the resource
1076 insertResourceInterface(resource, pointer);
1078 result = OC_STACK_OK;
1080 #ifdef WITH_PRESENCE
1081 if(presenceResource.handle)
1083 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1084 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1088 exit: if (result != OC_STACK_OK) {
1096 * Get the number of resources that have been created in the stack.
1098 * @param numResources - pointer to count variable
1101 * OC_STACK_OK - no errors
1102 * OC_STACK_ERROR - stack process error
1105 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
1106 OCResource *pointer = headResource;
1108 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
1109 VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
1112 *numResources = *numResources + 1;
1113 pointer = pointer->next;
1119 * Get a resource handle by index.
1121 * @param index - index of resource, 0 to Count - 1
1124 * Resource handle - if found
1125 * NULL - if not found
1127 OCResourceHandle OCGetResourceHandle(uint8_t index) {
1128 OCResource *pointer = headResource;
1131 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
1133 // Iterate through the list
1134 while ((i < index) && pointer) {
1136 pointer = pointer->next;
1138 return (OCResourceHandle) pointer;
1142 * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
1145 * @param handle - handle of resource to be deleted
1148 * OC_STACK_OK - no errors
1149 * OC_STACK_ERROR - stack process error
1150 * OC_STACK_NO_RESOURCE - resource not found
1151 * OC_STACK_INVALID_PARAM - invalid param
1153 OCStackResult OCDeleteResource(OCResourceHandle handle) {
1154 OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
1157 OC_LOG(ERROR, TAG, PCF("Invalid param"));
1158 return OC_STACK_INVALID_PARAM;
1161 OCResource *resource = findResource((OCResource *) handle);
1162 if (resource == NULL) {
1163 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1164 return OC_STACK_NO_RESOURCE;
1167 if (deleteResource((OCResource *) handle) == 0) {
1168 OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
1169 return OC_STACK_ERROR;
1176 * Get the URI of the resource specified by handle.
1178 * @param handle - handle of resource
1180 * URI string - if resource found
1181 * NULL - resource not found
1183 const char *OCGetResourceUri(OCResourceHandle handle) {
1184 OCResource *resource;
1185 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
1187 resource = findResource((OCResource *) handle);
1189 return resource->uri;
1191 return (const char *) NULL;
1195 * Get the properties of the resource specified by handle.
1196 * NOTE: that after a resource is created, the OC_ACTIVE property is set
1197 * for the resource by the stack.
1199 * @param handle - handle of resource
1201 * property bitmap - if resource found
1202 * NULL - resource not found
1204 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
1205 OCResource *resource;
1206 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
1208 resource = findResource((OCResource *) handle);
1210 return resource->resourceProperties;
1216 * Get the number of resource types of the resource.
1218 * @param handle - handle of resource
1219 * @param numResourceTypes - pointer to count variable
1222 * OC_STACK_OK - no errors
1223 * OC_STACK_ERROR - stack process error
1225 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
1226 uint8_t *numResourceTypes) {
1227 OCResource *resource;
1228 OCResourceType *pointer;
1230 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
1231 VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
1232 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1234 *numResourceTypes = 0;
1236 resource = findResource((OCResource *) handle);
1238 pointer = resource->rsrcType;
1240 *numResourceTypes = *numResourceTypes + 1;
1241 pointer = pointer->next;
1248 * Get name of resource type of the resource.
1250 * @param handle - handle of resource
1251 * @param index - index of resource, 0 to Count - 1
1254 * resource type name - if resource found
1255 * NULL - resource not found
1257 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
1258 OCResourceType *resourceType;
1260 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
1262 resourceType = findResourceTypeAtIndex(handle, index);
1264 return resourceType->resourcetypename;
1266 return (const char *) NULL;
1272 * Get the number of resource interfaces of the resource.
1274 * @param handle - handle of resource
1275 * @param numResources - pointer to count variable
1278 * OC_STACK_OK - no errors
1279 * OC_STACK_ERROR - stack process error
1281 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
1282 uint8_t *numResourceInterfaces) {
1283 OCResourceInterface *pointer;
1284 OCResource *resource;
1286 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
1288 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1289 VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
1291 *numResourceInterfaces = 0;
1292 resource = findResource((OCResource *) handle);
1294 pointer = resource->rsrcInterface;
1296 *numResourceInterfaces = *numResourceInterfaces + 1;
1297 pointer = pointer->next;
1304 * Get name of resource interface of the resource.
1306 * @param handle - handle of resource
1307 * @param index - index of resource, 0 to Count - 1
1310 * resource interface name - if resource found
1311 * NULL - resource not found
1313 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
1314 OCResourceInterface *resourceInterface;
1316 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
1318 resourceInterface = findResourceInterfaceAtIndex(handle, index);
1319 if (resourceInterface) {
1320 return resourceInterface->name;
1322 return (const char *) NULL;
1326 * Get resource handle from the collection resource by index.
1328 * @param collectionHandle - handle of collection resource
1329 * @param index - index of contained resource, 0 to Count - 1
1332 * handle to resource - if resource found
1333 * NULL - resource not found
1335 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
1337 OCResource *resource;
1339 OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
1341 if (index >= MAX_CONTAINED_RESOURCES) {
1345 resource = findResource((OCResource *) collectionHandle);
1350 return resource->rsrcResources[index];
1354 * Bind an entity handler to the resource.
1356 * @param handle - handle to the resource that the contained resource is to be bound
1357 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1359 * OC_STACK_OK - no errors
1360 * OC_STACK_ERROR - stack process error
1362 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
1363 OCEntityHandler entityHandler) {
1364 OCResource *resource;
1366 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
1368 // Validate parameters
1369 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1370 //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
1372 // Use the handle to find the resource in the resource linked list
1373 resource = findResource((OCResource *)handle);
1375 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1376 return OC_STACK_ERROR;
1380 resource->entityHandler = entityHandler;
1382 #ifdef WITH_PRESENCE
1383 if(presenceResource.handle)
1385 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1386 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1394 * Get the entity handler for a resource.
1396 * @param handle - handle of resource
1399 * entity handler - if resource found
1400 * NULL - resource not found
1402 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
1403 OCResource *resource;
1405 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
1407 // Use the handle to find the resource in the resource linked list
1408 resource = findResource((OCResource *)handle);
1410 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1415 return resource->entityHandler;
1418 void incrementSequenceNumber(OCResource * resPtr)
1420 // Increment the sequence number
1421 resPtr->sequenceNum += 1;
1422 if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
1424 resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
1430 * Notify observers that an observed value has changed.
1432 * @param handle - handle of resource
1435 * OC_STACK_OK - no errors
1436 * OC_STACK_NO_RESOURCE - invalid resource handle
1437 * OC_STACK_NO_OBSERVERS - no more observers intrested in resource
1439 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
1440 OCResource *resPtr = NULL;
1441 OCStackResult result;
1442 OCMethod method = OC_REST_NOMETHOD;
1443 uint32_t maxAge = 0;
1445 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
1447 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1449 // Verify that the resource exists
1450 resPtr = findResource ((OCResource *) handle);
1451 if (NULL == resPtr || myStackMode == OC_CLIENT)
1453 return OC_STACK_NO_RESOURCE;
1455 #ifdef WITH_PRESENCE
1456 if(strcmp(resPtr->uri, OC_PRESENCE_URI))
1459 //only increment in the case of regular observing (not presence)
1460 incrementSequenceNumber(resPtr);
1461 method = OC_REST_OBSERVE;
1463 #ifdef WITH_PRESENCE
1467 method = OC_REST_PRESENCE;
1468 if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
1470 maxAge = presenceResource.presenceTTL;
1479 result = SendObserverNotification (method, resPtr, maxAge, qos);
1485 OCNotifyListOfObservers (OCResourceHandle handle,
1486 OCObservationId *obsIdList,
1487 uint8_t numberOfIds,
1488 unsigned char *notificationJSONPayload,
1489 OCQualityOfService qos)
1491 OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
1493 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1494 VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
1495 VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
1497 uint8_t numIds = numberOfIds;
1498 ResourceObserver *observation;
1499 OCResource *resPtr = NULL;
1500 uint32_t maxAge = 0;
1501 unsigned char bufNotify[MAX_RESPONSE_LENGTH] = {0};
1502 unsigned char *currPtr;
1503 uint8_t numSentNotification = 0;
1505 // Verify the notification payload length does not exceed the maximim
1506 // the stack can handle
1507 if ((strlen((char *)notificationJSONPayload) +
1508 OC_JSON_PREFIX_LEN + OC_JSON_SUFFIX_LEN) > MAX_RESPONSE_LENGTH)
1510 OC_LOG(INFO, TAG, PCF("Observe notification message length too long"));
1511 return OC_STACK_ERROR;
1514 // Verify that the resource exists
1515 resPtr = findResource ((OCResource *) handle);
1516 if (NULL == resPtr || myStackMode == OC_CLIENT)
1518 return OC_STACK_NO_RESOURCE;
1522 incrementSequenceNumber(resPtr);
1523 //TODO: we should allow the serve to define thisl
1529 OC_LOG_V(INFO, TAG, "Need to notify observation id %d", *obsIdList);
1531 observation = GetObserverUsingId (*obsIdList);
1534 // Found observation - verify if it matches the resource handle
1535 if (observation->resource == resPtr)
1537 strcpy((char*)bufNotify, OC_JSON_PREFIX);
1538 currPtr = bufNotify + OC_JSON_PREFIX_LEN;
1539 memcpy (currPtr, notificationJSONPayload, strlen((char *)notificationJSONPayload));
1540 currPtr += strlen((char *)notificationJSONPayload);
1541 strcpy((char*)currPtr, OC_JSON_SUFFIX);
1543 // send notifications based on the qos of the request
1544 // The qos passed as a parameter overrides what the client requested
1545 // If we want the client preference taking high priority add:
1546 // QoS = resourceObserver->qos;
1547 if(qos == OC_NA_QOS){
1548 qos = observation->qos;
1550 if(qos != OC_HIGH_QOS)
1552 OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
1553 observation->lowQosCount);
1554 if(observation->forceHighQos \
1555 || observation->lowQosCount >= MAX_OBSERVER_NON_COUNT)
1557 observation->lowQosCount = 0;
1558 // at some point we have to to send CON to check on the
1559 // availability of observer
1560 OC_LOG(INFO, TAG, PCF("This time we are sending the \
1561 notification as High qos"));
1566 observation->lowQosCount++;
1569 OCSendCoAPNotification (observation->resUri, observation->addr,
1570 qos, &(observation->token),
1571 bufNotify, resPtr, maxAge);
1572 numSentNotification++;
1578 if(numSentNotification == numberOfIds)
1582 else if(numSentNotification == 0)
1584 return OC_STACK_NO_OBSERVERS;
1588 //TODO: we need to signal that not every one in the
1589 // list got an update, should we also indicate who did not receive on?
1594 //-----------------------------------------------------------------------------
1595 // Private internal function definitions
1596 //-----------------------------------------------------------------------------
1598 * Generate handle of OCDoResource invocation for callback management.
1600 static OCDoHandle GenerateInvocationHandle()
1602 OCDoHandle handle = NULL;
1603 // Generate token here, it will be deleted when the transaction is deleted
1604 handle = (OCDoHandle) malloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1607 OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1612 #ifdef WITH_PRESENCE
1613 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
1614 OCResourceProperty resourceProperties, uint8_t enable)
1616 if (resourceProperties
1617 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
1618 OC_LOG(ERROR, TAG, PCF("Invalid property"));
1619 return OC_STACK_INVALID_PARAM;
1623 *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
1627 *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
1634 * Initialize resource data structures, variables, etc.
1636 OCStackResult initResources() {
1637 OCStackResult result = OC_STACK_OK;
1638 // Init application resource vars
1639 headResource = NULL;
1640 // Init Virtual Resources
1641 #ifdef WITH_PRESENCE
1642 presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
1643 //presenceResource.token = OCGenerateCoAPToken();
1644 result = OCCreateResource(&presenceResource.handle,
1650 //make resource inactive
1651 result = OCChangeResourceProperty(
1652 &(((OCResource *) presenceResource.handle)->resourceProperties),
1659 * Add a resource to the end of the linked list of resources.
1661 * @param resource - resource to be added
1663 void insertResource(OCResource *resource) {
1664 OCResource *pointer;
1666 if (!headResource) {
1667 headResource = resource;
1669 pointer = headResource;
1671 while (pointer->next) {
1672 pointer = pointer->next;
1674 pointer->next = resource;
1676 resource->next = NULL;
1680 * Find a resource in the linked list of resources.
1682 * @param resource - resource to be found
1684 * NULL - resource not found
1685 * pointer to resource - pointer to resource that was found in the linked list
1687 OCResource *findResource(OCResource *resource) {
1688 OCResource *pointer = headResource;
1691 if (pointer == resource) {
1694 pointer = pointer->next;
1699 void deleteAllResources()
1701 OCResource *pointer = headResource;
1706 temp = pointer->next;
1707 deleteResource(pointer);
1713 * Delete the resource from the linked list.
1715 * @param resource - resource to be deleted
1720 int deleteResource(OCResource *resource) {
1721 OCResource *prev = NULL;
1724 temp = headResource;
1726 if (temp == resource) {
1727 // Invalidate all Resource Properties.
1728 resource->resourceProperties = (OCResourceProperty) 0;
1729 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
1731 #ifdef WITH_PRESENCE
1732 if(presenceResource.handle)
1734 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1735 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1739 if (temp == headResource) {
1740 headResource = temp->next;
1742 prev->next = temp->next;
1745 deleteResourceElements(temp);
1758 * Delete all of the dynamically allocated elements that were created for the resource.
1760 * @param resource - specified resource
1762 void deleteResourceElements(OCResource *resource) {
1768 OCFree(resource->uri);
1770 // Delete resourcetype linked list
1771 deleteResourceType(resource->rsrcType);
1773 // Delete resourceinterface linked list
1774 deleteResourceInterface(resource->rsrcInterface);
1778 * Delete all of the dynamically allocated elements that were created for the resource type.
1780 * @param resourceType - specified resource type
1782 void deleteResourceType(OCResourceType *resourceType) {
1783 OCResourceType *pointer = resourceType;
1784 OCResourceType *next;
1787 next = pointer->next;
1788 OCFree(pointer->resourcetypename);
1795 * Delete all of the dynamically allocated elements that were created for the resource interface.
1797 * @param resourceInterface - specified resource interface
1799 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
1800 OCResourceInterface *pointer = resourceInterface;
1801 OCResourceInterface *next;
1804 next = pointer->next;
1805 OCFree(pointer->name);
1812 * Insert a resource type into a resource's resource type linked list.
1814 * @param resource - resource where resource type is to be inserted
1815 * @param resourceType - resource type to be inserted
1817 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
1818 OCResourceType *pointer;
1820 if (!resource->rsrcType) {
1821 resource->rsrcType = resourceType;
1823 pointer = resource->rsrcType;
1824 while (pointer->next) {
1825 pointer = pointer->next;
1827 pointer->next = resourceType;
1829 resourceType->next = NULL;
1833 * Get a resource type at the specified index within a resource.
1835 * @param handle - handle of resource
1836 * @param index - index of resource type
1839 * resourcetype - if found
1842 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
1843 OCResource *resource;
1844 OCResourceType *pointer;
1847 // Find the specified resource
1848 resource = findResource((OCResource *) handle);
1853 // Make sure a resource has a resourcetype
1854 if (!resource->rsrcType) {
1858 // Iterate through the list
1859 pointer = resource->rsrcType;
1861 while ((i < index) && pointer) {
1863 pointer = pointer->next;
1869 * Insert a resource interface into a resource's resource interface linked list.
1871 * @param resource - resource where resource interface is to be inserted
1872 * @param resourceInterface - resource interface to be inserted
1874 void insertResourceInterface(OCResource *resource,
1875 OCResourceInterface *resourceInterface) {
1876 OCResourceInterface *pointer;
1878 if (!resource->rsrcInterface) {
1879 resource->rsrcInterface = resourceInterface;
1881 pointer = resource->rsrcInterface;
1882 while (pointer->next) {
1883 pointer = pointer->next;
1885 pointer->next = resourceInterface;
1887 resourceInterface->next = NULL;
1891 * Get a resource interface at the specified index within a resource.
1893 * @param handle - handle of resource
1894 * @param index - index of resource interface
1897 * resourceinterface - if found
1900 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
1902 OCResource *resource;
1903 OCResourceInterface *pointer;
1906 // Find the specified resource
1907 resource = findResource((OCResource *) handle);
1912 // Make sure a resource has a resourceinterface
1913 if (!resource->rsrcInterface) {
1917 // Iterate through the list
1918 pointer = resource->rsrcInterface;
1920 while ((i < index) && pointer) {
1922 pointer = pointer->next;