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 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 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; }
/* * @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; }
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; }