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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 // Defining _POSIX_C_SOURCE macro with 200112L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1-2001 base
24 // specification (excluding the XSI extension).
25 // For POSIX.1-2001 base specification,
26 // Refer http://pubs.opengroup.org/onlinepubs/009695399/
27 #define _POSIX_C_SOURCE 200112L
32 #include "iotivity_config.h"
40 #include "ocresource.h"
41 #include "ocresourcehandler.h"
42 #include "ocobserve.h"
43 #include "occollection.h"
44 #include "oic_malloc.h"
45 #include "oic_string.h"
47 #include "ocpayload.h"
48 #include "secureresourcemanager.h"
50 #include "cainterface.h"
51 #include "ocpayload.h"
52 #include "oickeepalive.h"
53 #include "platform_features.h"
54 #include "payload_logging.h"
55 #include "ocendpoint.h"
56 #include "ocstackinternal.h"
57 #include "oickeepalive.h"
58 #include "ocpayloadcbor.h"
59 #include "psinterface.h"
61 #ifdef ROUTING_GATEWAY
62 #include "routingmanager.h"
66 #define TAG "OIC_RI_RESOURCE"
68 // Using 1k as block size since most persistent storage implementations use a power of 2.
69 #define INTROSPECTION_FILE_SIZE_BLOCK 1024
71 #define VERIFY_SUCCESS(op) { if (op != (OC_STACK_OK)) \
72 {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
75 * Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
76 * The value of payload size is increased up to CBOR_MAX_SIZE.
78 static const uint16_t CBOR_SIZE = 512;
81 * Max cbor size payload.
83 static const uint16_t CBOR_MAX_SIZE = 4400;
85 extern OCResource *headResource;
88 * Prepares a Payload for response.
90 static OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
91 OCDiscoveryPayload *payload,
93 CAEndpoint_t *networkInfo,
97 * Sets the value of an attribute on a resource.
99 static OCStackResult SetAttributeInternal(OCResource *resource,
100 const char *attribute,
102 bool updateDatabase);
104 //-----------------------------------------------------------------------------
105 // Default resource entity handler function
106 //-----------------------------------------------------------------------------
107 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
108 OCEntityHandlerRequest * request, void* callbackParam)
110 //TODO ("Implement me!!!!");
111 // TODO: remove silence unused param warnings
114 (void) callbackParam;
115 return OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
118 /* This method will retrieve the port at which the secure resource is hosted */
119 static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port)
123 if (endpoint->adapter == OC_ADAPTER_IP)
125 if (endpoint->flags & OC_IP_USE_V6)
127 p = caglobals.ip.u6s.port;
129 else if (endpoint->flags & OC_IP_USE_V4)
131 p = caglobals.ip.u4s.port;
140 /* This method will retrieve the tcp port */
141 static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port, bool secured)
145 if (endpoint->adapter == OC_ADAPTER_IP)
147 if (endpoint->flags & OC_IP_USE_V4)
149 p = secured ? caglobals.tcp.ipv4s.port : caglobals.tcp.ipv4.port;
151 else if (endpoint->flags & OC_IP_USE_V6)
153 p = secured ? caglobals.tcp.ipv6s.port : caglobals.tcp.ipv6.port;
163 * Function will extract 0, 1 or 2 filters from query.
164 * More than 2 filters or unsupported filters will result in error.
165 * If both filters are of the same supported type, the 2nd one will be picked.
166 * Resource and device filters in the SAME query are NOT validated
167 * and resources will likely not clear filters.
169 OCStackResult ExtractFiltersFromQuery(const char *query, char **filterOne, char **filterTwo)
173 OIC_LOG(ERROR, TAG, "Query is empty!");
174 return OC_STACK_INVALID_QUERY;
178 char *queryDup = NULL;
179 char *restOfQuery = NULL;
180 char *keyValuePair = NULL;
181 int numKeyValuePairsParsed = 0;
186 queryDup = OICStrdup(query);
187 if (NULL == queryDup)
189 OIC_LOG(ERROR, TAG, "Creating duplicate string failed!");
190 return OC_STACK_NO_MEMORY;
193 OIC_LOG_V(INFO, TAG, "Extracting params from %s", queryDup);
195 OCStackResult eCode = OC_STACK_INVALID_QUERY;
196 if (strnlen(queryDup, MAX_QUERY_LENGTH) >= MAX_QUERY_LENGTH)
198 OIC_LOG(ERROR, TAG, "Query exceeds maximum length.");
202 keyValuePair = strtok_r (queryDup, OC_QUERY_SEPARATOR, &restOfQuery);
206 if (numKeyValuePairsParsed >= 2)
208 OIC_LOG(ERROR, TAG, "More than 2 queries params in URI.");
212 key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
218 else if (strncasecmp(key, OC_RSRVD_INTERFACE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0)
220 *filterOne = value; // if
222 else if (strncasecmp(key, OC_RSRVD_RESOURCE_TYPE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0)
224 *filterTwo = value; // rt
228 OIC_LOG_V(ERROR, TAG, "Unsupported query key: %s", key);
231 ++numKeyValuePairsParsed;
233 keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
238 *filterOne = OICStrdup(*filterOne);
239 if (NULL == *filterOne)
241 OIC_LOG(ERROR, TAG, "Creating duplicate string failed!");
242 eCode = OC_STACK_NO_MEMORY;
249 *filterTwo = OICStrdup(*filterTwo);
250 if (NULL == *filterTwo)
252 OIC_LOG(ERROR, TAG, "Creating duplicate string failed!");
254 eCode = OC_STACK_NO_MEMORY;
260 OIC_LOG_V(INFO, TAG, "Extracted params if: %s and rt: %s.", *filterOne, *filterTwo);
270 OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest)
272 if (strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_URI) == 0)
274 return OC_WELL_KNOWN_URI;
276 else if (strcmp(uriInRequest, OC_RSRVD_DEVICE_URI) == 0)
278 return OC_DEVICE_URI;
280 else if (strcmp(uriInRequest, OC_RSRVD_PLATFORM_URI) == 0)
282 return OC_PLATFORM_URI;
284 else if (strcmp(uriInRequest, OC_RSRVD_RESOURCE_TYPES_URI) == 0)
286 return OC_RESOURCE_TYPES_URI;
288 else if (strcmp(uriInRequest, OC_RSRVD_INTROSPECTION_URI) == 0)
290 return OC_INTROSPECTION_URI;
292 else if (strcmp(uriInRequest, OC_RSRVD_INTROSPECTION_PAYLOAD_URI) == 0)
294 return OC_INTROSPECTION_PAYLOAD_URI;
296 #ifdef ROUTING_GATEWAY
297 else if (0 == strcmp(uriInRequest, OC_RSRVD_GATEWAY_URI))
299 return OC_GATEWAY_URI;
303 else if (strcmp(uriInRequest, OC_RSRVD_PRESENCE_URI) == 0)
307 #endif //WITH_PRESENCE
310 else if (0 == strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_MQ_URI))
312 return OC_MQ_BROKER_URI;
317 else if (strcmp(uriInRequest, OC_RSRVD_KEEPALIVE_URI) == 0)
319 return OC_KEEPALIVE_RESOURCE_URI;
323 return OC_UNKNOWN_URI;
326 static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *query,
327 char **filterOne, char **filterTwo)
329 if(!filterOne || !filterTwo)
331 return OC_STACK_INVALID_PARAM;
338 if (uri == OC_PRESENCE)
340 //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
341 OIC_LOG(INFO, TAG, "OC_PRESENCE Request for virtual resource.");
346 OCStackResult result = OC_STACK_OK;
350 result = ExtractFiltersFromQuery(query, filterOne, filterTwo);
356 static OCStackResult BuildDevicePlatformPayload(const OCResource *resourcePtr, OCRepPayload** payload,
359 OCRepPayload *tempPayload = OCRepPayloadCreate();
363 OCRepPayloadDestroy(tempPayload);
364 return OC_STACK_INVALID_PARAM;
369 return OC_STACK_NO_MEMORY;
374 const char *deviceId = OCGetServerInstanceIDString();
377 OIC_LOG(ERROR, TAG, "Failed retrieving device id.");
378 return OC_STACK_ERROR;
380 OCRepPayloadSetPropString(tempPayload, OC_RSRVD_DEVICE_ID, deviceId);
383 for (OCResourceType *resType = resourcePtr->rsrcType; resType; resType = resType->next)
385 OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename);
388 for (OCResourceInterface *resInterface = resourcePtr->rsrcInterface; resInterface;
389 resInterface = resInterface->next)
391 OCRepPayloadAddInterface(tempPayload, resInterface->name);
394 for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
396 if (resAttrib->attrName && resAttrib->attrValue)
398 if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
400 char *dmv = OCCreateString((OCStringLL *)resAttrib->attrValue);
403 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, dmv);
409 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
416 *payload = tempPayload;
420 OCRepPayloadAppend(*payload, tempPayload);
426 OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
427 OCRepPayload** payload, OCDevAddr *devAddr)
429 OCRepPayload *tempPayload = OCRepPayloadCreate();
433 OCRepPayloadDestroy(tempPayload);
434 return OC_STACK_INVALID_PARAM;
439 return OC_STACK_NO_MEMORY;
442 OCRepPayloadSetPropString(tempPayload, OC_RSRVD_HREF, resourcePtr->uri);
444 uint8_t numElement = 0;
445 if (OC_STACK_OK == OCGetNumberOfResourceTypes((OCResource *)resourcePtr, &numElement))
447 size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
448 char **rt = (char **)OICMalloc(sizeof(char *) * numElement);
449 for (uint8_t i = 0; i < numElement; ++i)
451 const char *value = OCGetResourceTypeName((OCResource *)resourcePtr, i);
452 OIC_LOG_V(DEBUG, TAG, "value: %s", value);
453 rt[i] = OICStrdup(value);
455 OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_RESOURCE_TYPE, rt, rtDim);
459 if (OC_STACK_OK == OCGetNumberOfResourceInterfaces((OCResource *)resourcePtr, &numElement))
461 size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
462 char **itf = (char **)OICMalloc(sizeof(char *) * numElement);
463 for (uint8_t i = 0; i < numElement; ++i)
465 const char *value = OCGetResourceInterfaceName((OCResource *)resourcePtr, i);
466 OIC_LOG_V(DEBUG, TAG, "value: %s", value);
467 itf[i] = OICStrdup(value);
469 OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_INTERFACE, itf, ifDim);
472 for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
474 if (resAttrib->attrName && resAttrib->attrValue)
476 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
480 OCResourceProperty p = OCGetResourceProperties((OCResourceHandle *)resourcePtr);
481 OCRepPayload *policy = OCRepPayloadCreate();
484 OCPayloadDestroy((OCPayload *)tempPayload);
485 return OC_STACK_NO_MEMORY;
487 OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE)));
490 OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE);
491 uint16_t securePort = 0;
492 if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
496 OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort);
498 OCRepPayloadSetPropObjectAsOwner(tempPayload, OC_RSRVD_POLICY, policy);
502 *payload = tempPayload;
506 OCRepPayloadAppend(*payload, tempPayload);
512 void CleanUpDeviceProperties(OCDeviceProperties **deviceProperties)
514 if (!deviceProperties || !(*deviceProperties))
519 OICFreeAndSetToNull((void**)(deviceProperties));
522 static OCStackResult CreateDeviceProperties(const char *piid, OCDeviceProperties **deviceProperties)
524 OIC_LOG(DEBUG, TAG, "CreateDeviceProperties IN");
526 OCStackResult result = OC_STACK_OK;
528 if (!piid || !deviceProperties)
530 return OC_STACK_INVALID_PARAM;
533 *deviceProperties = (OCDeviceProperties*)OICCalloc(1, sizeof(OCDeviceProperties));
534 if (*deviceProperties)
536 OICStrcpy((*deviceProperties)->protocolIndependentId, UUID_STRING_SIZE, piid);
540 result = OC_STACK_NO_MEMORY;
543 OIC_LOG(DEBUG, TAG, "CreateDeviceProperties OUT");
548 static OCStackResult GenerateDeviceProperties(OCDeviceProperties **deviceProperties)
550 OCStackResult result = OC_STACK_OK;
551 OicUuid_t generatedProtocolIndependentId = {.id = {0}};
552 char* protocolIndependentId = NULL;
554 if (!deviceProperties)
556 return OC_STACK_INVALID_PARAM;
559 *deviceProperties = NULL;
561 // Generate a UUID for the Protocol Independent ID
562 if (OCGenerateUuid(generatedProtocolIndependentId.id))
564 protocolIndependentId = (char*)OICCalloc(UUID_STRING_SIZE, sizeof(char));
565 if (protocolIndependentId)
567 if (!OCConvertUuidToString(generatedProtocolIndependentId.id, protocolIndependentId))
569 OIC_LOG(ERROR, TAG, "ConvertUuidToStr failed");
570 result = OC_STACK_ERROR;
575 result = OC_STACK_NO_MEMORY;
580 OIC_LOG(FATAL, TAG, "Generate UUID for Device Properties Protocol Independent ID failed!");
581 result = OC_STACK_ERROR;
584 if (OC_STACK_OK == result)
586 result = CreateDeviceProperties(protocolIndependentId, deviceProperties);
587 if (OC_STACK_OK != result)
589 OIC_LOG(ERROR, TAG, "CreateDeviceProperties failed");
594 OICFreeAndSetToNull((void**)&protocolIndependentId);
599 OCStackResult CBORPayloadToDeviceProperties(const uint8_t *payload, size_t size, OCDeviceProperties **deviceProperties)
601 OCStackResult result = OC_STACK_OK;
602 CborError cborResult = CborNoError;
603 char* protocolIndependentId = NULL;
608 if (!payload || (size <= 0) || !deviceProperties)
610 return OC_STACK_INVALID_PARAM;
613 *deviceProperties = NULL;
615 cbor_parser_init(payload, size, 0, &parser, &dpCbor);
617 // Protocol Independent ID - Mandatory
618 cborResult = cbor_value_map_find_value(&dpCbor, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, &dpMap);
619 if ((CborNoError == cborResult) && cbor_value_is_text_string(&dpMap))
623 cborResult = cbor_value_dup_text_string(&dpMap, &protocolIndependentId, &len, NULL);
624 if (CborNoError != cborResult)
626 OIC_LOG(ERROR, TAG, "Failed to get Protocol Independent Id!");
627 result = OC_STACK_ERROR;
632 OIC_LOG(ERROR, TAG, "Protocol Independent Id is not present or invalid!");
633 result = OC_STACK_ERROR;
636 if (OC_STACK_OK == result)
638 result = CreateDeviceProperties(protocolIndependentId, deviceProperties);
639 if (OC_STACK_OK != result)
641 OIC_LOG(ERROR, TAG, "CreateDeviceProperties failed");
646 OICFreeAndSetToNull((void**)&protocolIndependentId);
651 OCStackResult DevicePropertiesToCBORPayload(const OCDeviceProperties *deviceProperties, uint8_t **payload, size_t *size)
653 OCStackResult result = OC_STACK_OK;
654 CborError cborResult = CborNoError;
655 uint8_t *cborPayload = NULL;
656 size_t cborLen = CBOR_SIZE;
660 if (!deviceProperties || !payload || !size || (*size > CBOR_MAX_SIZE))
662 return OC_STACK_INVALID_PARAM;
665 // Reset the CBOR length if we need to
674 cborPayload = (uint8_t*)OICCalloc(1, cborLen);
675 if (NULL != cborPayload)
677 cbor_encoder_init(&encoder, cborPayload, cborLen, 0);
679 // Create the Device Properties encoder map
680 cborResult = cbor_encoder_create_map(&encoder, &dpMap, CborIndefiniteLength);
681 if (CborNoError != cborResult)
683 OIC_LOG(ERROR, TAG, "Failed to create encoder map!");
684 result = OC_STACK_ERROR;
689 result = OC_STACK_NO_MEMORY;
692 // Protocol Independent ID - Mandatory
693 if (OC_STACK_OK == result)
695 cborResult = cbor_encode_text_string(&dpMap, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, strlen(OC_RSRVD_PROTOCOL_INDEPENDENT_ID));
696 if (CborNoError == cborResult)
698 cborResult = cbor_encode_text_string(&dpMap,
699 deviceProperties->protocolIndependentId,
700 strlen(deviceProperties->protocolIndependentId));
701 if (CborNoError != cborResult)
703 OIC_LOG(ERROR, TAG, "Failed to encode protocolIndependentId!");
704 result = OC_STACK_ERROR;
709 OIC_LOG(ERROR, TAG, "Failed to encode OC_RSRVD_PROTOCOL_INDEPENDENT_ID!");
710 result = OC_STACK_ERROR;
714 // Encoding is finished
715 if (OC_STACK_OK == result)
717 cborResult = cbor_encoder_close_container(&encoder, &dpMap);
718 if (CborNoError != cborResult)
720 OIC_LOG(ERROR, TAG, "Failed to close dpMap container!");
721 result = OC_STACK_ERROR;
725 if (OC_STACK_OK == result)
727 *size = cbor_encoder_get_buffer_size(&encoder, cborPayload);
728 *payload = cborPayload;
731 else if ((CborErrorOutOfMemory == cborResult) && (cborLen < CBOR_MAX_SIZE))
733 OICFreeAndSetToNull((void**)&cborPayload);
735 // Realloc and try again
736 cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
737 result = DevicePropertiesToCBORPayload(deviceProperties, payload, &cborLen);
738 if (OC_STACK_OK == result)
745 OICFreeAndSetToNull((void**)&cborPayload);
751 static OCStackResult UpdateDeviceInfoResourceWithDeviceProperties(const OCDeviceProperties *deviceProperties, bool updateDatabase)
753 OCStackResult result = OC_STACK_OK;
754 OCResource *resource = NULL;
756 if (!deviceProperties)
758 return OC_STACK_INVALID_PARAM;
761 resource = FindResourceByUri(OC_RSRVD_DEVICE_URI);
764 result = SetAttributeInternal(resource, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, deviceProperties->protocolIndependentId, updateDatabase);
765 if (OC_STACK_OK != result)
767 OIC_LOG(ERROR, TAG, "OCSetPropertyValue failed to set Protocol Independent ID");
772 OIC_LOG(ERROR, TAG, "Resource does not exist.");
773 result = OC_STACK_NO_RESOURCE;
779 static OCStackResult ReadDevicePropertiesFromDatabase(OCDeviceProperties **deviceProperties)
781 uint8_t *data = NULL;
784 OCStackResult result = ReadDatabaseFromPS(OC_DEVICE_PROPS_FILE_NAME, OC_JSON_DEVICE_PROPS_NAME, &data, &size);
785 if (OC_STACK_OK == result)
787 // Read device properties from PS
788 result = CBORPayloadToDeviceProperties(data, size, deviceProperties);
789 if (OC_STACK_OK != result)
791 OIC_LOG(WARNING, TAG, "CBORPayloadToDeviceProperties failed");
796 OIC_LOG(ERROR, TAG, "ReadDatabaseFromPS failed");
800 OICFreeAndSetToNull((void**)&data);
805 static OCStackResult UpdateDevicePropertiesDatabase(const OCDeviceProperties *deviceProperties)
807 OCStackResult result = OC_STACK_OK;
808 uint8_t *payload = NULL;
811 if (!deviceProperties)
813 return OC_STACK_INVALID_PARAM;
816 // Check to see if persistent storage exists. If it doesn't then
817 // we just allow the device properties to exist in memory and
818 // it is the application's job to manage them.
819 if (!OCGetPersistentStorageHandler())
821 OIC_LOG(DEBUG, TAG, "Persistent Storage handler is NULL.");
825 // Convert OCDeviceProperties into CBOR to use for updating Persistent Storage
826 result = DevicePropertiesToCBORPayload(deviceProperties, &payload, &size);
827 if ((OC_STACK_OK == result) && payload)
829 result = UpdateResourceInPS(OC_DEVICE_PROPS_FILE_NAME, OC_JSON_DEVICE_PROPS_NAME, payload, size);
830 if (OC_STACK_OK != result)
832 OIC_LOG_V(ERROR, TAG, "UpdateResourceInPS failed with %d!", result);
837 OIC_LOG_V(ERROR, TAG, "DevicePropertiesToCBORPayload failed with %d!", result);
841 OICFreeAndSetToNull((void**)&payload);
846 OCStackResult InitializeDeviceProperties()
848 OIC_LOG(DEBUG, TAG, "InitializeDeviceProperties IN");
850 OCStackResult result = OC_STACK_OK;
851 OCDeviceProperties *deviceProperties = NULL;
852 bool updateDatabase = false;
854 // Populate OCDeviceProperties from persistent storage
855 result = ReadDevicePropertiesFromDatabase(&deviceProperties);
856 if (OC_STACK_OK != result)
858 OIC_LOG(ERROR, TAG, "ReadDevicePropertiesFromDatabase failed");
861 // If the device properties in persistent storage are corrupted or
862 // not available for some reason, a default OCDeviceProperties is created.
863 if ((OC_STACK_OK != result) || !deviceProperties)
865 result = GenerateDeviceProperties(&deviceProperties);
866 if (OC_STACK_OK == result)
868 updateDatabase = true;
872 OIC_LOG(ERROR, TAG, "GenerateDeviceProperties failed");
876 // Set the device properties information on the device info resource. This will
877 // also persist OCDeviceProperties so they can be used in the future if they are
878 // not already in the database.
879 if (OC_STACK_OK == result)
881 result = UpdateDeviceInfoResourceWithDeviceProperties(deviceProperties, updateDatabase);
882 if (OC_STACK_OK != result)
884 OIC_LOG(ERROR, TAG, "UpdateDeviceInfoResourceWithDeviceProperties failed");
889 CleanUpDeviceProperties(&deviceProperties);
891 OIC_LOG(DEBUG, TAG, "InitializeDeviceProperties OUT");
896 static size_t GetIntrospectionDataSize(const OCPersistentStorage *ps)
899 char buffer[INTROSPECTION_FILE_SIZE_BLOCK];
907 fp = ps->open(OC_INTROSPECTION_FILE_NAME, "rb");
910 size_t bytesRead = 0;
913 bytesRead = ps->read(buffer, 1, INTROSPECTION_FILE_SIZE_BLOCK, fp);
921 OCStackResult GetIntrospectionDataFromPS(char **data, size_t *size)
923 OIC_LOG(DEBUG, TAG, "GetIntrospectionDataFromPS IN");
926 uint8_t *fsData = NULL;
928 OCStackResult ret = OC_STACK_ERROR;
929 OCPersistentStorage *ps = NULL;
931 if (!data || *data || !size)
933 return OC_STACK_INVALID_PARAM;
936 ps = OCGetPersistentStorageHandler();
939 OIC_LOG(ERROR, TAG, "Persistent Storage handler is NULL");
943 fileSize = GetIntrospectionDataSize(ps);
944 OIC_LOG_V(DEBUG, TAG, "File Read Size: %zu", fileSize);
947 // allocate one more byte to accomodate null terminator for string we are reading.
948 fsData = (uint8_t *)OICCalloc(1, fileSize + 1);
951 OIC_LOG(ERROR, TAG, "Could not allocate memory for introspection data");
955 fp = ps->open(OC_INTROSPECTION_FILE_NAME, "rb");
958 OIC_LOG(ERROR, TAG, "Could not open persistent storage file for introspection data");
961 if (ps->read(fsData, 1, fileSize, fp) == fileSize)
964 fsData[fileSize] = '\0';
965 *data = (char *)fsData;
970 OIC_LOG(DEBUG, TAG, "GetIntrospectionDataFromPS OUT");
984 OCStackResult BuildIntrospectionPayloadResponse(const OCResource *resourcePtr,
985 OCRepPayload** payload, OCDevAddr *devAddr)
987 OCRepPayload *tempPayload = NULL;
989 char *introspectionData = NULL;
991 ret = GetIntrospectionDataFromPS(&introspectionData, &size);
992 if (OC_STACK_OK == ret)
994 OCRepPayload *tempPayload = OCRepPayloadCreate();
997 if (OCRepPayloadSetPropStringAsOwner(tempPayload, OC_RSRVD_INTROSPECTION_DATA_NAME, introspectionData))
999 *payload = tempPayload;
1004 ret = OC_STACK_NO_MEMORY;
1007 if (ret != OC_STACK_OK)
1009 OICFree(introspectionData);
1010 OCRepPayloadDestroy(tempPayload);
1016 OCRepPayload *BuildUrlInfoWithProtocol(const char *protocol)
1018 OCStackResult result = OC_STACK_OK;
1019 OCRepPayload *urlInfoPayload = OCRepPayloadCreate();
1020 if (!urlInfoPayload)
1022 OIC_LOG(ERROR, TAG, "Failed to create a new RepPayload");
1023 result = OC_STACK_NO_MEMORY;
1027 if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_URL, OC_RSRVD_INTROSPECTION_PAYLOAD_URI))
1029 OIC_LOG(ERROR, TAG, "Failed to add url");
1030 result = OC_STACK_ERROR;
1033 if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_PROTOCOL, protocol))
1035 OIC_LOG(ERROR, TAG, "Failed to add protocol");
1036 result = OC_STACK_ERROR;
1039 if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_CONTENT_TYPE, OC_RSRVD_INTROSPECTION_CONTENT_TYPE_VALUE))
1041 OIC_LOG(ERROR, TAG, "Failed to add content type");
1042 result = OC_STACK_ERROR;
1045 if (!OCRepPayloadSetPropInt(urlInfoPayload, OC_RSRVD_INTROSPECTION_VERSION, OC_RSRVD_INTROSPECTION_VERSION_VALUE))
1047 OIC_LOG(ERROR, TAG, "Failed to add version");
1048 result = OC_STACK_ERROR;
1053 if (result != OC_STACK_OK)
1055 OCRepPayloadDestroy(urlInfoPayload);
1056 urlInfoPayload = NULL;
1058 return urlInfoPayload;
1061 OCStackResult AddProtocolToLL(OCStringLL **protoLL, const char *protocol)
1063 OCStringLL* cur = *protoLL;
1064 // Check if protocol is already in list
1067 if (strcmp(cur->value, protocol) == 0)
1075 // The intent of the protocol list is to collect all unique protocols available on this
1076 // endpoint. Set an error that can be used to skip processing this protocol further as
1077 // it already exists in the list.
1078 return OC_STACK_INVALID_PARAM;
1082 cur = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1085 return OC_STACK_NO_MEMORY;
1089 cur->value = OICStrdup(protocol);
1093 return OC_STACK_NO_MEMORY;
1096 cur->next = *protoLL;
1101 void FreeProtocolLL(OCStringLL *protoLL)
1103 OCStringLL* cur = protoLL;
1106 OCStringLL *temp = cur;
1108 OICFree(temp->value);
1113 OCStackResult BuildIntrospectionResponseRepresentation(const OCResource *resourcePtr,
1114 OCRepPayload** payload, OCDevAddr *devAddr)
1116 size_t dimensions[3] = { 0, 0, 0 };
1117 OCRepPayload *tempPayload = NULL;
1118 OCRepPayload **urlInfoPayload = NULL;
1119 OCStringLL *protoLL = NULL;
1120 OCStackResult ret = OC_STACK_OK;
1121 OCResourceType *resType = NULL;
1122 OCResourceInterface *resInterface = NULL;
1126 ret = OC_STACK_INVALID_PARAM;
1130 tempPayload = OCRepPayloadCreate();
1133 ret = OC_STACK_NO_MEMORY;
1137 if (!OCRepPayloadSetUri(tempPayload, resourcePtr->uri))
1139 OIC_LOG(ERROR, TAG, "Failed to set payload URI");
1140 ret = OC_STACK_ERROR;
1144 resType = resourcePtr->rsrcType;
1147 if (!OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename))
1149 OIC_LOG(ERROR, TAG, "Failed at add resource type");
1150 ret = OC_STACK_ERROR;
1153 resType = resType->next;
1156 resInterface = resourcePtr->rsrcInterface;
1157 while (resInterface)
1159 if (!OCRepPayloadAddInterface(tempPayload, resInterface->name))
1161 OIC_LOG(ERROR, TAG, "Failed to add interface");
1162 ret = OC_STACK_ERROR;
1165 resInterface = resInterface->next;
1167 if (!OCRepPayloadSetPropString(tempPayload, OC_RSRVD_INTROSPECTION_NAME, OC_RSRVD_INTROSPECTION_NAME_VALUE))
1169 OIC_LOG(ERROR, TAG, "Failed to set Name property.");
1170 ret = OC_STACK_ERROR;
1174 // Figure out which protocols this endpoint supports
1175 if (resourcePtr->endpointType & OC_COAP)
1177 if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
1182 if (resourcePtr->endpointType & OC_COAPS)
1184 if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAPS_STR))
1190 if (resourcePtr->endpointType & OC_COAP_TCP)
1192 if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
1197 if (resourcePtr->endpointType & OC_COAPS_TCP)
1199 if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAPS_STR))
1206 if (resourcePtr->endpointType & OC_HTTP)
1208 if (OC_STACK_OK == AddProtocolToLL(&protoLL, HTTP_STR))
1213 if (resourcePtr->endpointType & OC_HTTPS)
1215 if (OC_STACK_OK == AddProtocolToLL(&protoLL, HTTPS_STR))
1222 if (resourcePtr->endpointType & OC_COAP_RFCOMM)
1224 if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
1230 // Add a urlInfo object for each protocol supported
1231 if (dimensions[0] >= 0)
1233 urlInfoPayload = (OCRepPayload **)OICMalloc(dimensions[0] * sizeof(OCRepPayload));
1236 OCStringLL *proto = protoLL;
1240 urlInfoPayload[i] = BuildUrlInfoWithProtocol(proto->value);
1241 if (!urlInfoPayload[i])
1243 OIC_LOG(ERROR, TAG, "Unable to build urlInfo object for protocol");
1244 ret = OC_STACK_ERROR;
1247 proto = proto->next;
1250 if (!OCRepPayloadSetPropObjectArrayAsOwner(tempPayload,
1251 OC_RSRVD_INTROSPECTION_URL_INFO,
1255 OIC_LOG(ERROR, TAG, "Unable to add urlInfo object to introspection payload ");
1256 ret = OC_STACK_ERROR;
1262 OIC_LOG(ERROR, TAG, "Unable to allocate memory for urlInfo ");
1263 ret = OC_STACK_NO_MEMORY;
1270 *payload = tempPayload;
1274 OCRepPayloadAppend(*payload, tempPayload);
1277 if (ret != OC_STACK_OK)
1279 OCRepPayloadDestroy(tempPayload);
1282 OICFree(urlInfoPayload);
1285 FreeProtocolLL(protoLL);
1290 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
1291 OCDiscoveryPayload *payload,
1293 CAEndpoint_t *networkInfo,
1296 if (!resourcePtr || !payload)
1298 return OC_STACK_INVALID_PARAM;
1300 uint16_t securePort = 0;
1301 if (resourcePtr->resourceProperties & OC_SECURE)
1303 if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
1309 bool isVirtual = false;
1310 if (GetTypeOfVirtualURI(resourcePtr->uri) != OC_UNKNOWN_URI)
1315 uint16_t tcpPort = 0;
1316 GetTCPPortInfo(devAddr, &tcpPort, (resourcePtr->resourceProperties & OC_SECURE));
1318 OCDiscoveryPayloadAddResourceWithEps(payload, resourcePtr, securePort,
1319 isVirtual, networkInfo, infoSize, devAddr, tcpPort);
1321 OCDiscoveryPayloadAddResourceWithEps(payload, resourcePtr, securePort,
1322 isVirtual, networkInfo, infoSize, devAddr);
1328 OCResource *FindResourceByUri(const char* resourceUri)
1335 OCResource * pointer = headResource;
1338 if (strcmp(resourceUri, pointer->uri) == 0)
1342 pointer = pointer->next;
1344 OIC_LOG_V(INFO, TAG, "Resource %s not found", resourceUri);
1348 OCStackResult CheckRequestsEndpoint(const OCDevAddr *reqDevAddr,
1349 OCTpsSchemeFlags resTpsFlags)
1353 OIC_LOG(ERROR, TAG, "OCDevAddr* is NULL!!!");
1354 return OC_STACK_INVALID_PARAM;
1357 OCTpsSchemeFlags reqTpsFlags = OC_NO_TPS;
1358 OCStackResult result = OCGetMatchedTpsFlags((CATransportAdapter_t)reqDevAddr->adapter,
1359 (CATransportFlags_t)reqDevAddr->flags, &reqTpsFlags);
1361 if (result != OC_STACK_OK)
1363 OIC_LOG_V(ERROR, TAG, "Failed at get TPS flags. errcode is %d", result);
1367 // bit compare between request tps flags and resource tps flags
1368 if (reqTpsFlags & resTpsFlags)
1370 OIC_LOG(INFO, TAG, "Request come from registered TPS");
1375 OIC_LOG(ERROR, TAG, "Request come from unregistered TPS!!!");
1376 return OC_STACK_BAD_ENDPOINT;
1380 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
1381 ResourceHandling *handling,
1382 OCResource **resource)
1384 if(!request || !handling || !resource)
1386 return OC_STACK_INVALID_PARAM;
1389 OIC_LOG_V(INFO, TAG, "DetermineResourceHandling for %s", request->resourceUrl);
1391 // Check if virtual resource
1392 if (GetTypeOfVirtualURI(request->resourceUrl) != OC_UNKNOWN_URI)
1394 OIC_LOG_V (INFO, TAG, "%s is virtual", request->resourceUrl);
1395 *handling = OC_RESOURCE_VIRTUAL;
1396 *resource = headResource;
1399 if (strlen((const char*)(request->resourceUrl)) == 0)
1401 // Resource URL not specified
1402 *handling = OC_RESOURCE_NOT_SPECIFIED;
1403 return OC_STACK_NO_RESOURCE;
1407 OCResource *resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
1408 *resource = resourcePtr;
1410 // Checking resource TPS flags if resource exist in stack.
1413 OCStackResult result = CheckRequestsEndpoint(&(request->devAddr), resourcePtr->endpointType);
1415 if (result != OC_STACK_OK)
1417 if (result == OC_STACK_BAD_ENDPOINT)
1419 OIC_LOG(ERROR, TAG, "Request come from bad endpoint. ignore request!!!");
1420 return OC_STACK_BAD_ENDPOINT;
1424 OIC_LOG_V(ERROR, TAG, "Failed at get tps flag errcode: %d", result);
1432 if(defaultDeviceHandler)
1434 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
1438 // Resource does not exist
1439 // and default device handler does not exist
1440 *handling = OC_RESOURCE_NOT_SPECIFIED;
1441 return OC_STACK_NO_RESOURCE;
1444 if (resourcePtr && resourcePtr->rsrcChildResourcesHead != NULL)
1446 // Collection resource
1447 if (resourcePtr->entityHandler != defaultResourceEHandler)
1449 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
1454 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
1460 // Resource not a collection
1461 if (resourcePtr->entityHandler != defaultResourceEHandler)
1463 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
1468 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
1475 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
1477 OCStackResult result;
1484 result = OC_STACK_OK;
1487 result = OC_STACK_SLOW_RESOURCE;
1490 result = OC_STACK_ERROR;
1492 case OC_EH_FORBIDDEN:
1493 result = OC_STACK_FORBIDDEN_REQ;
1495 case OC_EH_INTERNAL_SERVER_ERROR:
1496 result = OC_STACK_INTERNAL_SERVER_ERROR;
1498 case OC_EH_RESOURCE_CREATED:
1499 result = OC_STACK_RESOURCE_CREATED;
1501 case OC_EH_RESOURCE_DELETED:
1502 result = OC_STACK_RESOURCE_DELETED;
1505 result = OC_STACK_RESOURCE_CHANGED;
1507 case OC_EH_RESOURCE_NOT_FOUND:
1508 result = OC_STACK_NO_RESOURCE;
1511 result = OC_STACK_ERROR;
1517 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
1524 // Null is analogous to no filter.i.e. query is of form /oic/res?if=oic.if.baseline or /oic/res,
1525 // without rt query.
1526 if (NULL == resourceTypeFilter)
1531 // Empty resourceType filter is analogous to error query
1532 // It is an error as query is of form /oic/res?rt=
1533 if (0 == strlen(resourceTypeFilter))
1538 for (OCResourceType *rtPtr = resource->rsrcType; rtPtr; rtPtr = rtPtr->next)
1540 if (0 == strcmp(rtPtr->resourcetypename, resourceTypeFilter))
1546 OIC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
1550 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
1557 // Null is analogous to no filter i.e. query is of form /oic/res?rt=core.light or /oic/res,
1558 // without if query.
1559 if (NULL == interfaceFilter)
1564 // Empty interface filter is analogous to error query
1565 // It is an error as query is of form /oic/res?if=
1566 if (0 == strlen(interfaceFilter))
1571 for (OCResourceInterface *ifPtr = resource->rsrcInterface; ifPtr; ifPtr = ifPtr->next)
1573 if (0 == strcmp(ifPtr->name, interfaceFilter) ||
1574 0 == strcmp(OC_RSRVD_INTERFACE_LL, interfaceFilter) ||
1575 0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter))
1581 OIC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
1586 * If the filters are null, they will be assumed to NOT be present
1587 * and the resource will not be matched against them.
1588 * Function will return true if all non null AND non empty filters passed in find a match.
1590 static bool includeThisResourceInResponse(OCResource *resource,
1591 char *interfaceFilter,
1592 char *resourceTypeFilter)
1596 OIC_LOG(ERROR, TAG, "Invalid resource");
1600 if (resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
1603 * At least one valid filter should be available to
1604 * include the resource in discovery response
1606 if (!(resourceTypeFilter && *resourceTypeFilter))
1608 OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE\
1609 resource", resource->uri);
1613 else if (!(resource->resourceProperties & OC_ACTIVE) ||
1614 !(resource->resourceProperties & OC_DISCOVERABLE))
1616 OIC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
1620 return resourceMatchesIFFilter(resource, interfaceFilter) &&
1621 resourceMatchesRTFilter(resource, resourceTypeFilter);
1624 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
1625 OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
1627 OCEntityHandlerResponse *response = NULL;
1628 OCStackResult result = OC_STACK_ERROR;
1630 response = (OCEntityHandlerResponse *)OICCalloc(1, sizeof(*response));
1631 VERIFY_PARAM_NON_NULL(TAG, response, "Failed allocating OCEntityHandlerResponse");
1633 response->ehResult = ehResult;
1634 response->payload = discoveryPayload;
1635 response->persistentBufferFlag = 0;
1636 response->requestHandle = (OCRequestHandle) request;
1637 response->resourceHandle = (OCResourceHandle) resource;
1639 result = OCDoResponse(response);
1645 return OC_STACK_NO_MEMORY;
1648 static OCStackResult EHRequest(OCEntityHandlerRequest *ehRequest, OCPayloadType type,
1649 OCServerRequest *request, OCResource *resource)
1651 return FormOCEntityHandlerRequest(ehRequest,
1652 (OCRequestHandle)request,
1655 (OCResourceHandle)resource,
1659 request->payloadSize,
1660 request->numRcvdVendorSpecificHeaderOptions,
1661 request->rcvdVendorSpecificHeaderOptions,
1662 (OCObserveAction)(request->notificationFlag ? OC_OBSERVE_NO_OPTION :
1663 request->observationOption),
1670 * Find resources at the resource directory server. These resources are not local resources but
1673 * @param interfaceQuery The interface query parameter.
1674 * @param resourceTypeQuery The resourceType query parameter.
1675 * @param discPayload The payload that will be added with the resource information if found at RD.
1677 * @return ::OC_STACK_OK if any resources are found else ::OC_STACK_NO_RESOURCE.
1678 * In case if RD server is not started, it returns ::OC_STACK_NO_RESOURCE.
1680 static OCStackResult findResourcesAtRD(const char *interfaceQuery,
1681 const char *resourceTypeQuery, OCDiscoveryPayload **discPayload)
1683 OCStackResult result = OC_STACK_NO_RESOURCE;
1684 if (OCGetResourceHandleAtUri(OC_RSRVD_RD_URI) != NULL)
1686 result = OCRDDatabaseDiscoveryPayloadCreate(interfaceQuery, resourceTypeQuery,
1687 (*discPayload) ? &(*discPayload)->next : discPayload);
1689 if ((*discPayload) && (*discPayload)->resources)
1691 result = OC_STACK_OK;
1698 * Creates a discovery payload and add device id information. This information is included in all
1699 * /oic/res response.
1701 * @param payload payload that will have memory alllocated and device id information added.
1703 * @return ::OC_STACK_OK if successful in allocating memory and adding ID information.
1704 * ::OC_STACK_NO_MEMORY if failed allocating the memory.
1706 static OCStackResult discoveryPayloadCreateAndAddDeviceId(OCPayload **payload)
1710 OIC_LOG(DEBUG, TAG, "Payload is already allocated");
1714 *payload = (OCPayload *) OCDiscoveryPayloadCreate();
1715 VERIFY_PARAM_NON_NULL(TAG, *payload, "Failed adding device id to discovery payload.");
1718 OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)*payload;
1719 discPayload->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
1720 VERIFY_PARAM_NON_NULL(TAG, discPayload->sid, "Failed adding device id to discovery payload.");
1722 const char* uid = OCGetServerInstanceIDString();
1725 memcpy(discPayload->sid, uid, UUID_STRING_SIZE);
1731 OCPayloadDestroy(*payload);
1732 return OC_STACK_NO_MEMORY;
1736 * Add the common properties to the payload, they are only included in case of oic.if.baseline response.
1738 * @param discPayload payload that will have the baseline information included.
1740 * @return ::OC_STACK_OK if successful in adding all the information. ::OC_STACK_NO_MEMORY if failed
1741 * allocating the memory for the baseline information.
1743 static OCStackResult addDiscoveryBaselineCommonProperties(OCDiscoveryPayload *discPayload)
1747 OIC_LOG(ERROR, TAG, "Payload is not allocated");
1748 return OC_STACK_INVALID_PARAM;
1751 OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **)&discPayload->name);
1753 discPayload->type = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1754 VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt to discovery payload.");
1755 discPayload->type->value = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES);
1756 VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt value to discovery payload.");
1758 OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_LL);
1759 OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_DEFAULT);
1760 VERIFY_PARAM_NON_NULL(TAG, discPayload->iface, "Failed adding if to discovery payload.");
1765 return OC_STACK_NO_MEMORY;
1768 static bool isUnicast(OCServerRequest *request)
1770 bool isMulticast = request->devAddr.flags & OC_MULTICAST;
1771 return (isMulticast == false &&
1772 (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
1773 (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE));
1776 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
1778 if (!request || !resource)
1780 return OC_STACK_INVALID_PARAM;
1783 OCPayload* payload = NULL;
1784 char *interfaceQuery = NULL;
1785 char *resourceTypeQuery = NULL;
1787 OIC_LOG(INFO, TAG, "Entering HandleVirtualResource");
1789 OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
1792 if (OC_KEEPALIVE_RESOURCE_URI == virtualUriInRequest)
1794 // Received request for a keepalive
1795 OIC_LOG(INFO, TAG, "Request is for KeepAlive Request");
1796 return HandleKeepAliveRequest(request, resource);
1800 OCStackResult discoveryResult = OC_STACK_ERROR;
1801 if (request->method == OC_REST_PUT || request->method == OC_REST_POST ||
1802 request->method == OC_REST_DELETE)
1804 OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d",
1805 request->resourceUrl, request->method);
1806 return OC_STACK_UNAUTHORIZED_REQ;
1809 discoveryResult = HandleVirtualObserveRequest(request);
1810 if (discoveryResult == OC_STACK_DUPLICATE_REQUEST)
1812 // server requests are usually free'd when the response is sent out
1813 // for the request in ocserverrequest.c : HandleSingleResponse()
1814 // Since we are making an early return and not responding, the server request
1815 // needs to be deleted.
1816 FindAndDeleteServerRequest (request);
1817 discoveryResult = OC_STACK_OK;
1820 else if (discoveryResult != OC_STACK_OK)
1825 // Step 1: Generate the response to discovery request
1826 if (virtualUriInRequest == OC_WELL_KNOWN_URI
1828 || virtualUriInRequest == OC_MQ_BROKER_URI
1832 char *interfaceQuery = NULL;
1833 char *resourceTypeQuery = NULL;
1835 CAEndpoint_t *networkInfo = NULL;
1836 size_t infoSize = 0;
1838 CAResult_t caResult = CAGetNetworkInformation(&networkInfo, &infoSize);
1839 if (CA_STATUS_FAILED == caResult)
1841 OIC_LOG(ERROR, TAG, "CAGetNetworkInformation has error on parsing network infomation");
1842 return OC_STACK_ERROR;
1845 discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
1846 &interfaceQuery, &resourceTypeQuery);
1847 VERIFY_SUCCESS(discoveryResult);
1849 if (!interfaceQuery && !resourceTypeQuery)
1851 // If no query is sent, default interface is used i.e. oic.if.ll.
1852 interfaceQuery = OICStrdup(OC_RSRVD_INTERFACE_LL);
1855 discoveryResult = discoveryPayloadCreateAndAddDeviceId(&payload);
1856 VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating Discovery Payload.");
1857 VERIFY_SUCCESS(discoveryResult);
1859 OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload;
1860 if (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_DEFAULT))
1862 discoveryResult = addDiscoveryBaselineCommonProperties(discPayload);
1863 VERIFY_SUCCESS(discoveryResult);
1865 OCResourceProperty prop = OC_DISCOVERABLE;
1867 prop = (OC_MQ_BROKER_URI == virtualUriInRequest) ? OC_MQ_BROKER : prop;
1869 for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
1871 // This case will handle when no resource type and it is oic.if.ll.
1872 // Do not assume check if the query is ll
1873 if (!resourceTypeQuery &&
1874 (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
1876 // Only include discoverable type
1877 if (resource->resourceProperties & prop)
1879 discoveryResult = BuildVirtualResourceResponse(resource,
1886 else if (includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
1888 discoveryResult = BuildVirtualResourceResponse(resource,
1896 discoveryResult = OC_STACK_OK;
1899 if (discPayload->resources == NULL)
1901 discoveryResult = OC_STACK_NO_RESOURCE;
1902 OCPayloadDestroy(payload);
1908 OICFree(networkInfo);
1911 discoveryResult = findResourcesAtRD(interfaceQuery, resourceTypeQuery, (OCDiscoveryPayload **)&payload);
1914 else if (virtualUriInRequest == OC_DEVICE_URI)
1916 OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1917 VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Device URI not found.");
1918 discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, true);
1920 else if (virtualUriInRequest == OC_PLATFORM_URI)
1922 OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1923 VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Platform URI not found.");
1924 discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, false);
1926 #ifdef ROUTING_GATEWAY
1927 else if (OC_GATEWAY_URI == virtualUriInRequest)
1929 // Received request for a gateway
1930 OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
1931 discoveryResult = RMHandleGatewayRequest(request, resource);
1934 else if (OC_INTROSPECTION_URI == virtualUriInRequest)
1936 // Received request for introspection
1937 OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_URI);
1938 VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection URI not found.");
1939 discoveryResult = BuildIntrospectionResponseRepresentation(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
1940 OIC_LOG(INFO, TAG, "Request is for Introspection");
1942 else if (OC_INTROSPECTION_PAYLOAD_URI == virtualUriInRequest)
1944 // Received request for introspection payload
1945 OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_PAYLOAD_URI);
1946 VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection Payload URI not found.");
1947 discoveryResult = BuildIntrospectionPayloadResponse(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
1948 OIC_LOG(INFO, TAG, "Request is for Introspection Payload");
1951 * Step 2: Send the discovery response
1953 * Iotivity should respond to discovery requests in below manner:
1954 * 1)If query filter matching fails and discovery request is multicast,
1955 * it should NOT send any response.
1956 * 2)If query filter matching fails and discovery request is unicast,
1957 * it should send an error(RESOURCE_NOT_FOUND - 404) response.
1958 * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
1959 * request is multicast, it should NOT send any response.
1960 * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
1961 * request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
1964 #ifdef WITH_PRESENCE
1965 if ((virtualUriInRequest == OC_PRESENCE) &&
1966 (resource->resourceProperties & OC_ACTIVE))
1968 // Need to send ACK when the request is CON.
1969 if (request->qos == OC_HIGH_QOS)
1971 CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
1972 CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
1973 SendDirectStackResponse(&endpoint, request->coapID, CA_EMPTY, CA_MSG_ACKNOWLEDGE,
1974 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
1976 FindAndDeleteServerRequest(request);
1978 // Presence uses observer notification api to respond via SendPresenceNotification.
1979 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
1984 // Gateway uses the RMHandleGatewayRequest to respond to the request.
1985 if (OC_GATEWAY_URI != virtualUriInRequest)
1988 OIC_LOG_PAYLOAD(DEBUG, payload);
1989 if(discoveryResult == OC_STACK_OK)
1992 SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
1994 else // Error handling
1996 if (isUnicast(request))
1998 OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request",
1999 discoveryResult, virtualUriInRequest);
2000 SendNonPersistantDiscoveryResponse(request, resource, NULL,
2001 (discoveryResult == OC_STACK_NO_RESOURCE) ?
2002 OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
2006 // Ignoring the discovery request as per RFC 7252, Section #8.2
2007 OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send.");
2008 // the request should be removed.
2009 // since it never remove and causes a big memory waste.
2010 FindAndDeleteServerRequest(request);
2012 discoveryResult = OC_STACK_CONTINUE;
2019 OICFree(interfaceQuery);
2022 if (resourceTypeQuery)
2024 OICFree(resourceTypeQuery);
2026 OCPayloadDestroy(payload);
2028 // To ignore the message, OC_STACK_CONTINUE is sent
2029 return discoveryResult;
2032 static OCStackResult
2033 HandleDefaultDeviceEntityHandler(OCServerRequest *request)
2037 return OC_STACK_INVALID_PARAM;
2040 OCEntityHandlerResult ehResult = OC_EH_ERROR;
2041 OCEntityHandlerRequest ehRequest = {0};
2042 OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
2043 OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, NULL);
2044 VERIFY_SUCCESS(result);
2046 // At this point we know for sure that defaultDeviceHandler exists
2047 ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
2048 (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
2049 if(ehResult == OC_EH_SLOW)
2051 OIC_LOG(INFO, TAG, "This is a slow resource");
2052 request->slowFlag = 1;
2054 else if(ehResult == OC_EH_ERROR)
2056 FindAndDeleteServerRequest(request);
2058 result = EntityHandlerCodeToOCStackCode(ehResult);
2060 OCPayloadDestroy(ehRequest.payload);
2064 static OCStackResult
2065 HandleResourceWithEntityHandler(OCServerRequest *request,
2066 OCResource *resource)
2068 if(!request || ! resource)
2070 return OC_STACK_INVALID_PARAM;
2073 OCStackResult result = OC_STACK_ERROR;
2074 OCEntityHandlerResult ehResult = OC_EH_ERROR;
2075 OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
2076 ResourceObserver *resObs = NULL;
2078 OCEntityHandlerRequest ehRequest = {0};
2080 OIC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
2081 OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
2082 // check the security resource
2083 if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
2085 type = PAYLOAD_TYPE_SECURITY;
2089 result = EHRequest(&ehRequest, type, request, resource);
2090 VERIFY_SUCCESS(result);
2092 if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
2094 OIC_LOG(INFO, TAG, "No observation requested");
2095 ehFlag = OC_REQUEST_FLAG;
2097 else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER)
2099 OIC_LOG(INFO, TAG, "Observation registration requested");
2101 ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
2102 request->tokenLength);
2106 OIC_LOG (INFO, TAG, "Observer with this token already present");
2107 OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
2108 OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
2109 OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
2111 // server requests are usually free'd when the response is sent out
2112 // for the request in ocserverrequest.c : HandleSingleResponse()
2113 // Since we are making an early return and not responding, the server request
2114 // needs to be deleted.
2115 FindAndDeleteServerRequest (request);
2119 result = GenerateObserverId(&ehRequest.obsInfo.obsId);
2120 VERIFY_SUCCESS(result);
2122 result = AddObserver ((const char*)(request->resourceUrl),
2123 (const char *)(request->query),
2124 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
2125 resource, request->qos, request->acceptFormat,
2126 request->acceptVersion, &request->devAddr);
2128 if(result == OC_STACK_OK)
2130 OIC_LOG(INFO, TAG, "Added observer successfully");
2131 request->observeResult = OC_STACK_OK;
2132 ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
2134 else if (result == OC_STACK_RESOURCE_ERROR)
2136 OIC_LOG(INFO, TAG, "The Resource is not active, discoverable or observable");
2137 request->observeResult = OC_STACK_ERROR;
2138 ehFlag = OC_REQUEST_FLAG;
2142 // The error in observeResult for the request will be used when responding to this
2143 // request by omitting the observation option/sequence number.
2144 request->observeResult = OC_STACK_ERROR;
2145 OIC_LOG(ERROR, TAG, "Observer Addition failed");
2146 ehFlag = OC_REQUEST_FLAG;
2147 FindAndDeleteServerRequest(request);
2152 else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER)
2154 OIC_LOG(INFO, TAG, "Deregistering observation requested");
2156 resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
2160 // Stack does not contain this observation request
2161 // Either token is incorrect or observation list is corrupted
2162 result = OC_STACK_ERROR;
2165 ehRequest.obsInfo.obsId = resObs->observeId;
2166 ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
2168 result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
2170 if(result == OC_STACK_OK)
2172 OIC_LOG(INFO, TAG, "Removed observer successfully");
2173 request->observeResult = OC_STACK_OK;
2174 // There should be no observe option header for de-registration response.
2175 // Set as an invalid value here so we can detect it later and remove the field in response.
2176 request->observationOption = MAX_SEQUENCE_NUMBER + 1;
2180 request->observeResult = OC_STACK_ERROR;
2181 OIC_LOG(ERROR, TAG, "Observer Removal failed");
2182 FindAndDeleteServerRequest(request);
2188 result = OC_STACK_ERROR;
2192 ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
2193 if(ehResult == OC_EH_SLOW)
2195 OIC_LOG(INFO, TAG, "This is a slow resource");
2196 request->slowFlag = 1;
2198 else if(ehResult == OC_EH_ERROR)
2200 FindAndDeleteServerRequest(request);
2202 result = EntityHandlerCodeToOCStackCode(ehResult);
2204 OCPayloadDestroy(ehRequest.payload);
2208 static OCStackResult HandleCollectionResourceDefaultEntityHandler(OCServerRequest *request,
2209 OCResource *resource)
2211 if (!request || !resource)
2213 return OC_STACK_INVALID_PARAM;
2216 OCEntityHandlerRequest ehRequest = {0};
2217 OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, resource);
2218 if(result == OC_STACK_OK)
2220 result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
2223 OCPayloadDestroy(ehRequest.payload);
2228 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
2230 OCStackResult ret = OC_STACK_OK;
2232 switch (resHandling)
2234 case OC_RESOURCE_VIRTUAL:
2236 ret = HandleVirtualResource (request, resource);
2239 case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
2241 ret = HandleDefaultDeviceEntityHandler(request);
2244 case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
2246 OIC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
2247 return OC_STACK_ERROR;
2249 case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
2251 ret = HandleResourceWithEntityHandler (request, resource);
2254 case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
2256 ret = HandleResourceWithEntityHandler (request, resource);
2259 case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
2261 ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
2264 case OC_RESOURCE_NOT_SPECIFIED:
2266 ret = OC_STACK_NO_RESOURCE;
2271 OIC_LOG(INFO, TAG, "Invalid Resource Determination");
2272 return OC_STACK_ERROR;
2278 OCStackResult OCSetPlatformInfo(OCPlatformInfo info)
2280 OCResource *resource = NULL;
2281 if (!info.platformID || !info.manufacturerName)
2283 OIC_LOG(ERROR, TAG, "No value specified.");
2286 if (0 == strlen(info.platformID) || 0 == strlen(info.manufacturerName))
2288 OIC_LOG(ERROR, TAG, "The passed value cannot be empty");
2291 if ((info.manufacturerName && strlen(info.manufacturerName) > MAX_PLATFORM_NAME_LENGTH) ||
2292 (info.manufacturerUrl && strlen(info.manufacturerUrl) > MAX_PLATFORM_URL_LENGTH) ||
2293 (info.modelNumber && strlen(info.modelNumber) > MAX_PLATFORM_NAME_LENGTH) ||
2294 (info.platformVersion && strlen(info.platformVersion) > MAX_PLATFORM_NAME_LENGTH) ||
2295 (info.operatingSystemVersion && strlen(info.operatingSystemVersion) > MAX_PLATFORM_NAME_LENGTH) ||
2296 (info.hardwareVersion && strlen(info.hardwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
2297 (info.firmwareVersion && strlen(info.firmwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
2298 (info.supportUrl && strlen(info.supportUrl) > MAX_PLATFORM_URL_LENGTH))
2300 OIC_LOG(ERROR, TAG, "The passed value is bigger than permitted.");
2305 * @todo (IOT-1541) There are several versions of a UUID structure and conversion
2306 * methods scattered around the IoTivity code base. They need to be combined
2309 uint8_t uuid[UUID_SIZE];
2310 if (!OCConvertStringToUuid(info.platformID, uuid))
2312 OIC_LOG(ERROR, TAG, "Platform ID is not a UUID.");
2316 resource = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
2319 OIC_LOG(ERROR, TAG, "Platform Resource does not exist.");
2322 OIC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
2323 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_ID, info.platformID));
2324 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_NAME, info.manufacturerName));
2325 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_URL, info.manufacturerUrl);
2326 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MODEL_NUM, info.modelNumber);
2327 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_DATE, info.dateOfManufacture);
2328 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_VERSION, info.platformVersion);
2329 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_OS_VERSION, info.operatingSystemVersion);
2330 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_HARDWARE_VERSION, info.hardwareVersion);
2331 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_FIRMWARE_VERSION, info.firmwareVersion);
2332 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SUPPORT_URL, info.supportUrl);
2333 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SYSTEM_TIME, info.systemTime);
2334 OIC_LOG(INFO, TAG, "Platform parameter initialized successfully.");
2338 return OC_STACK_INVALID_PARAM;
2341 OCStackResult OCSetDeviceInfo(OCDeviceInfo info)
2343 OCResource *resource = FindResourceByUri(OC_RSRVD_DEVICE_URI);
2346 OIC_LOG(ERROR, TAG, "Device Resource does not exist.");
2349 if (!info.deviceName || info.deviceName[0] == '\0')
2351 OIC_LOG(ERROR, TAG, "Null or empty device name.");
2352 return OC_STACK_INVALID_PARAM;
2355 if (OCGetServerInstanceIDString() == NULL)
2357 OIC_LOG(INFO, TAG, "Device ID generation failed");
2361 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, info.deviceName));
2362 for (OCStringLL *temp = info.types; temp; temp = temp->next)
2366 VERIFY_SUCCESS(OCBindResourceTypeToResource(resource, temp->value));
2369 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, info.specVersion ?
2370 info.specVersion: OC_SPEC_VERSION));
2372 if (info.dataModelVersions)
2374 char *dmv = OCCreateString(info.dataModelVersions);
2375 VERIFY_PARAM_NON_NULL(TAG, dmv, "Failed allocating dataModelVersions");
2376 OCStackResult r = OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, dmv);
2382 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION,
2383 OC_DATA_MODEL_VERSION));
2385 OIC_LOG(INFO, TAG, "Device parameter initialized successfully.");
2389 return OC_STACK_ERROR;
2392 OCStackResult OCGetAttribute(const OCResource *resource, const char *attribute, void **value)
2394 if (!resource || !attribute)
2396 return OC_STACK_INVALID_PARAM;
2398 if (0 == strlen(attribute))
2400 return OC_STACK_INVALID_PARAM;
2402 for (OCAttribute *temp = resource->rsrcAttributes; temp; temp = temp->next)
2404 if (0 == strcmp(attribute, temp->attrName))
2406 // A special case as this type return OCStringLL
2407 if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
2409 *value = CloneOCStringLL((OCStringLL *)temp->attrValue);
2414 *value = OICStrdup((char *)temp->attrValue);
2419 return OC_STACK_NO_RESOURCE;
2422 OCStackResult OCGetPropertyValue(OCPayloadType type, const char *prop, void **value)
2426 return OC_STACK_INVALID_PARAM;
2428 if (strlen(prop) == 0)
2430 return OC_STACK_INVALID_PARAM;
2436 OCStackResult res = OC_STACK_NO_RESOURCE;
2437 if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
2439 const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
2440 OCResource *resource = FindResourceByUri(pathType);
2443 return OC_STACK_NO_RESOURCE;
2446 res = OCGetAttribute(resource, prop, value);
2451 static OCStackResult SetAttributeInternal(OCResource *resource,
2452 const char *attribute,
2454 bool updateDatabase)
2456 OCAttribute *resAttrib = NULL;
2458 // See if the attribute already exists in the list.
2459 for (resAttrib = resource->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
2461 if (0 == strcmp(attribute, resAttrib->attrName))
2463 // Found, free the old value.
2464 if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
2466 OCFreeOCStringLL((OCStringLL *)resAttrib->attrValue);
2470 OICFree((char *)resAttrib->attrValue);
2476 // If not already in the list, add it.
2477 if (NULL == resAttrib)
2479 resAttrib = (OCAttribute *)OICCalloc(1, sizeof(OCAttribute));
2480 VERIFY_PARAM_NON_NULL(TAG, resAttrib, "Failed allocating OCAttribute");
2481 resAttrib->attrName = OICStrdup(attribute);
2482 VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrName, "Failed allocating attribute name");
2483 resAttrib->next = resource->rsrcAttributes;
2484 resource->rsrcAttributes = resAttrib;
2487 // Fill in the new value.
2488 if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
2490 resAttrib->attrValue = OCCreateOCStringLL((char *)value);
2494 resAttrib->attrValue = OICStrdup((char *)value);
2496 VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrValue, "Failed allocating attribute value");
2498 // The resource has changed from what is stored in the database. Update the database to
2499 // reflect the new value.
2502 OCDeviceProperties *deviceProperties = NULL;
2504 OCStackResult result = CreateDeviceProperties((const char*)value, &deviceProperties);
2505 if (OC_STACK_OK == result)
2507 result = UpdateDevicePropertiesDatabase(deviceProperties);
2508 if (OC_STACK_OK != result)
2510 OIC_LOG(ERROR, TAG, "UpdateDevicePropertiesDatabase failed!");
2513 CleanUpDeviceProperties(&deviceProperties);
2517 OIC_LOG(ERROR, TAG, "CreateDeviceProperties failed!");
2524 OCDeleteResourceAttributes(resAttrib);
2525 return OC_STACK_NO_MEMORY;
2528 static OCStackResult IsDatabaseUpdateNeeded(const char *attribute, const void *value, bool *update)
2530 OCStackResult result = OC_STACK_OK;
2531 void *currentPIID = NULL;
2533 if (!attribute || !value || !update)
2535 return OC_STACK_INVALID_PARAM;
2540 // Protocol Independent ID
2541 if (0 == strcmp(OC_RSRVD_PROTOCOL_INDEPENDENT_ID, attribute))
2543 result = OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, ¤tPIID);
2544 if (OC_STACK_OK == result)
2546 // PIID has already been set on the resource and stored in the database. Check to see
2547 // if the value is changing so the database can be updated accordingly.
2548 if (0 != strcmp((char *)currentPIID, (char*)value))
2553 else if (OC_STACK_NO_RESOURCE == result)
2555 // PIID has not been set yet so we should always update the database.
2557 result = OC_STACK_OK;
2561 OIC_LOG_V(ERROR, TAG,
2562 "Call to OCGetPropertyValue for the current PIID failed with error: %d", result);
2567 OICFreeAndSetToNull(¤tPIID);
2572 OCStackResult OCSetAttribute(OCResource *resource, const char *attribute, const void *value)
2574 bool updateDatabase = false;
2576 // Check to see if we also need to update the database for this attribute. If the current
2577 // value matches what is stored in the database we can skip the update and an unnecessary
2579 if (OC_STACK_OK != IsDatabaseUpdateNeeded(attribute, value, &updateDatabase))
2581 OIC_LOG_V(WARNING, TAG,
2582 "Could not determine if a database update was needed for %s. Proceeding without updating the database.",
2584 updateDatabase = false;
2587 return SetAttributeInternal(resource, attribute, value, updateDatabase);
2590 OCStackResult OCSetPropertyValue(OCPayloadType type, const char *prop, const void *value)
2592 if (!prop || !value)
2594 return OC_STACK_INVALID_PARAM;
2596 if (strlen(prop) == 0)
2598 return OC_STACK_INVALID_PARAM;
2601 OCStackResult res = OC_STACK_ERROR;
2602 if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
2604 const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
2605 OCResource *resource = FindResourceByUri(pathType);
2608 OIC_LOG(ERROR, TAG, "Resource does not exist.");
2612 res = OCSetAttribute(resource, prop, value);