// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. #include #include #include "azure_c_shared_utility/optimize_size.h" #include "azure_c_shared_utility/gballoc.h" #include "azure_c_shared_utility/crt_abstractions.h" #include "azure_c_shared_utility/string_tokenizer.h" #include "azure_c_shared_utility/singlylinkedlist.h" #include "azure_c_shared_utility/buffer_.h" #include "azure_c_shared_utility/xlogging.h" #include "azure_c_shared_utility/httpapiex.h" #include "azure_c_shared_utility/httpapiexsas.h" #include "azure_c_shared_utility/azure_base64.h" #include "azure_c_shared_utility/uniqueid.h" #include "azure_c_shared_utility/connection_string_parser.h" #include "parson.h" #include "iothub_deviceconfiguration.h" #include "iothub_sc_version.h" MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(IOTHUB_DEVICE_CONFIGURATION_RESULT, IOTHUB_DEVICE_CONFIGURATION_RESULT_VALUES); #define UID_LENGTH 37 #define IOTHUB_DEVICE_CONFIGURATIONS_MAX_REQUEST 20 static const char* HTTP_HEADER_KEY_AUTHORIZATION = "Authorization"; static const char* HTTP_HEADER_VAL_AUTHORIZATION = " "; static const char* HTTP_HEADER_KEY_REQUEST_ID = "Request-Id"; static const char* HTTP_HEADER_KEY_USER_AGENT = "User-Agent"; static const char* HTTP_HEADER_VAL_USER_AGENT = IOTHUB_SERVICE_CLIENT_TYPE_PREFIX IOTHUB_SERVICE_CLIENT_BACKSLASH IOTHUB_SERVICE_CLIENT_VERSION; static const char* HTTP_HEADER_KEY_ACCEPT = "Accept"; static const char* HTTP_HEADER_VAL_ACCEPT = "application/json"; static const char* HTTP_HEADER_KEY_CONTENT_TYPE = "Content-Type"; static const char* HTTP_HEADER_VAL_CONTENT_TYPE = "application/json; charset=utf-8"; static const char* HTTP_HEADER_KEY_IFMATCH = "If-Match"; static const char* HTTP_HEADER_VAL_IFMATCH = "*"; #define CONFIGURATION_JSON_KEY_CONTENT "content" #define CONFIGURATION_JSON_KEY_DEVICE_CONTENT "deviceContent" #define CONFIGURATION_JSON_KEY_MODULES_CONTENT "modulesContent" #define CONFIGURATION_JSON_KEY_SYSTEM_METRICS "systemMetrics" #define CONFIGURATION_JSON_KEY_CUSTOM_METRICS "metrics" #define CONFIGURATION_JSON_KEY_METRICS_RESULTS "results" #define CONFIGURATION_JSON_KEY_METRICS_QUERIES "queries" #define CONFIGURATION_JSON_DOT_SEPARATOR "." static const char* CONFIGURATION_JSON_KEY_CONFIGURATION_ID = "id"; static const char* CONFIGURATION_JSON_KEY_SCHEMA_VERSION = "schemaVersion"; static const char* CONFIGURATION_JSON_KEY_TARGET_CONDITION = "targetCondition"; static const char* CONFIGURATION_JSON_KEY_CREATED_TIME = "createdTimeUtc"; static const char* CONFIGURATION_JSON_KEY_LAST_UPDATED_TIME = "lastUpdatedTimeUtc"; static const char* CONFIGURATION_JSON_KEY_PRIORITY = "priority"; static const char* CONFIGURATION_JSON_KEY_ETAG = "etag"; static const char* CONFIGURATION_JSON_KEY_LABELS = "labels"; static const char* CONFIGURATION_DEVICE_CONTENT_NODE_NAME = CONFIGURATION_JSON_KEY_CONTENT CONFIGURATION_JSON_DOT_SEPARATOR CONFIGURATION_JSON_KEY_DEVICE_CONTENT; static const char* CONFIGURATION_MODULES_CONTENT_NODE_NAME = CONFIGURATION_JSON_KEY_CONTENT CONFIGURATION_JSON_DOT_SEPARATOR CONFIGURATION_JSON_KEY_MODULES_CONTENT; static const char* CONFIGURATION_SYSTEM_METRICS_RESULTS_NODE_NAME = CONFIGURATION_JSON_KEY_SYSTEM_METRICS CONFIGURATION_JSON_DOT_SEPARATOR CONFIGURATION_JSON_KEY_METRICS_RESULTS; static const char* CONFIGURATION_SYSTEM_METRICS_QUERIES_NODE_NAME = CONFIGURATION_JSON_KEY_SYSTEM_METRICS CONFIGURATION_JSON_DOT_SEPARATOR CONFIGURATION_JSON_KEY_METRICS_QUERIES; static const char* CONFIGURATION_CUSTOM_METRICS_RESULTS_NODE_NAME = CONFIGURATION_JSON_KEY_CUSTOM_METRICS CONFIGURATION_JSON_DOT_SEPARATOR CONFIGURATION_JSON_KEY_METRICS_RESULTS; static const char* CONFIGURATION_CUSTOM_METRICS_QUERIES_NODE_NAME = CONFIGURATION_JSON_KEY_CUSTOM_METRICS CONFIGURATION_JSON_DOT_SEPARATOR CONFIGURATION_JSON_KEY_METRICS_QUERIES; static const char* const URL_API_VERSION = "api-version=2020-09-30"; static const char* const RELATIVE_PATH_FMT_DEVICECONFIGURATION = "/configurations/%s?%s"; static const char* const RELATIVE_PATH_FMT_DEVICECONFIGURATIONS = "/configurations/?top=%d&%s"; static const char* const RELATIVE_PATH_FMT_APPLYCONFIGURATIONCONTENT = "/devices/%s/applyConfigurationContent?%s"; static const char* const CONFIGURATION_DEFAULT_SCHEMA_VERSION = "1.0"; static const char* const CONFIGURATION_DEFAULT_ETAG = "MQ=="; typedef struct IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION_TAG { char* hostname; char* sharedAccessKey; char* keyName; } IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION; static const char* generateGuid(void) { char* result; if ((result = malloc(UID_LENGTH)) != NULL) { result[0] = '\0'; if (UniqueId_Generate(result, UID_LENGTH) != UNIQUEID_OK) { LogError("UniqueId_Generate failed"); free((void*)result); result = NULL; } } return (const char*)result; } static STRING_HANDLE createRelativePath(IOTHUB_DEVICECONFIGURATION_REQUEST_MODE iotHubDeviceConfigurationRequestMode, const char* id, size_t numberOfConfigurations) { //IOTHUB_DEVICECONFIGURATION_REQUEST_GET GET {iot hub}/configurations/{configuration id} // Get single device configuration //IOTHUB_DEVICECONFIGURATION_REQUEST_ADD PUT {iot hub}/configurations/{configuration id} // Add device configuration //IOTHUB_DEVICECONFIGURATION_REQUEST_UPDATE PUT {iot hub}/configurations/{configuration id} // Update device configuration //IOTHUB_DEVICECONFIGURATION_REQUEST_DELETE DELETE {iot hub}/configurations/{configuration id} // Delete device configuration //IOTHUB_DEVICECONFIGURATION_REQUEST_GET_LIST GET {iot hub}/configurations // Get multiple configurations //IOTHUB_DEVICECONFIGURATION_REQUEST_APPLY_CONFIGURATION_CONTENT POST {iot hub}/devices/{deviceOrModule id}/applyConfigurationContent // Apply device configuration to device or module STRING_HANDLE result; if (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_GET_LIST) { result = STRING_construct_sprintf(RELATIVE_PATH_FMT_DEVICECONFIGURATIONS, numberOfConfigurations, URL_API_VERSION); } else if ((iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_ADD) || (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_UPDATE) || (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_GET) || (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_DELETE)) { result = STRING_construct_sprintf(RELATIVE_PATH_FMT_DEVICECONFIGURATION, id, URL_API_VERSION); } else if (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_APPLY_CONFIGURATION_CONTENT) { result = STRING_construct_sprintf(RELATIVE_PATH_FMT_APPLYCONFIGURATIONCONTENT, id, URL_API_VERSION); } else { result = NULL; } return result; } static HTTP_HEADERS_HANDLE createHttpHeader(IOTHUB_DEVICECONFIGURATION_REQUEST_MODE iotHubDeviceConfigurationRequestMode) { HTTP_HEADERS_HANDLE httpHeader; const char* guid = NULL; if ((httpHeader = HTTPHeaders_Alloc()) == NULL) { LogError("HTTPHeaders_Alloc failed"); } else if (HTTPHeaders_AddHeaderNameValuePair(httpHeader, HTTP_HEADER_KEY_AUTHORIZATION, HTTP_HEADER_VAL_AUTHORIZATION) != HTTP_HEADERS_OK) { LogError("HTTPHeaders_AddHeaderNameValuePair failed for Authorization header"); HTTPHeaders_Free(httpHeader); httpHeader = NULL; } else if ((guid = generateGuid()) == NULL) { LogError("GUID creation failed"); HTTPHeaders_Free(httpHeader); httpHeader = NULL; } else if (HTTPHeaders_AddHeaderNameValuePair(httpHeader, HTTP_HEADER_KEY_REQUEST_ID, guid) != HTTP_HEADERS_OK) { LogError("HTTPHeaders_AddHeaderNameValuePair failed for RequestId header"); HTTPHeaders_Free(httpHeader); httpHeader = NULL; } else if (HTTPHeaders_AddHeaderNameValuePair(httpHeader, HTTP_HEADER_KEY_USER_AGENT, HTTP_HEADER_VAL_USER_AGENT) != HTTP_HEADERS_OK) { LogError("HTTPHeaders_AddHeaderNameValuePair failed for User-Agent header"); HTTPHeaders_Free(httpHeader); httpHeader = NULL; } else if (HTTPHeaders_AddHeaderNameValuePair(httpHeader, HTTP_HEADER_KEY_ACCEPT, HTTP_HEADER_VAL_ACCEPT) != HTTP_HEADERS_OK) { LogError("HTTPHeaders_AddHeaderNameValuePair failed for Accept header"); HTTPHeaders_Free(httpHeader); httpHeader = NULL; } else if (HTTPHeaders_AddHeaderNameValuePair(httpHeader, HTTP_HEADER_KEY_CONTENT_TYPE, HTTP_HEADER_VAL_CONTENT_TYPE) != HTTP_HEADERS_OK) { LogError("HTTPHeaders_AddHeaderNameValuePair failed for Content-Type header"); HTTPHeaders_Free(httpHeader); httpHeader = NULL; } else if ((iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_UPDATE) || (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_DELETE)) { if (HTTPHeaders_AddHeaderNameValuePair(httpHeader, HTTP_HEADER_KEY_IFMATCH, HTTP_HEADER_VAL_IFMATCH) != HTTP_HEADERS_OK) { LogError("HTTPHeaders_AddHeaderNameValuePair failed for If-Match header"); HTTPHeaders_Free(httpHeader); httpHeader = NULL; } } free((void*)guid); return httpHeader; } static IOTHUB_DEVICE_CONFIGURATION_RESULT sendHttpRequestDeviceConfiguration(IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION_HANDLE serviceClientDeviceConfigurationHandle, IOTHUB_DEVICECONFIGURATION_REQUEST_MODE iotHubDeviceConfigurationRequestMode, const char* id, BUFFER_HANDLE json, size_t maxConfigurationsCount, BUFFER_HANDLE responseBuffer) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; STRING_HANDLE uriResource = NULL; STRING_HANDLE accessKey = NULL; STRING_HANDLE keyName = NULL; HTTPAPIEX_SAS_HANDLE httpExApiSasHandle; HTTPAPIEX_HANDLE httpExApiHandle; HTTP_HEADERS_HANDLE httpHeader; if ((uriResource = STRING_construct(serviceClientDeviceConfigurationHandle->hostname)) == NULL) { LogError("STRING_construct failed for uriResource"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((accessKey = STRING_construct(serviceClientDeviceConfigurationHandle->sharedAccessKey)) == NULL) { LogError("STRING_construct failed for accessKey"); STRING_delete(uriResource); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((keyName = STRING_construct(serviceClientDeviceConfigurationHandle->keyName)) == NULL) { LogError("STRING_construct failed for keyName"); STRING_delete(accessKey); STRING_delete(uriResource); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((httpHeader = createHttpHeader(iotHubDeviceConfigurationRequestMode)) == NULL) { LogError("HttpHeader creation failed"); STRING_delete(keyName); STRING_delete(accessKey); STRING_delete(uriResource); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((httpExApiSasHandle = HTTPAPIEX_SAS_Create(accessKey, uriResource, keyName)) == NULL) { LogError("HTTPAPIEX_SAS_Create failed"); HTTPHeaders_Free(httpHeader); STRING_delete(keyName); STRING_delete(accessKey); STRING_delete(uriResource); result = IOTHUB_DEVICE_CONFIGURATION_HTTPAPI_ERROR; } else if ((httpExApiHandle = HTTPAPIEX_Create(serviceClientDeviceConfigurationHandle->hostname)) == NULL) { LogError("HTTPAPIEX_Create failed"); HTTPAPIEX_SAS_Destroy(httpExApiSasHandle); HTTPHeaders_Free(httpHeader); STRING_delete(keyName); STRING_delete(accessKey); STRING_delete(uriResource); result = IOTHUB_DEVICE_CONFIGURATION_HTTPAPI_ERROR; } else { HTTPAPI_REQUEST_TYPE httpApiRequestType = HTTPAPI_REQUEST_GET; STRING_HANDLE relativePath; unsigned int statusCode = 0; unsigned char is_error = 0; if ((iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_ADD) || (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_UPDATE)) { httpApiRequestType = HTTPAPI_REQUEST_PUT; } else if ((iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_GET) || (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_GET_LIST)) { httpApiRequestType = HTTPAPI_REQUEST_GET; } else if (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_DELETE) { httpApiRequestType = HTTPAPI_REQUEST_DELETE; } else if (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_APPLY_CONFIGURATION_CONTENT) { httpApiRequestType = HTTPAPI_REQUEST_POST; } else { is_error = 1; } if (is_error) { LogError("Invalid request type"); result = IOTHUB_DEVICE_CONFIGURATION_HTTPAPI_ERROR; } else { if ((relativePath = createRelativePath(iotHubDeviceConfigurationRequestMode, id, maxConfigurationsCount)) == NULL) { LogError("Failure creating relative path"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (HTTPAPIEX_SAS_ExecuteRequest(httpExApiSasHandle, httpExApiHandle, httpApiRequestType, STRING_c_str(relativePath), httpHeader, json, &statusCode, NULL, responseBuffer) != HTTPAPIEX_OK) { LogError("HTTPAPIEX_SAS_ExecuteRequest failed"); STRING_delete(relativePath); result = IOTHUB_DEVICE_CONFIGURATION_HTTPAPI_ERROR; } else { STRING_delete(relativePath); if ((((iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_ADD) || (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_GET) || (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_GET_LIST) || (iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_UPDATE)) && (statusCode == 200)) || ((iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_DELETE) && (statusCode == 204)) || ((iotHubDeviceConfigurationRequestMode == IOTHUB_DEVICECONFIGURATION_REQUEST_APPLY_CONFIGURATION_CONTENT) && ((statusCode == 200) || (statusCode == 204))) ) { result = IOTHUB_DEVICE_CONFIGURATION_OK; } else { LogError("Http Failure status code %d.", statusCode); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } } } HTTPAPIEX_Destroy(httpExApiHandle); HTTPAPIEX_SAS_Destroy(httpExApiSasHandle); HTTPHeaders_Free(httpHeader); STRING_delete(keyName); STRING_delete(accessKey); STRING_delete(uriResource); } return result; } static JSON_Value* createConfigurationContentPayload(const IOTHUB_DEVICE_CONFIGURATION_CONTENT* configurationContent) { JSON_Value* result = NULL; JSON_Object* root_object = NULL; if (configurationContent == NULL) { LogError("configuration cannot be null"); result = NULL; } else if (((configurationContent->deviceContent == NULL) && (configurationContent->modulesContent == NULL)) || ((configurationContent->deviceContent != NULL && strlen(configurationContent->deviceContent) == 0) && (configurationContent->modulesContent != NULL && strlen(configurationContent->modulesContent) == 0))) { LogError("both deviceContent and modulesContent cannot be NULL or empty"); result = NULL; } else if ((result = json_value_init_object()) == NULL) { LogError("json_value_init_object failed"); } else if ((root_object = json_value_get_object(result)) == NULL) { LogError("json_value_get_object failed"); result = NULL; } else if ((configurationContent->deviceContent != NULL) && (strlen(configurationContent->deviceContent) > 0) && (json_object_set_value(root_object, CONFIGURATION_JSON_KEY_DEVICE_CONTENT, json_parse_string(configurationContent->deviceContent))) != JSONSuccess) { LogError("json_object_set_string failed for deviceContent"); result = NULL; } else if ((configurationContent->modulesContent != NULL) && (strlen(configurationContent->modulesContent) > 0) && (json_object_set_value(root_object, CONFIGURATION_JSON_KEY_MODULES_CONTENT, json_parse_string(configurationContent->modulesContent))) != JSONSuccess) { LogError("json_object_set_string failed for modulesContent"); result = NULL; } return result; } static JSON_Value* createConfigurationMetricsQueriesPayload(const IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION* configurationMetricsDefinition) { JSON_Value* result = NULL; JSON_Value* new_value = NULL; JSON_Object* root_object = NULL; JSON_Object* new_value_object = NULL; if (configurationMetricsDefinition == NULL) { LogError("configuration cannot be null"); result = NULL; } else if ((result = json_value_init_object()) == NULL || (new_value = json_value_init_object()) == NULL) { LogError("json_value_init_object failed"); result = NULL; } else if ((root_object = json_value_get_object(result)) == NULL || (new_value_object = json_value_get_object(new_value)) == NULL) { LogError("json_value_get_object failed"); result = NULL; } else if (json_object_set_value(root_object, CONFIGURATION_JSON_KEY_METRICS_QUERIES, new_value) != JSONSuccess) { LogError("json_object_set_value failed for deviceContent"); result = NULL; } else { for (size_t i = 0; i < configurationMetricsDefinition->numQueries; i++) { if (json_object_set_string(new_value_object, (const char*)configurationMetricsDefinition->queryNames[i], configurationMetricsDefinition->queryStrings[i]) != JSONSuccess) { LogError("json_object_set_string failed"); result = NULL; break; } } } return result; } static JSON_Value* createConfigurationLabelsPayload(const IOTHUB_DEVICE_CONFIGURATION_LABELS* configurationLabels) { JSON_Value* result = NULL; JSON_Object* root_object = NULL; if (configurationLabels == NULL) { LogError("configurationLabels cannot be null"); result = NULL; } else if (configurationLabels->numLabels == 0) { result = NULL; } else if ((result = json_value_init_object()) == NULL) { LogError("json_value_init_object failed"); result = NULL; } else if ((root_object = json_value_get_object(result)) == NULL) { LogError("json_value_get_object failed"); result = NULL; } else { for (size_t i = 0; i < configurationLabels->numLabels; i++) { if (json_object_set_string(root_object, (const char*)configurationLabels->labelNames[i], configurationLabels->labelValues[i]) != JSONSuccess) { LogError("json_object_set_value failed"); result = NULL; break; } } } return result; } static BUFFER_HANDLE createConfigurationPayloadJson(const IOTHUB_DEVICE_CONFIGURATION* configuration) { BUFFER_HANDLE result; JSON_Value* root_value = NULL; JSON_Object* root_object = NULL; JSON_Value* configurationContentJson; JSON_Value* configurationLabelsJson; JSON_Value* metricsQueriesJson; JSON_Value* systemMetricsQueriesJson; if (configuration == NULL) { LogError("configuration cannot be null"); result = NULL; } else if (configuration->configurationId == NULL) { LogError("Configuration id cannot be NULL"); result = NULL; } else if (((configuration->content).deviceContent == NULL) && (((configuration->content).modulesContent) == NULL)) { LogError("deviceContent and modulesContent both cannot be NULL"); result = NULL; } else if ((root_value = json_value_init_object()) == NULL) { LogError("json_value_init_object failed"); result = NULL; } else if ((root_object = json_value_get_object(root_value)) == NULL) { LogError("json_value_get_object failed"); result = NULL; } else if ((json_object_set_string(root_object, CONFIGURATION_JSON_KEY_CONFIGURATION_ID, configuration->configurationId)) != JSONSuccess) { LogError("json_object_set_string failed for configurationId"); result = NULL; } else if ((json_object_set_string(root_object, CONFIGURATION_JSON_KEY_SCHEMA_VERSION, configuration->schemaVersion)) != JSONSuccess) { LogError("json_object_set_string failed for schemaVersion"); result = NULL; } else if ((json_object_set_string(root_object, CONFIGURATION_JSON_KEY_TARGET_CONDITION, configuration->targetCondition)) != JSONSuccess) { LogError("json_object_set_string failed for targetCondition"); result = NULL; } else if ((json_object_set_number(root_object, CONFIGURATION_JSON_KEY_PRIORITY, configuration->priority)) != JSONSuccess) { LogError("json_object_set_string failed for priority"); result = NULL; } else if ((json_object_set_string(root_object, CONFIGURATION_JSON_KEY_ETAG, configuration->eTag)) != JSONSuccess) { LogError("json_object_set_string failed for eTag"); result = NULL; } else if (((configuration->createdTimeUtc != NULL) && json_object_set_string(root_object, CONFIGURATION_JSON_KEY_CREATED_TIME, configuration->createdTimeUtc)) != JSONSuccess) { LogError("json_object_set_string failed for createdTimeUtc"); result = NULL; } else if (((configuration->lastUpdatedTimeUtc != NULL) && json_object_set_string(root_object, CONFIGURATION_JSON_KEY_CREATED_TIME, configuration->lastUpdatedTimeUtc)) != JSONSuccess) { LogError("json_object_set_string failed for lastUpdatedTimeUtc"); result = NULL; } else if (((configurationLabelsJson = createConfigurationLabelsPayload(&configuration->labels)) != NULL) && ((json_object_set_value(root_object, CONFIGURATION_JSON_KEY_LABELS, configurationLabelsJson)) != JSONSuccess)) { LogError("json_object_set_string failed for configurationLabelsJson"); result = NULL; } else if ((((configurationContentJson = createConfigurationContentPayload(&configuration->content)) != NULL) && ((json_object_set_value(root_object, CONFIGURATION_JSON_KEY_CONTENT, configurationContentJson)) != JSONSuccess))) { LogError("json_object_set_string failed for configurationContentJson"); result = NULL; } else if (((metricsQueriesJson = createConfigurationMetricsQueriesPayload(&configuration->metricsDefinition)) != NULL) && ((json_object_set_value(root_object, CONFIGURATION_JSON_KEY_CUSTOM_METRICS, metricsQueriesJson)) != JSONSuccess)) { LogError("json_object_set_string failed for metricsQueriesJson"); result = NULL; } else if (((systemMetricsQueriesJson = createConfigurationMetricsQueriesPayload(&configuration->systemMetricsDefinition)) != NULL) && ((json_object_set_value(root_object, CONFIGURATION_JSON_KEY_SYSTEM_METRICS, systemMetricsQueriesJson)) != JSONSuccess)) { LogError("json_object_set_string failed for systemMetricsQueriesJson"); result = NULL; } else { char* serialized_string; if ((serialized_string = json_serialize_to_string(root_value)) == NULL) { LogError("json_serialize_to_string failed"); result = NULL; } else { if ((result = BUFFER_create((const unsigned char*)serialized_string, strlen(serialized_string))) == NULL) { LogError("Buffer_Create failed"); result = NULL; } json_free_serialized_string(serialized_string); } } json_object_clear(root_object); if (root_value != NULL) json_value_free(root_value); return result; } static IOTHUB_DEVICE_CONFIGURATION_RESULT parseDeviceConfigurationLabelsJsonObject(const JSON_Object* labelsJson, IOTHUB_DEVICE_CONFIGURATION_LABELS* labels) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; STRING_HANDLE tempLabelsName = NULL; STRING_HANDLE tempLabelsValue = NULL; if (labels == NULL) { LogError("labels cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_INVALID_ARG; } else if (labelsJson == NULL) { labels->numLabels = 0; result = IOTHUB_DEVICE_CONFIGURATION_OK; } else { result = IOTHUB_DEVICE_CONFIGURATION_OK; size_t labelsCount = json_object_get_count(labelsJson); labels->numLabels = labelsCount; if (labelsCount > 0) { if ((labels->labelNames = malloc(sizeof(const char*) * labelsCount)) == NULL) { LogError("Malloc failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_RESULT labelNames"); result = IOTHUB_DEVICE_CONFIGURATION_OUT_OF_MEMORY_ERROR; } else if ((labels->labelValues = malloc(sizeof(const char*) * labelsCount)) == NULL) { LogError("Malloc failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_RESULT results"); result = IOTHUB_DEVICE_CONFIGURATION_OUT_OF_MEMORY_ERROR; } else { for (size_t i = 0; i < labelsCount; i++) { if ((tempLabelsName = STRING_construct(json_object_get_name(labelsJson, i))) == NULL) { LogError("STRING_construct failed for tempLabelsName"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (!json_object_has_value(labelsJson, STRING_c_str(tempLabelsName))) { LogError("missing result for label %s", STRING_c_str(tempLabelsName)); result = IOTHUB_DEVICE_CONFIGURATION_JSON_ERROR; } else if (mallocAndStrcpy_s((char**)&(labels->labelNames[i]), STRING_c_str(tempLabelsName)) != 0) { LogError("mallocAndStrcpy_s failed for results tempLabelsName"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((tempLabelsValue = STRING_construct(json_value_get_string(json_object_get_value_at(labelsJson, i)))) == NULL) { LogError("STRING_construct failed for tempMetricQueryString"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (mallocAndStrcpy_s((char**)&(labels->labelValues[i]), STRING_c_str(tempLabelsValue)) != 0) { LogError("mallocAndStrcpy_s failed for tempMetricQueryString"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } } } } } STRING_delete(tempLabelsName); STRING_delete(tempLabelsValue); return result; } static IOTHUB_DEVICE_CONFIGURATION_RESULT parseDeviceConfigurationMetricsJsonObject(const JSON_Object* metricResults, const JSON_Object* metricQueries, IOTHUB_DEVICE_CONFIGURATION_METRICS_RESULT* results, IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION* queries) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; size_t metricResultsCount = json_object_get_count(metricResults); size_t metricQueriesCount = json_object_get_count(metricQueries); const char* tempMetricQueryName = NULL; const char* tempMetricQueryString = NULL; if (metricResults == NULL || metricQueries == NULL || results == NULL || queries == NULL) { LogError("metricResults, metricQueries, results or queries cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_INVALID_ARG; } else { result = IOTHUB_DEVICE_CONFIGURATION_OK; results->numQueries = metricResultsCount; if (metricResultsCount > 0) { if ((results->queryNames = calloc(metricResultsCount, sizeof(const char*))) == NULL) { LogError("Calloc failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_RESULT queryNames"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((results->results = calloc(metricResultsCount, sizeof(double))) == NULL) { LogError("Calloc failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_RESULT results"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else { for (size_t i = 0; i < metricResultsCount; i++) { if ((tempMetricQueryName = json_object_get_name(metricResults, i)) == NULL) { LogError("STRING_construct failed for tempMetricQueryName"); result = IOTHUB_DEVICE_CONFIGURATION_JSON_ERROR; } else if (mallocAndStrcpy_s((char**)&(results->queryNames[i]), tempMetricQueryName) != 0) { LogError("mallocAndStrcpy_s failed for queries tempMetricQueryName"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else { results->results[i] = json_object_dotget_number(metricResults, tempMetricQueryName); } } } } queries->numQueries = metricQueriesCount; if (metricQueriesCount > 0) { if ((queries->queryNames = calloc(metricQueriesCount, sizeof(const char*))) == NULL) { LogError("Malloc failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION queryNames"); result = IOTHUB_DEVICE_CONFIGURATION_OUT_OF_MEMORY_ERROR; } else if ((queries->queryStrings = calloc(metricQueriesCount, sizeof(const char*))) == NULL) { LogError("Malloc failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION queryStrings"); result = IOTHUB_DEVICE_CONFIGURATION_OUT_OF_MEMORY_ERROR; } else { for (size_t i = 0; i < metricQueriesCount; i++) { if ((tempMetricQueryName = json_object_get_name(metricQueries, i)) == NULL) { LogError("STRING_construct failed for tempMetricQueryName"); result = IOTHUB_DEVICE_CONFIGURATION_JSON_ERROR; } else if (mallocAndStrcpy_s((char**)&(queries->queryNames[i]), tempMetricQueryName) != 0) { LogError("mallocAndStrcpy_s failed for queries tempMetricQueryName"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((tempMetricQueryString = json_value_get_string(json_object_get_value_at(metricQueries, i))) == NULL) { LogError("STRING_construct failed for tempMetricQueryString"); result = IOTHUB_DEVICE_CONFIGURATION_JSON_ERROR; } else if (mallocAndStrcpy_s((char**)&(queries->queryStrings[i]), tempMetricQueryString) != 0) { LogError("mallocAndStrcpy_s failed for tempMetricQueryString"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } } } } } return result; } static IOTHUB_DEVICE_CONFIGURATION_RESULT parseDeviceConfigurationJsonObject(JSON_Object* root_object, IOTHUB_DEVICE_CONFIGURATION* configuration) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; const char* configurationId = json_object_get_string(root_object, CONFIGURATION_JSON_KEY_CONFIGURATION_ID); const char* schemaVersion = json_object_get_string(root_object, CONFIGURATION_JSON_KEY_SCHEMA_VERSION); const char* deviceContent = json_serialize_to_string(json_object_dotget_value(root_object, CONFIGURATION_DEVICE_CONTENT_NODE_NAME)); const char* modulesContent = json_serialize_to_string(json_object_dotget_value(root_object, CONFIGURATION_MODULES_CONTENT_NODE_NAME)); const char* targetCondition = json_object_get_string(root_object, CONFIGURATION_JSON_KEY_TARGET_CONDITION); const char* createdTime = json_object_get_string(root_object, CONFIGURATION_JSON_KEY_CREATED_TIME); const char* lastUpdatedTime = json_object_get_string(root_object, CONFIGURATION_JSON_KEY_LAST_UPDATED_TIME); const char* priority = json_object_get_string(root_object, CONFIGURATION_JSON_KEY_PRIORITY); const char* eTag = json_object_get_string(root_object, CONFIGURATION_JSON_KEY_ETAG); JSON_Object* systemMetricsResults = json_object_dotget_object(root_object, CONFIGURATION_SYSTEM_METRICS_RESULTS_NODE_NAME); JSON_Object* systemMetricsQueries = json_object_dotget_object(root_object, CONFIGURATION_SYSTEM_METRICS_QUERIES_NODE_NAME); JSON_Object* customMetricsResults = json_object_dotget_object(root_object, CONFIGURATION_CUSTOM_METRICS_RESULTS_NODE_NAME); JSON_Object* customMetricsQueries = json_object_dotget_object(root_object, CONFIGURATION_CUSTOM_METRICS_QUERIES_NODE_NAME); JSON_Object* labels = json_object_dotget_object(root_object, CONFIGURATION_JSON_KEY_LABELS); if ((configurationId != NULL) && (mallocAndStrcpy_s((char**)&(configuration->configurationId), configurationId) != 0)) { LogError("mallocAndStrcpy_s failed for configurationId"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((schemaVersion != NULL) && (mallocAndStrcpy_s((char**)&(configuration->schemaVersion), schemaVersion) != 0)) { LogError("mallocAndStrcpy_s failed for schemaVersion"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((deviceContent != NULL) && (mallocAndStrcpy_s((char**)&configuration->content.deviceContent, deviceContent) != 0)) { LogError("mallocAndStrcpy_s failed for content.deviceContent"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((modulesContent != NULL) && (mallocAndStrcpy_s((char**)&configuration->content.modulesContent, modulesContent) != 0)) { LogError("mallocAndStrcpy_s failed for content.modulesContent"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((eTag != NULL) && (mallocAndStrcpy_s((char**)&configuration->eTag, eTag) != 0)) { LogError("mallocAndStrcpy_s failed for eTag"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((targetCondition != NULL) && (mallocAndStrcpy_s((char**)&configuration->targetCondition, targetCondition) != 0)) { LogError("mallocAndStrcpy_s failed for targetCondition"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((createdTime != NULL) && (mallocAndStrcpy_s((char**)&configuration->createdTimeUtc, createdTime) != 0)) { LogError("mallocAndStrcpy_s failed for createdTimeUtc"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((lastUpdatedTime != NULL) && (mallocAndStrcpy_s((char**)&configuration->lastUpdatedTimeUtc, lastUpdatedTime) != 0)) { LogError("mallocAndStrcpy_s failed for lastUpdatedTimeUtc"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else { if (priority != NULL) { configuration->priority = (int)json_object_get_number(root_object, priority); } if ((result = parseDeviceConfigurationMetricsJsonObject(systemMetricsResults, systemMetricsQueries, &(configuration->systemMetricsResult), &(configuration->systemMetricsDefinition))) != IOTHUB_DEVICE_CONFIGURATION_OK) { LogError("parseDeviceConfigurationMetricsJsonObject failed for systemMetrics"); } else if ((result = parseDeviceConfigurationMetricsJsonObject(customMetricsResults, customMetricsQueries, &(configuration->metricResult), &(configuration->metricsDefinition))) != IOTHUB_DEVICE_CONFIGURATION_OK) { LogError("parseDeviceConfigurationMetricsJsonObject failed for systemMetrics"); } else if ((result = parseDeviceConfigurationLabelsJsonObject(labels, &(configuration->labels))) != IOTHUB_DEVICE_CONFIGURATION_OK) { LogError("parseDeviceConfigurationLabelsJsonObject failed for systemMetrics"); } } return result; } void IoTHubDeviceConfiguration_FreeConfigurationMembers(IOTHUB_DEVICE_CONFIGURATION* configuration) { free((void *)configuration->configurationId); free((char *)configuration->schemaVersion); free((char *)configuration->targetCondition); free((char *)configuration->eTag); free((char *)configuration->createdTimeUtc); free((char *)configuration->lastUpdatedTimeUtc); if (configuration->content.deviceContent != NULL) free((char *)configuration->content.deviceContent); if (configuration->content.modulesContent != NULL) free((char *)configuration->content.modulesContent); if (configuration->labels.numLabels > 0) { for (size_t i = 0; i < configuration->labels.numLabels; i++) { free((void *)(configuration->labels.labelNames[i])); free((void *)(configuration->labels.labelValues[i])); } free((void *)configuration->labels.labelNames); free((void *)configuration->labels.labelValues); } if (configuration->metricsDefinition.numQueries > 0) { for (size_t i = 0; i < configuration->metricsDefinition.numQueries; i++) { free((void *)(configuration->metricsDefinition.queryNames[i])); free((void *)(configuration->metricsDefinition.queryStrings[i])); } free((void *)configuration->metricsDefinition.queryNames); free((void *)configuration->metricsDefinition.queryStrings); } if (configuration->metricResult.numQueries > 0) { for (size_t i = 0; i < configuration->metricResult.numQueries; i++) { free((void *)(configuration->metricResult.queryNames[i])); } free((void *)configuration->metricResult.queryNames); free((void *)configuration->metricResult.results); } if (configuration->systemMetricsDefinition.numQueries > 0) { for (size_t i = 0; i < configuration->systemMetricsDefinition.numQueries; i++) { free((void *)(configuration->systemMetricsDefinition.queryNames[i])); free((void *)(configuration->systemMetricsDefinition.queryStrings[i])); } free((void *)configuration->systemMetricsDefinition.queryNames); free((void *)configuration->systemMetricsDefinition.queryStrings); } if (configuration->systemMetricsResult.numQueries > 0) { for (size_t i = 0; i < configuration->systemMetricsResult.numQueries; i++) { free((void *)(configuration->systemMetricsResult.queryNames[i])); } free((void *)configuration->systemMetricsResult.queryNames); free((void *)configuration->systemMetricsResult.results); } memset(configuration, 0, sizeof(*configuration)); } static IOTHUB_DEVICE_CONFIGURATION_RESULT parseDeviceConfigurationJson(BUFFER_HANDLE jsonBuffer, IOTHUB_DEVICE_CONFIGURATION* configuration) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; if (jsonBuffer == NULL) { LogError("jsonBuffer cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (configuration == NULL) { LogError("configuration cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else { const char* bufferStr = NULL; JSON_Value* root_value = NULL; JSON_Object* root_object = NULL; if ((bufferStr = (const char*)BUFFER_u_char(jsonBuffer)) == NULL) { LogError("BUFFER_u_char failed"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (strlen(bufferStr) == 0) { LogError("Returned JSON cannot be empty"); result = IOTHUB_DEVICE_CONFIGURATION_CONFIGURATION_NOT_EXIST; } else if ((root_value = json_parse_string(bufferStr)) == NULL) { LogError("json_parse_string failed"); result = IOTHUB_DEVICE_CONFIGURATION_JSON_ERROR; } else if ((root_object = json_value_get_object(root_value)) == NULL) { LogError("json_value_get_object failed"); result = IOTHUB_DEVICE_CONFIGURATION_JSON_ERROR; } else { result = parseDeviceConfigurationJsonObject(root_object, configuration); } json_object_clear(root_object); json_value_free(root_value); } return result; } static void free_deviceConfiguration_handle(IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION* deviceConfiguration) { free(deviceConfiguration->hostname); free(deviceConfiguration->sharedAccessKey); free(deviceConfiguration->keyName); free(deviceConfiguration); } IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION_HANDLE IoTHubDeviceConfiguration_Create(IOTHUB_SERVICE_CLIENT_AUTH_HANDLE serviceClientHandle) { IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION* result; if (serviceClientHandle == NULL) { LogError("IotHubDeviceConfiguration_Create: serviceClientHandle is null"); result = NULL; } else { IOTHUB_SERVICE_CLIENT_AUTH* serviceClientAuth = (IOTHUB_SERVICE_CLIENT_AUTH*)serviceClientHandle; if (serviceClientAuth->hostname == NULL) { LogError("authInfo->hostName input parameter cannot be NULL"); result = NULL; } else if (serviceClientAuth->iothubName == NULL) { LogError("authInfo->iothubName input parameter cannot be NULL"); result = NULL; } else if (serviceClientAuth->iothubSuffix == NULL) { LogError("authInfo->iothubSuffix input parameter cannot be NULL"); result = NULL; } else if (serviceClientAuth->keyName == NULL) { LogError("authInfo->keyName input parameter cannot be NULL"); result = NULL; } else if (serviceClientAuth->sharedAccessKey == NULL) { LogError("authInfo->sharedAccessKey input parameter cannot be NULL"); result = NULL; } else { result = malloc(sizeof(IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION)); if (result == NULL) { LogError("Malloc failed for IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION"); } else { memset(result, 0, sizeof(IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION)); if (mallocAndStrcpy_s(&result->hostname, serviceClientAuth->hostname) != 0) { LogError("mallocAndStrcpy_s failed for hostName"); free_deviceConfiguration_handle(result); result = NULL; } else if (mallocAndStrcpy_s(&result->sharedAccessKey, serviceClientAuth->sharedAccessKey) != 0) { LogError("mallocAndStrcpy_s failed for sharedAccessKey"); free_deviceConfiguration_handle(result); result = NULL; } else if (mallocAndStrcpy_s(&result->keyName, serviceClientAuth->keyName) != 0) { LogError("mallocAndStrcpy_s failed for keyName"); free_deviceConfiguration_handle(result); result = NULL; } } } } return (IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION_HANDLE)result; } void IoTHubDeviceConfiguration_Destroy(IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION_HANDLE serviceClientDeviceConfigurationHandle) { if (serviceClientDeviceConfigurationHandle != NULL) { free_deviceConfiguration_handle((IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION*)serviceClientDeviceConfigurationHandle); } } static IOTHUB_DEVICE_CONFIGURATION_RESULT cloneNameValueArrays_labels(IOTHUB_DEVICE_CONFIGURATION_LABELS *source, IOTHUB_DEVICE_CONFIGURATION_LABELS *target) { IOTHUB_DEVICE_CONFIGURATION_RESULT result = IOTHUB_DEVICE_CONFIGURATION_OK; target->numLabels = source->numLabels; if (target->numLabels > 0) { if ((target->labelNames = malloc(sizeof(const char*) * target->numLabels)) == NULL) { LogError("Malloc failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION labelNames"); result = IOTHUB_DEVICE_CONFIGURATION_OUT_OF_MEMORY_ERROR; } else if ((target->labelValues = malloc(sizeof(const char*) * target->numLabels)) == NULL) { LogError("Malloc failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION labelValues"); result = IOTHUB_DEVICE_CONFIGURATION_OUT_OF_MEMORY_ERROR; } else { for (size_t i = 0; i < target->numLabels; i++) { if (mallocAndStrcpy_s((char**)&(target->labelNames[i]), source->labelNames[i]) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION labelNames"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (mallocAndStrcpy_s((char**)&(target->labelValues[i]), source->labelValues[i]) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION labelValues"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } } } } return result; } static IOTHUB_DEVICE_CONFIGURATION_RESULT cloneNameValueArrays_definitions(IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION *source, IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION *target) { IOTHUB_DEVICE_CONFIGURATION_RESULT result = IOTHUB_DEVICE_CONFIGURATION_OK; target->numQueries = source->numQueries; if (target->numQueries > 0) { if ((target->queryNames = malloc(sizeof(const char*) * target->numQueries)) == NULL) { LogError("Malloc failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION queryNames"); result = IOTHUB_DEVICE_CONFIGURATION_OUT_OF_MEMORY_ERROR; } else if ((target->queryStrings = malloc(sizeof(const char*) * target->numQueries)) == NULL) { LogError("Malloc failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION queryStrings"); result = IOTHUB_DEVICE_CONFIGURATION_OUT_OF_MEMORY_ERROR; } else { for (size_t i = 0; i < target->numQueries; i++) { if (mallocAndStrcpy_s((char**)&(target->queryNames[i]), source->queryNames[i]) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION queryNames"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (mallocAndStrcpy_s((char**)&(target->queryStrings[i]), source->queryStrings[i]) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION queryStrings"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } } } } return result; } static IOTHUB_DEVICE_CONFIGURATION_RESULT cloneNameValueArrays_results(IOTHUB_DEVICE_CONFIGURATION_METRICS_RESULT *source, IOTHUB_DEVICE_CONFIGURATION_METRICS_RESULT *target) { IOTHUB_DEVICE_CONFIGURATION_RESULT result = IOTHUB_DEVICE_CONFIGURATION_OK; target->numQueries = source->numQueries; if (target->numQueries > 0) { if ((target->queryNames = malloc(sizeof(const char*) * target->numQueries)) == NULL) { LogError("Malloc failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_RESULT queryNames"); result = IOTHUB_DEVICE_CONFIGURATION_OUT_OF_MEMORY_ERROR; } else if ((target->results = malloc(sizeof(double) * target->numQueries)) == NULL) { LogError("Malloc failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_RESULT results"); result = IOTHUB_DEVICE_CONFIGURATION_OUT_OF_MEMORY_ERROR; } else { for (size_t i = 0; i < target->numQueries; i++) { if (mallocAndStrcpy_s((char**)&(target->queryNames[i]), source->queryNames[i]) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_RESULT queryNames"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else { target->results[i] = source->results[i]; } } } } return result; } static IOTHUB_DEVICE_CONFIGURATION_RESULT clone_deviceConfiguration(IOTHUB_DEVICE_CONFIGURATION* source, IOTHUB_DEVICE_CONFIGURATION* target) { IOTHUB_DEVICE_CONFIGURATION_RESULT result = IOTHUB_DEVICE_CONFIGURATION_OK; if ((source != NULL) && (target != NULL)) { target->version = source->version; target->priority = source->priority; target->content.deviceContent = NULL; target->content.modulesContent = NULL; if (source->configurationId != NULL && mallocAndStrcpy_s((char**)&(target->configurationId), source->configurationId) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION configurationId"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (source->schemaVersion != NULL && mallocAndStrcpy_s((char**)&(target->schemaVersion), source->schemaVersion) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION schemaVersion"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (source->targetCondition != NULL && mallocAndStrcpy_s((char**)&(target->targetCondition), source->targetCondition) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION targetCondition"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (source->eTag != NULL && mallocAndStrcpy_s((char**)&(target->eTag), source->eTag) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION eTag"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (source->createdTimeUtc != NULL && mallocAndStrcpy_s((char**)&(target->createdTimeUtc), source->createdTimeUtc) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION createdTimeUtc"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (source->lastUpdatedTimeUtc != NULL && mallocAndStrcpy_s((char**)&(target->lastUpdatedTimeUtc), source->lastUpdatedTimeUtc) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION lastUpdatedTimeUtc"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (source->content.deviceContent != NULL && mallocAndStrcpy_s((char**)&(target->content.deviceContent), source->content.deviceContent) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION_CONTENT deviceContent"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (source->content.modulesContent != NULL && mallocAndStrcpy_s((char**)&(target->content.modulesContent), source->content.modulesContent) != 0) { LogError("mallocAndStrcpy_s failed for IOTHUB_DEVICE_CONFIGURATION_CONTENT modulesContent"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else { if (cloneNameValueArrays_results(&(source->metricResult), &(target->metricResult)) != IOTHUB_DEVICE_CONFIGURATION_OK || cloneNameValueArrays_results(&(source->systemMetricsResult), &(target->systemMetricsResult)) != IOTHUB_DEVICE_CONFIGURATION_OK) { LogError("Cloning failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_RESULT structures"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } if (cloneNameValueArrays_definitions(&(source->metricsDefinition), &(target->metricsDefinition)) != IOTHUB_DEVICE_CONFIGURATION_OK || cloneNameValueArrays_definitions(&(source->systemMetricsDefinition), &(target->systemMetricsDefinition)) != IOTHUB_DEVICE_CONFIGURATION_OK) { LogError("Cloning failed for IOTHUB_DEVICE_CONFIGURATION_METRICS_DEFINITION structures"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } if (cloneNameValueArrays_labels(&(source->labels), &(target->labels)) != IOTHUB_DEVICE_CONFIGURATION_OK) { LogError("Cloning failed for IOTHUB_DEVICE_CONFIGURATION_LABELS structures"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } } } return result; } static IOTHUB_DEVICE_CONFIGURATION_RESULT addDeviceConfigurationToLinkedList(IOTHUB_DEVICE_CONFIGURATION* iothubDeviceConfiguration, SINGLYLINKEDLIST_HANDLE deviceConfigurationList) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; IOTHUB_DEVICE_CONFIGURATION* deviceConfiguration = NULL; if ((deviceConfiguration = (IOTHUB_DEVICE_CONFIGURATION*)calloc(1, sizeof(IOTHUB_DEVICE_CONFIGURATION))) == NULL) { LogError("Malloc failed for deviceConfiguration"); result = IOTHUB_DEVICE_CONFIGURATION_OUT_OF_MEMORY_ERROR; } else { if (clone_deviceConfiguration(iothubDeviceConfiguration, deviceConfiguration) != IOTHUB_DEVICE_CONFIGURATION_OK) { LogError("clone_deviceConfiguration failed for deviceConfiguration"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((singlylinkedlist_add(deviceConfigurationList, deviceConfiguration)) == NULL) { LogError("singlylinkedlist_add deviceConfiguration failed"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else { result = IOTHUB_DEVICE_CONFIGURATION_OK; } if (result != IOTHUB_DEVICE_CONFIGURATION_OK) { IoTHubDeviceConfiguration_FreeConfigurationMembers(deviceConfiguration); free(deviceConfiguration); } } return result; } static void initializeDeviceConfigurationMembers(IOTHUB_DEVICE_CONFIGURATION * configuration) { if (NULL != configuration) { memset(configuration, 0, sizeof(IOTHUB_DEVICE_CONFIGURATION)); } } static IOTHUB_DEVICE_CONFIGURATION_RESULT parseDeviceConfigurationListJson(BUFFER_HANDLE jsonBuffer, SINGLYLINKEDLIST_HANDLE configurationList) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; const char* bufferStr = NULL; JSON_Value* root_value = NULL; JSON_Array* device_configuration_array = NULL; JSON_Status jsonStatus = JSONFailure; if (jsonBuffer == NULL) { LogError("jsonBuffer cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if (configurationList == NULL) { LogError("configurationList cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else { if ((bufferStr = (const char*)BUFFER_u_char(jsonBuffer)) == NULL) { LogError("BUFFER_u_char failed"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((root_value = json_parse_string(bufferStr)) == NULL) { LogError("json_parse_string failed"); result = IOTHUB_DEVICE_CONFIGURATION_JSON_ERROR; } else if ((device_configuration_array = json_value_get_array(root_value)) == NULL) { LogError("json_value_get_object failed"); result = IOTHUB_DEVICE_CONFIGURATION_JSON_ERROR; } else { result = IOTHUB_DEVICE_CONFIGURATION_OK; size_t array_count = json_array_get_count(device_configuration_array); for (size_t i = 0; i < array_count; i++) { JSON_Object* device_configuration_object = NULL; IOTHUB_DEVICE_CONFIGURATION iotHubDeviceConfiguration; if ((device_configuration_object = json_array_get_object(device_configuration_array, i)) == NULL) { LogError("json_array_get_object failed"); result = IOTHUB_DEVICE_CONFIGURATION_JSON_ERROR; } else { initializeDeviceConfigurationMembers(&iotHubDeviceConfiguration); result = parseDeviceConfigurationJsonObject(device_configuration_object, &iotHubDeviceConfiguration); if (result != IOTHUB_DEVICE_CONFIGURATION_OK) { LogError("parseDeviceConfigurationJsonObject failed"); } else { result = addDeviceConfigurationToLinkedList(&iotHubDeviceConfiguration, configurationList); if (result != IOTHUB_DEVICE_CONFIGURATION_OK) { LogError("addDeviceConfigurationToLinkedList failed"); } } } json_object_clear(device_configuration_object); IoTHubDeviceConfiguration_FreeConfigurationMembers(&iotHubDeviceConfiguration); if (result != IOTHUB_DEVICE_CONFIGURATION_OK) { break; } } } } if (device_configuration_array != NULL) { if ((jsonStatus = json_array_clear(device_configuration_array)) != JSONSuccess) { LogError("json_array_clear failed"); result = IOTHUB_DEVICE_CONFIGURATION_JSON_ERROR; } } if (root_value != NULL) { json_value_free(root_value); } if (result != IOTHUB_DEVICE_CONFIGURATION_OK) { if (configurationList != NULL) { LIST_ITEM_HANDLE itemHandle = singlylinkedlist_get_head_item(configurationList); while (itemHandle != NULL) { IOTHUB_DEVICE_CONFIGURATION* curr_item = (IOTHUB_DEVICE_CONFIGURATION *)singlylinkedlist_item_get_value(itemHandle); IoTHubDeviceConfiguration_FreeConfigurationMembers(curr_item); free(curr_item); LIST_ITEM_HANDLE lastHandle = itemHandle; itemHandle = singlylinkedlist_get_next_item(itemHandle); singlylinkedlist_remove(configurationList, lastHandle); } } } return result; } IOTHUB_DEVICE_CONFIGURATION_RESULT IoTHubDeviceConfiguration_GetConfigurations(IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION_HANDLE serviceClientDeviceConfigurationHandle, size_t maxConfigurationsCount, SINGLYLINKEDLIST_HANDLE configurations) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; if ((serviceClientDeviceConfigurationHandle == NULL) || (configurations == NULL)) { LogError("Input parameter cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_INVALID_ARG; } else if ((maxConfigurationsCount == 0) || (maxConfigurationsCount > IOTHUB_DEVICE_CONFIGURATIONS_MAX_REQUEST)) { LogError("numberOfDevices has to be between 1 and %d", IOTHUB_DEVICE_CONFIGURATIONS_MAX_REQUEST); result = IOTHUB_DEVICE_CONFIGURATION_INVALID_ARG; } else { BUFFER_HANDLE responseBuffer = NULL; if ((responseBuffer = BUFFER_new()) == NULL) { LogError("BUFFER_new failed for responseBuffer"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((result = sendHttpRequestDeviceConfiguration(serviceClientDeviceConfigurationHandle, IOTHUB_DEVICECONFIGURATION_REQUEST_GET_LIST, NULL, NULL, maxConfigurationsCount, responseBuffer)) == IOTHUB_DEVICE_CONFIGURATION_ERROR) { LogError("Failure sending HTTP request for get configuration list"); } else if (result == IOTHUB_DEVICE_CONFIGURATION_OK) { result = parseDeviceConfigurationListJson(responseBuffer, configurations); } if (responseBuffer != NULL) { BUFFER_delete(responseBuffer); } } return result; } IOTHUB_DEVICE_CONFIGURATION_RESULT IoTHubDeviceConfiguration_GetConfiguration(IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION_HANDLE serviceClientDeviceConfigurationHandle, const char* configurationId, IOTHUB_DEVICE_CONFIGURATION* configuration) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; if ((serviceClientDeviceConfigurationHandle == NULL) || (configurationId == NULL)) { LogError("Input parameter cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_INVALID_ARG; } else { initializeDeviceConfigurationMembers(configuration); BUFFER_HANDLE responseBuffer; if ((responseBuffer = BUFFER_new()) == NULL) { LogError("BUFFER_new failed for responseBuffer"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((result = sendHttpRequestDeviceConfiguration(serviceClientDeviceConfigurationHandle, IOTHUB_DEVICECONFIGURATION_REQUEST_GET, configurationId, NULL, (size_t)0, responseBuffer)) == IOTHUB_DEVICE_CONFIGURATION_ERROR) { LogError("Failure sending HTTP request for get device configuration"); } else if (result == IOTHUB_DEVICE_CONFIGURATION_OK) { result = parseDeviceConfigurationJson(responseBuffer, configuration); } BUFFER_delete(responseBuffer); } return result; } IOTHUB_DEVICE_CONFIGURATION_RESULT IoTHubDeviceConfiguration_AddConfiguration(IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION_HANDLE serviceClientDeviceConfigurationHandle, const IOTHUB_DEVICE_CONFIGURATION_ADD* configurationCreate, IOTHUB_DEVICE_CONFIGURATION* configuration) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; if ((serviceClientDeviceConfigurationHandle == NULL) || (configurationCreate == NULL) || (configuration == NULL)) { LogError("Input parameter cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_INVALID_ARG; } else { initializeDeviceConfigurationMembers(configuration); if (configurationCreate->configurationId == NULL) { LogError("configurationId cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_INVALID_ARG; } else { IOTHUB_DEVICE_CONFIGURATION* tempConfigurationInfo; if ((tempConfigurationInfo = malloc(sizeof(IOTHUB_DEVICE_CONFIGURATION))) == NULL) { LogError("Malloc failed for tempconfiguration"); result = IOTHUB_DEVICE_CONFIGURATION_OUT_OF_MEMORY_ERROR; } else { memset(tempConfigurationInfo, 0, sizeof(*tempConfigurationInfo)); tempConfigurationInfo->configurationId = configurationCreate->configurationId; tempConfigurationInfo->targetCondition = configurationCreate->targetCondition; tempConfigurationInfo->content = configurationCreate->content; tempConfigurationInfo->labels = configurationCreate->labels; tempConfigurationInfo->metricsDefinition = configurationCreate->metrics; tempConfigurationInfo->priority = configurationCreate->priority; tempConfigurationInfo->schemaVersion = CONFIGURATION_DEFAULT_SCHEMA_VERSION; tempConfigurationInfo->eTag = CONFIGURATION_DEFAULT_ETAG; BUFFER_HANDLE configurationJsonBuffer = NULL; BUFFER_HANDLE responseBuffer = NULL; if (((tempConfigurationInfo->content).deviceContent == NULL || strlen((tempConfigurationInfo->content).deviceContent) == 0) && ((tempConfigurationInfo->content).modulesContent == NULL || strlen((tempConfigurationInfo->content).modulesContent) == 0)) { LogError("both deviceContent and modulesContent cannot be null"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((configurationJsonBuffer = createConfigurationPayloadJson(tempConfigurationInfo)) == NULL) { LogError("Json creation failed"); result = IOTHUB_DEVICE_CONFIGURATION_JSON_ERROR; } else if ((responseBuffer = BUFFER_new()) == NULL) { LogError("BUFFER_new failed for responseBuffer"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((result = sendHttpRequestDeviceConfiguration(serviceClientDeviceConfigurationHandle, IOTHUB_DEVICECONFIGURATION_REQUEST_ADD, tempConfigurationInfo->configurationId, configurationJsonBuffer, (size_t)0, responseBuffer)) == IOTHUB_DEVICE_CONFIGURATION_ERROR) { LogError("Failure sending HTTP request for create device"); } else if (result == IOTHUB_DEVICE_CONFIGURATION_OK) { result = parseDeviceConfigurationJson(responseBuffer, configuration); } else { } if (responseBuffer != NULL) { BUFFER_delete(responseBuffer); } if (configurationJsonBuffer != NULL) { BUFFER_delete(configurationJsonBuffer); } } free(tempConfigurationInfo); } } return result; } IOTHUB_DEVICE_CONFIGURATION_RESULT IoTHubDeviceConfiguration_UpdateConfiguration(IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION_HANDLE serviceClientDeviceConfigurationHandle, const IOTHUB_DEVICE_CONFIGURATION* configuration) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; if ((serviceClientDeviceConfigurationHandle == NULL) || (configuration == NULL)) { LogError("Input parameter cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_INVALID_ARG; } else { if (configuration->configurationId == NULL) { LogError("configurationId cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_INVALID_ARG; } else { BUFFER_HANDLE configurationJsonBuffer = NULL; BUFFER_HANDLE responseBuffer = NULL; if ((configurationJsonBuffer = createConfigurationPayloadJson(configuration)) == NULL) { LogError("Json creation failed"); result = IOTHUB_DEVICE_CONFIGURATION_JSON_ERROR; } else if ((responseBuffer = BUFFER_new()) == NULL) { LogError("BUFFER_new failed for responseBuffer"); result = IOTHUB_DEVICE_CONFIGURATION_ERROR; } else if ((result = sendHttpRequestDeviceConfiguration(serviceClientDeviceConfigurationHandle, IOTHUB_DEVICECONFIGURATION_REQUEST_UPDATE, configuration->configurationId, configurationJsonBuffer, (size_t)0, responseBuffer)) == IOTHUB_DEVICE_CONFIGURATION_ERROR) { LogError("Failure sending HTTP request for update device configuration"); } else { } if (responseBuffer != NULL) { BUFFER_delete(responseBuffer); } if (configurationJsonBuffer != NULL) { BUFFER_delete(configurationJsonBuffer); } } } return result; } IOTHUB_DEVICE_CONFIGURATION_RESULT IoTHubDeviceConfiguration_DeleteConfiguration(IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION_HANDLE serviceClientDeviceConfigurationHandle, const char* configurationId) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; if ((serviceClientDeviceConfigurationHandle == NULL) || (configurationId == NULL)) { LogError("Input parameter cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_INVALID_ARG; } else { /*SRS_IOTHUBDEVICECONFIGURATION_38_053: [ IoTHubDeviceConfiguration_DeleteConfiguration shall create HTTP DELETE request URL using the given configurationId using the following format : url/configurations/[configurationId]?api-version ] */ /*SRS_IOTHUBDEVICECONFIGURATION_38_054: [ IoTHubDeviceConfiguration_DeleteConfiguration shall add the following headers to the created HTTP GET request : authorization=sasToken,Request-Id=,Accept=application/json,Content-Type=application/json,charset=utf-8 ] */ /*SRS_IOTHUBDEVICECONFIGURATION_38_055: [ IoTHubDeviceConfiguration_DeleteConfiguration shall create an HTTPAPIEX_SAS_HANDLE handle by calling HTTPAPIEX_SAS_Create ] */ /*SRS_IOTHUBDEVICECONFIGURATION_38_056: [ IoTHubDeviceConfiguration_DeleteConfiguration shall create an HTTPAPIEX_HANDLE handle by calling HTTPAPIEX_Create ] */ /*SRS_IOTHUBDEVICECONFIGURATION_38_057: [ IoTHubDeviceConfiguration_DeleteConfiguration shall execute the HTTP DELETE request by calling HTTPAPIEX_ExecuteRequest ] */ /*SRS_IOTHUBDEVICECONFIGURATION_38_058: [ IoTHubDeviceConfiguration_DeleteConfiguration shall verify the received HTTP status code and if it is greater than 300 then return IOTHUB_DEVICE_CONFIGURATION_HTTP_STATUS_ERROR ] */ /*SRS_IOTHUBDEVICECONFIGURATION_38_059: [ IoTHubDeviceConfiguration_DeleteConfiguration shall verify the received HTTP status code and if it is less or equal than 300 then return IOTHUB_DEVICE_CONFIGURATION_OK ] */ result = sendHttpRequestDeviceConfiguration(serviceClientDeviceConfigurationHandle, IOTHUB_DEVICECONFIGURATION_REQUEST_DELETE, configurationId, NULL, (size_t)0, NULL); } return result; } IOTHUB_DEVICE_CONFIGURATION_RESULT IoTHubDeviceConfiguration_ApplyConfigurationContentToDeviceOrModule(IOTHUB_SERVICE_CLIENT_DEVICE_CONFIGURATION_HANDLE serviceClientDeviceConfigurationHandle, const char* deviceOrModuleId, const IOTHUB_DEVICE_CONFIGURATION_CONTENT* configurationContent) { IOTHUB_DEVICE_CONFIGURATION_RESULT result; if ((serviceClientDeviceConfigurationHandle == NULL) || (deviceOrModuleId == NULL) || (configurationContent == NULL)) { LogError("Input parameter cannot be NULL"); result = IOTHUB_DEVICE_CONFIGURATION_INVALID_ARG; } else { BUFFER_HANDLE configurationJsonBuffer; JSON_Value* root_value = NULL; JSON_Object* root_object = NULL; JSON_Value* configurationContentJson; if ((configurationContent->deviceContent == NULL) && ((configurationContent->modulesContent) == NULL)) { LogError("deviceContent and modulesContent both cannot be NULL"); configurationJsonBuffer = NULL; } else if ((root_value = json_value_init_object()) == NULL) { LogError("json_value_init_object failed"); configurationJsonBuffer = NULL; } else if ((root_object = json_value_get_object(root_value)) == NULL) { LogError("json_value_get_object failed"); configurationJsonBuffer = NULL; } else if ((((configurationContentJson = createConfigurationContentPayload(configurationContent)) != NULL) && ((json_object_set_value(root_object, CONFIGURATION_JSON_KEY_CONTENT, configurationContentJson)) != JSONSuccess))) { LogError("json_object_set_string failed for configurationContentJson"); configurationJsonBuffer = NULL; } else { char* serialized_string; if ((serialized_string = json_serialize_to_string(root_value)) == NULL) { LogError("json_serialize_to_string failed"); configurationJsonBuffer = NULL; } else { if ((configurationJsonBuffer = BUFFER_create((const unsigned char*)serialized_string, strlen(serialized_string))) == NULL) { LogError("Buffer_Create failed"); } json_free_serialized_string(serialized_string); } } json_object_clear(root_object); if (root_value != NULL) json_value_free(root_value); /*SRS_IOTHUBDEVICECONFIGURATION_38_053: [ IoTHubDeviceConfiguration_ApplyConfigurationContentToDeviceOrModule shall create HTTP POST request URL using the given deviceOrModuleId using the following format : url/devices/[deviceOrModuleId]?api-version ] */ /*SRS_IOTHUBDEVICECONFIGURATION_38_054: [ IoTHubDeviceConfiguration_ApplyConfigurationContentToDeviceOrModule shall add the following headers to the created HTTP POST request : authorization=sasToken,Request-Id=,Accept=application/json,Content-Type=application/json,charset=utf-8 ] */ /*SRS_IOTHUBDEVICECONFIGURATION_38_055: [ IoTHubDeviceConfiguration_ApplyConfigurationContentToDeviceOrModule shall create an HTTPAPIEX_SAS_HANDLE handle by calling HTTPAPIEX_SAS_Create ] */ /*SRS_IOTHUBDEVICECONFIGURATION_38_056: [ IoTHubDeviceConfiguration_ApplyConfigurationContentToDeviceOrModule shall create an HTTPAPIEX_HANDLE handle by calling HTTPAPIEX_Create ] */ /*SRS_IOTHUBDEVICECONFIGURATION_38_057: [ IoTHubDeviceConfiguration_ApplyConfigurationContentToDeviceOrModule shall execute the HTTP POST request by calling HTTPAPIEX_ExecuteRequest ] */ /*SRS_IOTHUBDEVICECONFIGURATION_38_058: [ IoTHubDeviceConfiguration_ApplyConfigurationContentToDeviceOrModule shall verify the received HTTP status code and if it is greater than 300 then return IOTHUB_DEVICE_CONFIGURATION_HTTP_STATUS_ERROR ] */ /*SRS_IOTHUBDEVICECONFIGURATION_38_059: [ IoTHubDeviceConfiguration_ApplyConfigurationContentToDeviceOrModule shall verify the received HTTP status code and if it is equal to 200 or 204 then return IOTHUB_DEVICE_CONFIGURATION_OK ] */ result = sendHttpRequestDeviceConfiguration(serviceClientDeviceConfigurationHandle, IOTHUB_DEVICECONFIGURATION_REQUEST_APPLY_CONFIGURATION_CONTENT, deviceOrModuleId, configurationJsonBuffer, (size_t)0, NULL); } return result; }