static VECTOR_HANDLE VECTOR_copy(VECTOR_HANDLE vector) { VECTOR_HANDLE new_vector = VECTOR_create(sizeof(STRING_HANDLE)); size_t size = VECTOR_size(vector); for (size_t index = 0; index < size && new_vector != NULL; index++) { STRING_HANDLE* str = VECTOR_element(vector, index); if (str == NULL) { VECTOR_destroy(new_vector); new_vector = NULL; } else { STRING_HANDLE new_str = STRING_clone(*str); if (new_str == NULL) { VECTOR_destroy(new_vector); new_vector = NULL; } else { if (VECTOR_push_back(new_vector, &new_str, 1) != 0) { STRING_delete(new_str); VECTOR_destroy(new_vector); new_vector = NULL; } } } } return new_vector; }
void DataPublisher_DestroyTransaction_ReportedProperties(REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle) { /*Codes_SRS_DATA_PUBLISHER_02_025: [ If argument transactionHandle is NULL then DataPublisher_DestroyTransaction_ReportedProperties shall return. ]*/ if (transactionHandle == NULL) { LogError("invalig argument REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle=%p", transactionHandle); } else { /*Codes_SRS_DATA_PUBLISHER_02_026: [ Otherwise DataPublisher_DestroyTransaction_ReportedProperties shall free all resources associated with the reported properties transactionHandle. ]*/ REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA* handleData = (REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA*)transactionHandle; size_t i, nReportedProperties; nReportedProperties = VECTOR_size(handleData->value); for (i = 0;i < nReportedProperties;i++) { DATA_MARSHALLER_VALUE *value = *(DATA_MARSHALLER_VALUE**)VECTOR_element(handleData->value, i); Destroy_AGENT_DATA_TYPE((AGENT_DATA_TYPE*)value->Value); free((void*)value->Value); free((void*)value->PropertyPath); free((void*)value); } VECTOR_destroy(handleData->value); free(handleData); } return; }
void HTTPAPIEX_Destroy(HTTPAPIEX_HANDLE handle) { if (handle != NULL) { /*Codes_SRS_HTTPAPIEX_02_042: [HTTPAPIEX_Destroy shall free all the resources used by HTTAPIEX_HANDLE.]*/ size_t i; size_t vectorSize; HTTPAPIEX_HANDLE_DATA* handleData = (HTTPAPIEX_HANDLE_DATA*)handle; if (handleData->k == 2) { HTTPAPI_CloseConnection(handleData->httpHandle); HTTPAPI_Deinit(); } STRING_delete(handleData->hostName); vectorSize = VECTOR_size(handleData->savedOptions); for (i = 0; i < vectorSize; i++) { HTTPAPIEX_SAVED_OPTION*savedOption = VECTOR_element(handleData->savedOptions, i); free((void*)savedOption->optionName); free((void*)savedOption->value); } VECTOR_destroy(handleData->savedOptions); free(handle); } else { /*Codes_SRS_HTTPAPIEX_02_043: [If parameter handle is NULL then HTTPAPIEX_Destroy shall take no action.] */ } }
static bool signal_end_worker_thread(TRANSPORT_HANDLE_DATA * transportData, IOTHUB_CLIENT_HANDLE clientHandle) { bool okToJoin; void* element = VECTOR_find_if(transportData->clients, find_by_handle, clientHandle); if (element != NULL) { /*Codes_SRS_IOTHUBTRANSPORT_17_026: [ IoTHubTransport_EndWorkerThread shall remove clientHandlehandle from handle list. ]*/ VECTOR_erase(transportData->clients, element, 1); } /*Codes_SRS_IOTHUBTRANSPORT_17_025: [ If the worker thread does not exist, then IoTHubTransport_EndWorkerThread shall return. ]*/ if (transportData->workerThreadHandle != NULL) { if (VECTOR_size(transportData->clients) == 0) { stop_worker_thread(transportData); okToJoin = true; } else { okToJoin = false; } } else { okToJoin = false; } return okToJoin; }
void ModuleLoader_Destroy(void) { if (g_module_loaders.lock != NULL) { if (Lock(g_module_loaders.lock) != LOCK_OK) { LogError("Lock failed. Proceeding with destruction anyway."); } } if(g_module_loaders.module_loaders != NULL) { // free all module loader resources size_t length = VECTOR_size(g_module_loaders.module_loaders); for (size_t i = 0; i < length; i++) { MODULE_LOADER* loader = *((MODULE_LOADER **)VECTOR_element(g_module_loaders.module_loaders, i)); // NOTE: We free the configuration object even for default loaders because // the configuration may have been replaced by the gateway for default // loaders. /*Codes_SRS_MODULE_LOADER_13_046: [ ModuleLoader_Destroy shall invoke FreeConfiguration on every module loader's configuration field. ]*/ if (loader->configuration != NULL) { loader->api->FreeConfiguration(loader, loader->configuration); } // if this is not a default loader then free resources allocated in // add_loader_from_json if (ModuleLoader_IsDefaultLoader(loader->name) == false) { /*Codes_SRS_MODULE_LOADER_13_047: [ ModuleLoader_Destroy shall free the loader's name and the loader itself if it is not a default loader. ]*/ free((void *)loader->name); free(loader); } } /*Codes_SRS_MODULE_LOADER_13_048: [ ModuleLoader_Destroy shall destroy the loaders vector. ]*/ VECTOR_destroy(g_module_loaders.module_loaders); g_module_loaders.module_loaders = NULL; } if (g_module_loaders.lock != NULL) { if (Unlock(g_module_loaders.lock) != LOCK_OK) { LogError("Unlock failed."); } /*Codes_SRS_MODULE_LOADER_13_045: [ ModuleLoader_Destroy shall free g_module_loaders.lock if it is not NULL. ]*/ Lock_Deinit(g_module_loaders.lock); g_module_loaders.lock = NULL; } }
static int VECTOR_compare(VECTOR_HANDLE vector1, VECTOR_HANDLE vector2) { int result = 0; if (vector1 == NULL && vector2 == NULL) { result = 0; } else if (VECTOR_size(vector1) == 0 && VECTOR_size(vector2) == 0) { result = 0; } else if (vector1 == NULL) { result = __LINE__; } else if (vector2 == NULL) { result = __LINE__; } else if(VECTOR_size(vector1) != VECTOR_size(vector2)) { result = __LINE__; } else { size_t size = VECTOR_size(vector1); for (size_t index = 0; index < size && result == 0; index++) { STRING_HANDLE* str1 = (STRING_HANDLE*)VECTOR_element(vector1, index); STRING_HANDLE* str2 = (STRING_HANDLE*)VECTOR_element(vector2, index); result = STRING_compare(*str1, *str2); } } return result; }
DATA_PUBLISHER_RESULT DataPublisher_CommitTransaction_ReportedProperties(REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle, unsigned char** destination, size_t* destinationSize) { DATA_PUBLISHER_RESULT result; /*Codes_SRS_DATA_PUBLISHER_02_019: [ If argument transactionHandle is NULL then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/ /*Codes_SRS_DATA_PUBLISHER_02_020: [ If argument destination is NULL then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/ /*Codes_SRS_DATA_PUBLISHER_02_021: [ If argument destinationSize NULL then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/ if ( (transactionHandle == NULL) || (destination == NULL) || (destinationSize == NULL) ) { LogError("invalid argument REPORTED_PROPERTIES_TRANSACTION_HANDLE transactionHandle=%p, unsigned char** destination=%p, size_t* destinationSize=%p", transactionHandle, destination, destinationSize); result = DATA_PUBLISHER_INVALID_ARG; } else { /*Codes_SRS_DATA_PUBLISHER_02_031: [ If the transaction contains zero elements then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_INVALID_ARG. ]*/ REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA* handle = (REPORTED_PROPERTIES_TRANSACTION_HANDLE_DATA*)transactionHandle; if (VECTOR_size(handle->value) == 0) { LogError("cannot commit empty transaction"); result = DATA_PUBLISHER_INVALID_ARG; } else { /*Codes_SRS_DATA_PUBLISHER_02_022: [ DataPublisher_CommitTransaction_ReportedProperties shall call DataMarshaller_SendData_ReportedProperties providing the VECTOR_HANDLE holding the transacted reported properties, destination and destinationSize. ]*/ if (DataMarshaller_SendData_ReportedProperties(handle->DataPublisherInstance->DataMarshallerHandle, handle->value, destination, destinationSize) != DATA_MARSHALLER_OK) { /*Codes_SRS_DATA_PUBLISHER_02_023: [ If any error occurs then DataPublisher_CommitTransaction_ReportedProperties shall fail and return DATA_PUBLISHER_ERROR. ]*/ LogError("unable to DataMarshaller_SendData_ReportedProperties"); result = DATA_PUBLISHER_ERROR; } else { /*Codes_SRS_DATA_PUBLISHER_02_024: [ Otherwise DataPublisher_CommitTransaction_ReportedProperties shall succeed and return DATA_PUBLISHER_OK. ]*/ result = DATA_PUBLISHER_OK; } } } return result; }
/* * @brief Walks through our mappingVector to ensure it is correct for our identity map module. */ static bool IdentityMap_ValidateConfig(const VECTOR_HANDLE mappingVector) { size_t mappingSize = VECTOR_size(mappingVector); bool mappingOk; if (mappingSize == 0) { /*Codes_SRS_IDMAP_17_041: [If the configuration has no vector elements, this function shall fail and return NULL.*/ LogError("nothing for this module to do, no mapping data"); mappingOk = false; } else { mappingOk = true; size_t index; for (index = 0; (index < mappingSize) && (mappingOk != false); index++) { IDENTITY_MAP_CONFIG * element = (IDENTITY_MAP_CONFIG *)VECTOR_element(mappingVector, index); if ((element->deviceId == NULL) || (element->deviceKey == NULL) || (element->macAddress == NULL)) { /*Codes_SRS_IDMAP_17_019: [If any macAddress, deviceId or deviceKey are NULL, this function shall fail and return NULL.]*/ LogError("Empty mapping data values, mac=%p, ID=%p, key=%p", element->macAddress, element->deviceId, element->deviceKey); mappingOk = false; break; } else { if (IdentityMapConfig_IsCanonicalMAC(element->macAddress) == false) { /*Codes_SRS_IDMAP_17_006: [If any macAddress string in configuration is not a MAC address in canonical form, this function shall fail and return NULL.]*/ LogError("Non-canonical MAC Address: %s", element->macAddress); mappingOk = false; break; } } } } return mappingOk; }
static IOTHUB_CLIENT_RESULT start_worker_if_needed(TRANSPORT_HANDLE_DATA * transportData, IOTHUB_CLIENT_HANDLE clientHandle) { IOTHUB_CLIENT_RESULT result; if (transportData->workerThreadHandle == NULL) { /*Codes_SRS_IOTHUBTRANSPORT_17_018: [ If the worker thread does not exist, IoTHubTransport_StartWorkerThread shall start the thread using ThreadAPI_Create. ]*/ transportData->stopThread = 0; if (ThreadAPI_Create(&transportData->workerThreadHandle, transport_worker_thread, transportData) != THREADAPI_OK) { transportData->workerThreadHandle = NULL; } } if (transportData->workerThreadHandle != NULL) { /*Codes_SRS_IOTHUBTRANSPORT_17_020: [ IoTHubTransport_StartWorkerThread shall search for IoTHubClient clientHandle in the list of IoTHubClient handles. ]*/ bool addToList = ((VECTOR_size(transportData->clients) == 0) || (VECTOR_find_if(transportData->clients, find_by_handle, clientHandle) == NULL)); if (addToList) { /*Codes_SRS_IOTHUBTRANSPORT_17_021: [ If handle is not found, then clientHandle shall be added to the list. ]*/ if (VECTOR_push_back(transportData->clients, &clientHandle, 1) != 0) { /*Codes_SRS_IOTHUBTRANSPORT_17_042: [ If Adding to the client list fails, IoTHubTransport_StartWorkerThread shall return IOTHUB_CLIENT_ERROR. ]*/ result = IOTHUB_CLIENT_ERROR; } else { result = IOTHUB_CLIENT_OK; } } else { result = IOTHUB_CLIENT_OK; } } else { result = IOTHUB_CLIENT_ERROR; } return result; }
HTTPAPIEX_RESULT HTTPAPIEX_ExecuteRequest(HTTPAPIEX_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, HTTP_HEADERS_HANDLE requestHttpHeadersHandle, BUFFER_HANDLE requestContent, unsigned int* statusCode, HTTP_HEADERS_HANDLE responseHttpHeadersHandle, BUFFER_HANDLE responseContent) { HTTPAPIEX_RESULT result; /*Codes_SRS_HTTPAPIEX_02_006: [If parameter handle is NULL then HTTPAPIEX_ExecuteRequest shall fail and return HTTPAPIEX_INVALID_ARG.]*/ if (handle == NULL) { result = HTTPAPIEX_INVALID_ARG; LOG_HTTAPIEX_ERROR(); } else { /*Codes_SRS_HTTPAPIEX_02_007: [If parameter requestType does not indicate a valid request, HTTPAPIEX_ExecuteRequest shall fail and return HTTPAPIEX_INVALID_ARG.] */ if (requestType >= COUNT_ARG(HTTPAPI_REQUEST_TYPE_VALUES)) { result = HTTPAPIEX_INVALID_ARG; LOG_HTTAPIEX_ERROR(); } else { HTTPAPIEX_HANDLE_DATA *handleData = (HTTPAPIEX_HANDLE_DATA *)handle; /*call to buildAll*/ const char* toBeUsedRelativePath; HTTP_HEADERS_HANDLE toBeUsedRequestHttpHeadersHandle; bool isOriginalRequestHttpHeadersHandle; BUFFER_HANDLE toBeUsedRequestContent; bool isOriginalRequestContent; unsigned int* toBeUsedStatusCode; HTTP_HEADERS_HANDLE toBeUsedResponseHttpHeadersHandle; bool isOriginalResponseHttpHeadersHandle; BUFFER_HANDLE toBeUsedResponseContent; bool isOriginalResponseContent; if (buildAllRequests(handleData, requestType, relativePath, requestHttpHeadersHandle, requestContent, statusCode, responseHttpHeadersHandle, responseContent, &toBeUsedRelativePath, &toBeUsedRequestHttpHeadersHandle, &isOriginalRequestHttpHeadersHandle, &toBeUsedRequestContent, &isOriginalRequestContent, &toBeUsedStatusCode, &toBeUsedResponseHttpHeadersHandle, &isOriginalResponseHttpHeadersHandle, &toBeUsedResponseContent, &isOriginalResponseContent) != 0) { result = HTTPAPIEX_ERROR; LOG_HTTAPIEX_ERROR(); } else { /*Codes_SRS_HTTPAPIEX_02_023: [HTTPAPIEX_ExecuteRequest shall try to execute the HTTP call by ensuring the following API call sequence is respected:]*/ /*Codes_SRS_HTTPAPIEX_02_024: [If any point in the sequence fails, HTTPAPIEX_ExecuteRequest shall attempt to recover by going back to the previous step and retrying that step.]*/ /*Codes_SRS_HTTPAPIEX_02_025: [If the first step fails, then the sequence fails.]*/ /*Codes_SRS_HTTPAPIEX_02_026: [A step shall be retried at most once.]*/ /*Codes_SRS_HTTPAPIEX_02_027: [If a step has been retried then all subsequent steps shall be retried too.]*/ bool st[3] = { false, false, false }; /*the three levels of possible failure in resilient send: HTTAPI_Init, HTTPAPI_CreateConnection, HTTPAPI_ExecuteRequest*/ if (handleData->k == -1) { handleData->k = 0; } do { bool goOn; if (handleData->k > 2) { /* error */ break; } if (st[handleData->k] == true) /*already been tried*/ { goOn = false; } else { switch (handleData->k) { case 0: { if (HTTPAPI_Init() != HTTPAPI_OK) { goOn = false; } else { goOn = true; } break; } case 1: { if ((handleData->httpHandle = HTTPAPI_CreateConnection(STRING_c_str(handleData->hostName))) == NULL) { goOn = false; } else { size_t i; size_t vectorSize = VECTOR_size(handleData->savedOptions); for (i = 0; i < vectorSize; i++) { /*Codes_SRS_HTTPAPIEX_02_035: [HTTPAPIEX_ExecuteRequest shall pass all the saved options (see HTTPAPIEX_SetOption) to the newly create HTTPAPI_HANDLE in step 2 by calling HTTPAPI_SetOption.]*/ /*Codes_SRS_HTTPAPIEX_02_036: [If setting the option fails, then the failure shall be ignored.] */ HTTPAPIEX_SAVED_OPTION* option = VECTOR_element(handleData->savedOptions, i); if (HTTPAPI_SetOption(handleData->httpHandle, option->optionName, option->value) != HTTPAPI_OK) { LogError("HTTPAPI_SetOption failed when called for option %s\r\n", option->optionName); } } goOn = true; } break; } case 2: { if (HTTPAPI_ExecuteRequest(handleData->httpHandle, requestType, toBeUsedRelativePath, toBeUsedRequestHttpHeadersHandle, BUFFER_u_char(toBeUsedRequestContent), BUFFER_length(toBeUsedRequestContent), toBeUsedStatusCode, toBeUsedResponseHttpHeadersHandle, toBeUsedResponseContent) != HTTPAPI_OK) { goOn = false; } else { goOn = true; } break; } default: { /*serious error*/ goOn = false; break; } } } if (goOn) { if (handleData->k == 2) { /*Codes_SRS_HTTPAPIEX_02_028: [HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_OK when a call to HTTPAPI_ExecuteRequest has been completed successfully.]*/ result = HTTPAPIEX_OK; goto out; } else { st[handleData->k] = true; handleData->k++; st[handleData->k] = false; } } else { st[handleData->k] = false; handleData->k--; switch (handleData->k) { case 0: { HTTPAPI_Deinit(); break; } case 1: { HTTPAPI_CloseConnection(handleData->httpHandle); handleData->httpHandle = NULL; break; } case 2: { break; } default: { break; } } } } while (handleData->k >= 0); /*Codes_SRS_HTTPAPIEX_02_029: [Otherwise, HTTAPIEX_ExecuteRequest shall return HTTPAPIEX_RECOVERYFAILED.] */ result = HTTPAPIEX_RECOVERYFAILED; LogError("unable to recover sending to a working state\r\n"); out:; /*in all cases, unbuild the temporaries*/ if (isOriginalRequestContent == false) { BUFFER_delete(toBeUsedRequestContent); } if (isOriginalRequestHttpHeadersHandle == false) { HTTPHeaders_Free(toBeUsedRequestHttpHeadersHandle); } if (isOriginalResponseContent == false) { BUFFER_delete(toBeUsedResponseContent); } if (isOriginalResponseHttpHeadersHandle == false) { HTTPHeaders_Free(toBeUsedResponseHttpHeadersHandle); } } } } return result; }
/* * @brief Create an identity map module. */ static MODULE_HANDLE IdentityMap_Create(MESSAGE_BUS_HANDLE busHandle, const void* configuration) { IDENTITY_MAP_DATA* result; if (busHandle == NULL || configuration == NULL) { /*Codes_SRS_IDMAP_17_004: [If the busHandle is NULL, this function shall fail and return NULL.]*/ /*Codes_SRS_IDMAP_17_005: [If the configuration is NULL, this function shall fail and return NULL.]*/ LogError("invalid parameter (NULL)."); result = NULL; } else { VECTOR_HANDLE mappingVector = (VECTOR_HANDLE)configuration; if (IdentityMap_ValidateConfig(mappingVector) == false) { LogError("unable to validate mapping table"); result = NULL; } else { result = (IDENTITY_MAP_DATA*)malloc(sizeof(IDENTITY_MAP_DATA)); if (result == NULL) { /*Codes_SRS_IDMAP_17_010: [If IdentityMap_Create fails to allocate a new IDENTITY_MAP_DATA structure, then this function shall fail, and return NULL.]*/ LogError("Could not Allocate Module"); } else { size_t mappingSize = VECTOR_size(mappingVector); /* validation ensures the vector is greater than zero */ result->macToDevIdArray = (IDENTITY_MAP_CONFIG*)malloc(mappingSize*sizeof(IDENTITY_MAP_CONFIG)); if (result->macToDevIdArray == NULL) { /*Codes_SRS_IDMAP_17_011: [If IdentityMap_Create fails to create memory for the macToDeviceArray, then this function shall fail and return NULL.*/ LogError("Could not allocate mac to device mapping table"); free(result); result = NULL; } else { result->devIdToMacArray = (IDENTITY_MAP_CONFIG*)malloc(mappingSize*sizeof(IDENTITY_MAP_CONFIG)); if (result->devIdToMacArray == NULL) { /*Codes_SRS_IDMAP_17_042: [ If IdentityMap_Create fails to create memory for the deviceToMacArray, then this function shall fail and return NULL. */ LogError("Could not allocate devicee to mac mapping table"); free(result->macToDevIdArray); free(result); result = NULL; } else { size_t index; size_t failureIndex = mappingSize; for (index = 0; index < mappingSize; index++) { IDENTITY_MAP_CONFIG * element = (IDENTITY_MAP_CONFIG *)VECTOR_element(mappingVector, index); IDENTITY_MAP_CONFIG * dest = &(result->macToDevIdArray[index]); IDENTITYMAP_RESULT copyResult; copyResult = IdentityMapConfig_CopyDeep(dest, element); if (copyResult != IDENTITYMAP_OK) { failureIndex = index; break; } dest = &(result->devIdToMacArray[index]); copyResult = IdentityMapConfig_CopyDeep(dest, element); if (copyResult != IDENTITYMAP_OK) { IdentityMapConfig_Free(&(result->macToDevIdArray[index])); failureIndex = index; break; } } if (failureIndex < mappingSize) { /*Codes_SRS_IDMAP_17_012: [If IdentityMap_Create fails to add a MAC address triplet to the macToDeviceArray, then this function shall fail, release all resources, and return NULL.]*/ /*Codes_SRS_IDMAP_17_043: [ If IdentityMap_Create fails to add a MAC address triplet to the deviceToMacArray, then this function shall fail, release all resources, and return NULL. */ for (index = 0; index < failureIndex; index++) { IdentityMapConfig_Free(&(result->macToDevIdArray[index])); IdentityMapConfig_Free(&(result->devIdToMacArray[index])); } free(result->macToDevIdArray); free(result->devIdToMacArray); free(result); result = NULL; } else { /*Codes_SRS_IDMAP_17_003: [Upon success, this function shall return a valid pointer to a MODULE_HANDLE.]*/ qsort(result->macToDevIdArray, mappingSize, sizeof(IDENTITY_MAP_CONFIG), IdentityMapConfig_MacCompare); qsort(result->devIdToMacArray, mappingSize, sizeof(IDENTITY_MAP_CONFIG), IdentityMapConfig_IdCompare); result->mappingSize = mappingSize; result->busHandle = busHandle; } } } } } } return result; }