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)) {
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);
845 * Create a resource. with host ip address for remote resource
847 * @param handle - pointer to handle to newly created resource. Set by ocstack.
848 * Used to refer to resource
849 * @param resourceTypeName - name of resource type. Example: "core.led"
850 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
851 * @param host - HOST address of the remote resource. Example: "coap://xxx.xxx.xxx.xxx:xxxxx"
852 * @param uri - URI of the resource. Example: "/a/led"
853 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
854 * NULL for default entity handler
855 * @param resourceProperties - properties supported by resource.
856 * Example: OC_DISCOVERABLE|OC_OBSERVABLE
859 * OC_STACK_OK - no errors
860 * OC_STACK_ERROR - stack process error
863 OCStackResult OCCreateResourceWithHost(OCResourceHandle *handle,
864 const char *resourceTypeName,
865 const char *resourceInterfaceName,
868 OCEntityHandler entityHandler,
869 uint8_t resourceProperties)
873 OCStackResult result = OC_STACK_ERROR;
875 result = OCCreateResource(handle, resourceTypeName, resourceInterfaceName,
876 uri, entityHandler, resourceProperties);
878 if (result != OC_STACK_ERROR)
881 size = strlen(host) + 1;
882 str = (char *) OCMalloc(size);
885 return OC_STACK_ERROR;
887 strncpy(str, host, size);
888 ((OCResource *) *handle)->host = str;
895 * Add a resource to a collection resource.
897 * @param collectionHandle - handle to the collection resource
898 * @param resourceHandle - handle to resource to be added to the collection resource
901 * OC_STACK_OK - no errors
902 * OC_STACK_ERROR - stack process error
903 * OC_STACK_INVALID_PARAM - invalid collectionhandle
905 OCStackResult OCBindResource(
906 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
907 OCResource *resource;
910 OC_LOG(INFO, TAG, PCF("Entering OCBindResource"));
912 // Validate parameters
913 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
914 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
915 // Container cannot contain itself
916 if (collectionHandle == resourceHandle) {
917 OC_LOG(ERROR, TAG, PCF("Added handle equals collection handle"));
918 return OC_STACK_INVALID_PARAM;
921 // Use the handle to find the resource in the resource linked list
922 resource = findResource((OCResource *) collectionHandle);
924 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
925 return OC_STACK_INVALID_PARAM;
928 // Look for an open slot to add add the child resource.
929 // If found, add it and return success
930 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
931 if (!resource->rsrcResources[i]) {
932 resource->rsrcResources[i] = (OCResource *) resourceHandle;
933 OC_LOG(INFO, TAG, PCF("resource bound"));
939 if(presenceResource.handle)
941 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
942 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
946 // Unable to add resourceHandle, so return error
947 return OC_STACK_ERROR;
951 * Remove a resource from a collection resource.
953 * @param collectionHandle - handle to the collection resource
954 * @param resourceHandle - handle to resource to be added to the collection resource
957 * OC_STACK_OK - no errors
958 * OC_STACK_ERROR - stack process error
959 * OC_STACK_INVALID_PARAM - invalid collectionHandle
961 OCStackResult OCUnBindResource(
962 OCResourceHandle collectionHandle, OCResourceHandle resourceHandle) {
963 OCResource *resource;
966 OC_LOG(INFO, TAG, PCF("Entering OCUnBindResource"));
968 // Validate parameters
969 VERIFY_NON_NULL(collectionHandle, ERROR, OC_STACK_ERROR);
970 VERIFY_NON_NULL(resourceHandle, ERROR, OC_STACK_ERROR);
971 // Container cannot contain itself
972 if (collectionHandle == resourceHandle) {
973 OC_LOG(ERROR, TAG, PCF("removing handle equals collection handle"));
974 return OC_STACK_INVALID_PARAM;
977 // Use the handle to find the resource in the resource linked list
978 resource = findResource((OCResource *) collectionHandle);
980 OC_LOG(ERROR, TAG, PCF("Collection handle not found"));
981 return OC_STACK_INVALID_PARAM;
984 // Look for an open slot to add add the child resource.
985 // If found, add it and return success
986 for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
987 if (resourceHandle == resource->rsrcResources[i]) {
988 resource->rsrcResources[i] = (OCResource *) NULL;
989 OC_LOG(INFO, TAG, PCF("resource unbound"));
994 OC_LOG(INFO, TAG, PCF("resource not found in collection"));
997 if(presenceResource.handle)
999 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1000 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1004 // Unable to add resourceHandle, so return error
1005 return OC_STACK_ERROR;
1010 * Bind a resourcetype to a resource.
1012 * @param handle - handle to the resource
1013 * @param resourceTypeName - name of resource type. Example: "core.led"
1016 * OC_STACK_OK - no errors
1017 * OC_STACK_ERROR - stack process error
1019 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
1020 const char *resourceTypeName) {
1022 OCResourceType *pointer = NULL;
1025 OCResource *resource;
1026 OCStackResult result = OC_STACK_ERROR;
1028 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceTypeToResource"));
1030 // Validate parameters
1031 VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
1032 // TODO: Does resource attribute resentation really have to be maintained in stack?
1033 // Is it presented during resource discovery?
1035 // Make sure resource exists
1036 resource = findResource((OCResource *) handle);
1038 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1039 return OC_STACK_ERROR;
1042 TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
1044 // Create the resourcetype and insert it into the resource list
1045 pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
1049 memset(pointer, 0, sizeof(OCResourceType));
1051 // Set the resourceTypeName
1052 size = strlen(resourceTypeName) + 1;
1053 str = (char *) OCMalloc(size);
1057 strncpy(str, resourceTypeName, size);
1058 pointer->resourcetypename = str;
1060 insertResourceType(resource, pointer);
1061 result = OC_STACK_OK;
1063 #ifdef WITH_PRESENCE
1064 if(presenceResource.handle)
1066 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1067 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1071 exit: if (result != OC_STACK_OK) {
1079 * Bind a resourceinterface to a resource.
1081 * @param handle - handle to the resource
1082 * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
1085 * OC_STACK_OK - no errors
1086 * OC_STACK_ERROR - stack process error
1088 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
1089 const char *resourceInterfaceName) {
1091 OCResourceInterface *pointer = NULL;
1094 OCResource *resource;
1095 OCStackResult result = OC_STACK_ERROR;
1097 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceInterfaceToResource"));
1099 // Validate parameters
1100 VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
1102 // Make sure resource exists
1103 resource = findResource((OCResource *) handle);
1105 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1106 return OC_STACK_INVALID_PARAM;
1109 TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
1111 // Create the resourceinterface and insert it into the resource list
1112 pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
1116 memset(pointer, 0, sizeof(OCResourceInterface));
1118 // Set the resourceinterface name
1119 size = strlen(resourceInterfaceName) + 1;
1120 str = (char *) OCMalloc(size);
1124 strncpy(str, resourceInterfaceName, size);
1125 pointer->name = str;
1127 // Bind the resourceinterface to the resource
1128 insertResourceInterface(resource, pointer);
1130 result = OC_STACK_OK;
1132 #ifdef WITH_PRESENCE
1133 if(presenceResource.handle)
1135 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1136 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1140 exit: if (result != OC_STACK_OK) {
1148 * Get the number of resources that have been created in the stack.
1150 * @param numResources - pointer to count variable
1153 * OC_STACK_OK - no errors
1154 * OC_STACK_ERROR - stack process error
1157 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
1158 OCResource *pointer = headResource;
1160 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
1161 VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
1164 *numResources = *numResources + 1;
1165 pointer = pointer->next;
1171 * Get a resource handle by index.
1173 * @param index - index of resource, 0 to Count - 1
1176 * Resource handle - if found
1177 * NULL - if not found
1179 OCResourceHandle OCGetResourceHandle(uint8_t index) {
1180 OCResource *pointer = headResource;
1183 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
1185 // Iterate through the list
1186 while ((i < index) && pointer) {
1188 pointer = pointer->next;
1190 return (OCResourceHandle) pointer;
1194 * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
1197 * @param handle - handle of resource to be deleted
1200 * OC_STACK_OK - no errors
1201 * OC_STACK_ERROR - stack process error
1202 * OC_STACK_NO_RESOURCE - resource not found
1203 * OC_STACK_INVALID_PARAM - invalid param
1205 OCStackResult OCDeleteResource(OCResourceHandle handle) {
1206 OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
1209 OC_LOG(ERROR, TAG, PCF("Invalid param"));
1210 return OC_STACK_INVALID_PARAM;
1213 OCResource *resource = findResource((OCResource *) handle);
1214 if (resource == NULL) {
1215 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1216 return OC_STACK_NO_RESOURCE;
1219 if (deleteResource((OCResource *) handle) == 0) {
1220 OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
1221 return OC_STACK_ERROR;
1228 * Get the URI of the resource specified by handle.
1230 * @param handle - handle of resource
1232 * URI string - if resource found
1233 * NULL - resource not found
1235 const char *OCGetResourceUri(OCResourceHandle handle) {
1236 OCResource *resource;
1237 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
1239 resource = findResource((OCResource *) handle);
1241 return resource->uri;
1243 return (const char *) NULL;
1247 * Get the properties of the resource specified by handle.
1248 * NOTE: that after a resource is created, the OC_ACTIVE property is set
1249 * for the resource by the stack.
1251 * @param handle - handle of resource
1253 * property bitmap - if resource found
1254 * NULL - resource not found
1256 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
1257 OCResource *resource;
1258 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
1260 resource = findResource((OCResource *) handle);
1262 return resource->resourceProperties;
1268 * Get the number of resource types of the resource.
1270 * @param handle - handle of resource
1271 * @param numResourceTypes - pointer to count variable
1274 * OC_STACK_OK - no errors
1275 * OC_STACK_ERROR - stack process error
1277 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
1278 uint8_t *numResourceTypes) {
1279 OCResource *resource;
1280 OCResourceType *pointer;
1282 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
1283 VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
1284 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1286 *numResourceTypes = 0;
1288 resource = findResource((OCResource *) handle);
1290 pointer = resource->rsrcType;
1292 *numResourceTypes = *numResourceTypes + 1;
1293 pointer = pointer->next;
1300 * Get name of resource type of the resource.
1302 * @param handle - handle of resource
1303 * @param index - index of resource, 0 to Count - 1
1306 * resource type name - if resource found
1307 * NULL - resource not found
1309 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
1310 OCResourceType *resourceType;
1312 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
1314 resourceType = findResourceTypeAtIndex(handle, index);
1316 return resourceType->resourcetypename;
1318 return (const char *) NULL;
1324 * Get the number of resource interfaces of the resource.
1326 * @param handle - handle of resource
1327 * @param numResources - pointer to count variable
1330 * OC_STACK_OK - no errors
1331 * OC_STACK_ERROR - stack process error
1333 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
1334 uint8_t *numResourceInterfaces) {
1335 OCResourceInterface *pointer;
1336 OCResource *resource;
1338 OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
1340 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1341 VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
1343 *numResourceInterfaces = 0;
1344 resource = findResource((OCResource *) handle);
1346 pointer = resource->rsrcInterface;
1348 *numResourceInterfaces = *numResourceInterfaces + 1;
1349 pointer = pointer->next;
1356 * Get name of resource interface of the resource.
1358 * @param handle - handle of resource
1359 * @param index - index of resource, 0 to Count - 1
1362 * resource interface name - if resource found
1363 * NULL - resource not found
1365 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
1366 OCResourceInterface *resourceInterface;
1368 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
1370 resourceInterface = findResourceInterfaceAtIndex(handle, index);
1371 if (resourceInterface) {
1372 return resourceInterface->name;
1374 return (const char *) NULL;
1378 * Get resource handle from the collection resource by index.
1380 * @param collectionHandle - handle of collection resource
1381 * @param index - index of contained resource, 0 to Count - 1
1384 * handle to resource - if resource found
1385 * NULL - resource not found
1387 OCResourceHandle OCGetResourceHandleFromCollection(OCResourceHandle collectionHandle,
1389 OCResource *resource;
1391 OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
1393 if (index >= MAX_CONTAINED_RESOURCES) {
1397 resource = findResource((OCResource *) collectionHandle);
1402 return resource->rsrcResources[index];
1406 * Bind an entity handler to the resource.
1408 * @param handle - handle to the resource that the contained resource is to be bound
1409 * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1411 * OC_STACK_OK - no errors
1412 * OC_STACK_ERROR - stack process error
1414 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
1415 OCEntityHandler entityHandler) {
1416 OCResource *resource;
1418 OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
1420 // Validate parameters
1421 VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1422 //VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
1424 // Use the handle to find the resource in the resource linked list
1425 resource = findResource((OCResource *)handle);
1427 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1428 return OC_STACK_ERROR;
1432 resource->entityHandler = entityHandler;
1434 #ifdef WITH_PRESENCE
1435 if(presenceResource.handle)
1437 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1438 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1446 * Get the entity handler for a resource.
1448 * @param handle - handle of resource
1451 * entity handler - if resource found
1452 * NULL - resource not found
1454 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
1455 OCResource *resource;
1457 OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
1459 // Use the handle to find the resource in the resource linked list
1460 resource = findResource((OCResource *)handle);
1462 OC_LOG(ERROR, TAG, PCF("Resource not found"));
1467 return resource->entityHandler;
1470 void incrementSequenceNumber(OCResource * resPtr)
1472 // Increment the sequence number
1473 resPtr->sequenceNum += 1;
1474 if (resPtr->sequenceNum == MAX_SEQUENCE_NUMBER)
1476 resPtr->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER+1;
1482 * Notify observers that an observed value has changed.
1484 * @param handle - handle of resource
1487 * OC_STACK_OK - no errors
1488 * OC_STACK_NO_RESOURCE - invalid resource handle
1489 * OC_STACK_NO_OBSERVERS - no more observers intrested in resource
1491 OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService qos) {
1492 OCResource *resPtr = NULL;
1493 OCStackResult result;
1494 OCMethod method = OC_REST_NOMETHOD;
1495 uint32_t maxAge = 0;
1497 OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
1499 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1501 // Verify that the resource exists
1502 resPtr = findResource ((OCResource *) handle);
1503 if (NULL == resPtr || myStackMode == OC_CLIENT)
1505 return OC_STACK_NO_RESOURCE;
1507 #ifdef WITH_PRESENCE
1508 if(strcmp(resPtr->uri, OC_PRESENCE_URI))
1511 //only increment in the case of regular observing (not presence)
1512 incrementSequenceNumber(resPtr);
1513 method = OC_REST_OBSERVE;
1515 #ifdef WITH_PRESENCE
1519 method = OC_REST_PRESENCE;
1520 if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
1522 maxAge = presenceResource.presenceTTL;
1531 result = SendObserverNotification (method, resPtr, maxAge, qos);
1537 OCNotifyListOfObservers (OCResourceHandle handle,
1538 OCObservationId *obsIdList,
1539 uint8_t numberOfIds,
1540 unsigned char *notificationJSONPayload,
1541 OCQualityOfService qos)
1543 OC_LOG(INFO, TAG, PCF("Entering OCNotifyListOfObservers"));
1545 VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1546 VERIFY_NON_NULL(obsIdList, ERROR, OC_STACK_ERROR);
1547 VERIFY_NON_NULL(notificationJSONPayload, ERROR, OC_STACK_ERROR);
1549 uint8_t numIds = numberOfIds;
1550 ResourceObserver *observation;
1551 OCResource *resPtr = NULL;
1552 uint32_t maxAge = 0;
1553 unsigned char bufNotify[MAX_RESPONSE_LENGTH] = {0};
1554 unsigned char *currPtr;
1555 uint8_t numSentNotification = 0;
1557 // Verify the notification payload length does not exceed the maximim
1558 // the stack can handle
1559 if ((strlen((char *)notificationJSONPayload) +
1560 OC_JSON_PREFIX_LEN + OC_JSON_SUFFIX_LEN) > MAX_RESPONSE_LENGTH)
1562 OC_LOG(INFO, TAG, PCF("Observe notification message length too long"));
1563 return OC_STACK_ERROR;
1566 // Verify that the resource exists
1567 resPtr = findResource ((OCResource *) handle);
1568 if (NULL == resPtr || myStackMode == OC_CLIENT)
1570 return OC_STACK_NO_RESOURCE;
1574 incrementSequenceNumber(resPtr);
1575 //TODO: we should allow the serve to define thisl
1581 OC_LOG_V(INFO, TAG, "Need to notify observation id %d", *obsIdList);
1583 observation = GetObserverUsingId (*obsIdList);
1586 // Found observation - verify if it matches the resource handle
1587 if (observation->resource == resPtr)
1589 strcpy((char*)bufNotify, OC_JSON_PREFIX);
1590 currPtr = bufNotify + OC_JSON_PREFIX_LEN;
1591 memcpy (currPtr, notificationJSONPayload, strlen((char *)notificationJSONPayload));
1592 currPtr += strlen((char *)notificationJSONPayload);
1593 strcpy((char*)currPtr, OC_JSON_SUFFIX);
1595 // send notifications based on the qos of the request
1596 // The qos passed as a parameter overrides what the client requested
1597 // If we want the client preference taking high priority add:
1598 // QoS = resourceObserver->qos;
1599 if(qos == OC_NA_QOS){
1600 qos = observation->qos;
1602 if(qos != OC_HIGH_QOS)
1604 OC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
1605 observation->lowQosCount);
1606 if(observation->forceHighQos \
1607 || observation->lowQosCount >= MAX_OBSERVER_NON_COUNT)
1609 observation->lowQosCount = 0;
1610 // at some point we have to to send CON to check on the
1611 // availability of observer
1612 OC_LOG(INFO, TAG, PCF("This time we are sending the \
1613 notification as High qos"));
1618 observation->lowQosCount++;
1621 OCSendCoAPNotification (observation->resUri, observation->addr,
1622 qos, &(observation->token),
1623 bufNotify, resPtr, maxAge);
1624 numSentNotification++;
1630 if(numSentNotification == numberOfIds)
1634 else if(numSentNotification == 0)
1636 return OC_STACK_NO_OBSERVERS;
1640 //TODO: we need to signal that not every one in the
1641 // list got an update, should we also indicate who did not receive on?
1646 //-----------------------------------------------------------------------------
1647 // Private internal function definitions
1648 //-----------------------------------------------------------------------------
1650 * Generate handle of OCDoResource invocation for callback management.
1652 static OCDoHandle GenerateInvocationHandle()
1654 OCDoHandle handle = NULL;
1655 // Generate token here, it will be deleted when the transaction is deleted
1656 handle = (OCDoHandle) malloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1659 OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1664 #ifdef WITH_PRESENCE
1665 OCStackResult OCChangeResourceProperty(OCResourceProperty * inputProperty,
1666 OCResourceProperty resourceProperties, uint8_t enable)
1668 if (resourceProperties
1669 > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
1670 OC_LOG(ERROR, TAG, PCF("Invalid property"));
1671 return OC_STACK_INVALID_PARAM;
1675 *inputProperty = (OCResourceProperty) (*inputProperty & ~(resourceProperties));
1679 *inputProperty = (OCResourceProperty) (*inputProperty | resourceProperties);
1686 * Initialize resource data structures, variables, etc.
1688 OCStackResult initResources() {
1689 OCStackResult result = OC_STACK_OK;
1690 // Init application resource vars
1691 headResource = NULL;
1692 // Init Virtual Resources
1693 #ifdef WITH_PRESENCE
1694 presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
1695 //presenceResource.token = OCGenerateCoAPToken();
1696 result = OCCreateResource(&presenceResource.handle,
1702 //make resource inactive
1703 result = OCChangeResourceProperty(
1704 &(((OCResource *) presenceResource.handle)->resourceProperties),
1711 * Add a resource to the end of the linked list of resources.
1713 * @param resource - resource to be added
1715 void insertResource(OCResource *resource) {
1716 OCResource *pointer;
1718 if (!headResource) {
1719 headResource = resource;
1721 pointer = headResource;
1723 while (pointer->next) {
1724 pointer = pointer->next;
1726 pointer->next = resource;
1728 resource->next = NULL;
1732 * Find a resource in the linked list of resources.
1734 * @param resource - resource to be found
1736 * NULL - resource not found
1737 * pointer to resource - pointer to resource that was found in the linked list
1739 OCResource *findResource(OCResource *resource) {
1740 OCResource *pointer = headResource;
1743 if (pointer == resource) {
1746 pointer = pointer->next;
1751 void deleteAllResources()
1753 OCResource *pointer = headResource;
1758 temp = pointer->next;
1759 deleteResource(pointer);
1765 * Delete the resource from the linked list.
1767 * @param resource - resource to be deleted
1772 int deleteResource(OCResource *resource) {
1773 OCResource *prev = NULL;
1776 temp = headResource;
1778 if (temp == resource) {
1779 // Invalidate all Resource Properties.
1780 resource->resourceProperties = (OCResourceProperty) 0;
1781 OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
1783 #ifdef WITH_PRESENCE
1784 if(presenceResource.handle)
1786 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
1787 OCNotifyAllObservers(presenceResource.handle, OC_LOW_QOS);
1791 if (temp == headResource) {
1792 headResource = temp->next;
1794 prev->next = temp->next;
1797 deleteResourceElements(temp);
1810 * Delete all of the dynamically allocated elements that were created for the resource.
1812 * @param resource - specified resource
1814 void deleteResourceElements(OCResource *resource) {
1820 OCFree(resource->uri);
1822 // Delete resourcetype linked list
1823 deleteResourceType(resource->rsrcType);
1825 // Delete resourceinterface linked list
1826 deleteResourceInterface(resource->rsrcInterface);
1830 * Delete all of the dynamically allocated elements that were created for the resource type.
1832 * @param resourceType - specified resource type
1834 void deleteResourceType(OCResourceType *resourceType) {
1835 OCResourceType *pointer = resourceType;
1836 OCResourceType *next;
1839 next = pointer->next;
1840 OCFree(pointer->resourcetypename);
1847 * Delete all of the dynamically allocated elements that were created for the resource interface.
1849 * @param resourceInterface - specified resource interface
1851 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
1852 OCResourceInterface *pointer = resourceInterface;
1853 OCResourceInterface *next;
1856 next = pointer->next;
1857 OCFree(pointer->name);
1864 * Insert a resource type into a resource's resource type linked list.
1866 * @param resource - resource where resource type is to be inserted
1867 * @param resourceType - resource type to be inserted
1869 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
1870 OCResourceType *pointer;
1872 if (!resource->rsrcType) {
1873 resource->rsrcType = resourceType;
1875 pointer = resource->rsrcType;
1876 while (pointer->next) {
1877 pointer = pointer->next;
1879 pointer->next = resourceType;
1881 resourceType->next = NULL;
1885 * Get a resource type at the specified index within a resource.
1887 * @param handle - handle of resource
1888 * @param index - index of resource type
1891 * resourcetype - if found
1894 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
1895 OCResource *resource;
1896 OCResourceType *pointer;
1899 // Find the specified resource
1900 resource = findResource((OCResource *) handle);
1905 // Make sure a resource has a resourcetype
1906 if (!resource->rsrcType) {
1910 // Iterate through the list
1911 pointer = resource->rsrcType;
1913 while ((i < index) && pointer) {
1915 pointer = pointer->next;
1921 * Insert a resource interface into a resource's resource interface linked list.
1923 * @param resource - resource where resource interface is to be inserted
1924 * @param resourceInterface - resource interface to be inserted
1926 void insertResourceInterface(OCResource *resource,
1927 OCResourceInterface *resourceInterface) {
1928 OCResourceInterface *pointer;
1930 if (!resource->rsrcInterface) {
1931 resource->rsrcInterface = resourceInterface;
1933 pointer = resource->rsrcInterface;
1934 while (pointer->next) {
1935 pointer = pointer->next;
1937 pointer->next = resourceInterface;
1939 resourceInterface->next = NULL;
1943 * Get a resource interface at the specified index within a resource.
1945 * @param handle - handle of resource
1946 * @param index - index of resource interface
1949 * resourceinterface - if found
1952 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
1954 OCResource *resource;
1955 OCResourceInterface *pointer;
1958 // Find the specified resource
1959 resource = findResource((OCResource *) handle);
1964 // Make sure a resource has a resourceinterface
1965 if (!resource->rsrcInterface) {
1969 // Iterate through the list
1970 pointer = resource->rsrcInterface;
1972 while ((i < index) && pointer) {
1974 pointer = pointer->next;