static void sendHttpRequestMethodExpectedCalls() { STRICT_EXPECTED_CALL(environment_get_variable(IGNORED_PTR_ARG)).CallCannotFail(); STRICT_EXPECTED_CALL(HTTPHeaders_Alloc()); STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_malloc(IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(UniqueId_Generate(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(HTTPHeaders_AddHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); //cannot fail STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_SasToken(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(HTTPHeaders_ReplaceHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(HTTPHeaders_ReplaceHeaderNameValuePair(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); //cannot fail STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); //cannot fail STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); //cannot fail STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(HTTPAPIEX_Create(IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(IoTHubClient_Auth_Get_TrustBundle(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(HTTPAPIEX_SetOption(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(HTTPAPIEX_ExecuteRequest(IGNORED_PTR_ARG, HTTPAPI_REQUEST_POST, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, NULL, IGNORED_PTR_ARG)); STRICT_EXPECTED_CALL(HTTPHeaders_Free(IGNORED_PTR_ARG)); //cannot fail STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG)); //cannot fail STRICT_EXPECTED_CALL(HTTPAPIEX_Destroy(IGNORED_PTR_ARG)); //cannot fail STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG)); //cannot fail }
static int prov_sc_get_record(PROVISIONING_SERVICE_CLIENT_HANDLE prov_client, const char* id, void** handle_ptr, HANDLE_FUNCTION_VECTOR vector, const char* path_format) { int result = 0; if (prov_client == NULL) { LogError("Invalid Provisioning Client Handle"); result = __FAILURE__; } else if (id == NULL) { LogError("Invalid id"); result = __FAILURE__; } else if (handle_ptr == NULL) { LogError("Invalid handle"); result = __FAILURE__; } else { STRING_HANDLE registration_path = create_registration_path(path_format, id); if (registration_path == NULL) { LogError("Failed to construct a registration path"); result = __FAILURE__; } else { HTTP_HEADERS_HANDLE request_headers; if ((request_headers = construct_http_headers(prov_client, NULL, HTTP_CLIENT_REQUEST_GET)) == NULL) { LogError("Failure constructing http headers"); result = __FAILURE__; } else { result = rest_call(prov_client, HTTP_CLIENT_REQUEST_GET, STRING_c_str(registration_path), request_headers, NULL); if (result == 0) { void* handle; if ((handle = vector.deserializeFromJson(prov_client->response)) == NULL) { LogError("Failure constructing new enrollment structure from json response"); result = __FAILURE__; } *handle_ptr = handle; } clear_response(prov_client); } HTTPHeaders_Free(request_headers); } STRING_delete(registration_path); } return result; }
/*any other code is error*/ static int buildRequestHttpHeadersHandle(HTTPAPIEX_HANDLE_DATA *handleData, BUFFER_HANDLE requestContent, HTTP_HEADERS_HANDLE originalRequestHttpHeadersHandle, bool* isOriginalRequestHttpHeadersHandle, HTTP_HEADERS_HANDLE* toBeUsedRequestHttpHeadersHandle) { int result; if (originalRequestHttpHeadersHandle != NULL) { *toBeUsedRequestHttpHeadersHandle = originalRequestHttpHeadersHandle; *isOriginalRequestHttpHeadersHandle = true; } else { /*Codes_SRS_HTTPAPIEX_02_009: [If parameter requestHttpHeadersHandle is NULL then HTTPAPIEX_ExecuteRequest shall allocate a temporary internal instance of HTTPHEADERS, shall add to that instance the following headers Host:{hostname} - as it was indicated by the call to HTTPAPIEX_Create API call Content-Length:the size of the requestContent parameter, and use this instance to all the subsequent calls to HTTPAPI_ExecuteRequest as parameter httpHeadersHandle.] */ *isOriginalRequestHttpHeadersHandle = false; *toBeUsedRequestHttpHeadersHandle = HTTPHeaders_Alloc(); } if (*toBeUsedRequestHttpHeadersHandle == NULL) { result = __LINE__; LogError("unable to HTTPHeaders_Alloc\r\n"); } else { char temp[22]; (void)size_tToString(temp, 22, BUFFER_length(requestContent)); /*cannot fail, MAX_uint64 has 19 digits*/ /*Codes_SRS_HTTPAPIEX_02_011: [If parameter requestHttpHeadersHandle is not NULL then HTTPAPIEX_ExecuteRequest shall create or update the following headers of the request: Host:{hostname} Content-Length:the size of the requestContent parameter, and shall use the so constructed HTTPHEADERS object to all calls to HTTPAPI_ExecuteRequest as parameter httpHeadersHandle.] */ /*Codes_SRS_HTTPAPIEX_02_009: [If parameter requestHttpHeadersHandle is NULL then HTTPAPIEX_ExecuteRequest shall allocate a temporary internal instance of HTTPHEADERS, shall add to that instance the following headers Host:{hostname} - as it was indicated by the call to HTTPAPIEX_Create API call Content-Length:the size of the requestContent parameter, and use this instance to all the subsequent calls to HTTPAPI_ExecuteRequest as parameter httpHeadersHandle.] */ if (!( (HTTPHeaders_ReplaceHeaderNameValuePair(*toBeUsedRequestHttpHeadersHandle, "Host", STRING_c_str(handleData->hostName)) == HTTP_HEADERS_OK) && (HTTPHeaders_ReplaceHeaderNameValuePair(*toBeUsedRequestHttpHeadersHandle, "Content-Length", temp) == HTTP_HEADERS_OK) )) { if (! *isOriginalRequestHttpHeadersHandle) { HTTPHeaders_Free(*toBeUsedRequestHttpHeadersHandle); } *toBeUsedRequestHttpHeadersHandle = NULL; result = __LINE__; } else { result = 0; } } return result; }
void prov_sc_destroy(PROVISIONING_SERVICE_CLIENT_HANDLE prov_client) { if (prov_client != NULL) { free(prov_client->provisioning_service_uri); free(prov_client->key_name); free(prov_client->access_key); free(prov_client->response); HTTPHeaders_Free(prov_client->response_headers); free(prov_client->certificate); free(prov_client); } }
static int prov_sc_delete_record_by_param(PROVISIONING_SERVICE_CLIENT_HANDLE prov_client, const char* id, const char* etag, const char* path_format) { int result = 0; if (prov_client == NULL) { LogError("Invalid Provisioning Client Handle"); result = __FAILURE__; } else if (id == NULL) { LogError("Invalid Id"); result = __FAILURE__; } else { STRING_HANDLE registration_path = create_registration_path(path_format, id); if (registration_path == NULL) { LogError("Failed to construct a registration path"); result = __FAILURE__; } else { HTTP_HEADERS_HANDLE request_headers; if ((request_headers = construct_http_headers(prov_client, etag, HTTP_CLIENT_REQUEST_DELETE)) == NULL) { LogError("Failure constructing http headers"); result = __FAILURE__; } else { result = rest_call(prov_client, HTTP_CLIENT_REQUEST_DELETE, STRING_c_str(registration_path), request_headers, NULL); clear_response(prov_client); } HTTPHeaders_Free(request_headers); } STRING_delete(registration_path); } return result; }
static int prov_sc_query_records(PROVISIONING_SERVICE_CLIENT_HANDLE prov_client, PROVISIONING_QUERY_SPECIFICATION* query_spec, char** cont_token_ptr, PROVISIONING_QUERY_RESPONSE** query_res_ptr, const char* path_format) { int result = 0; if (prov_client == NULL) { LogError("Invalid Provisioning Client Handle"); result = __FAILURE__; } else if (query_spec == NULL || query_spec->version != PROVISIONING_QUERY_SPECIFICATION_VERSION_1) { LogError("Invalid Query details"); result = __FAILURE__; } else if (cont_token_ptr == NULL) { LogError("Invalid Continuation Token pointer"); result = __FAILURE__; } else if (query_res_ptr == NULL) { LogError("Invalid Query Response pointer"); result = __FAILURE__; } else { char* content = NULL; //do not serialize the query specification if there is no query_string (i.e. DRS query) if ((query_spec->query_string != NULL) && ((content = querySpecification_serializeToJson(query_spec)) == NULL)) { LogError("Failure serializing query specification"); result = __FAILURE__; } else { STRING_HANDLE registration_path = create_registration_path(path_format, query_spec->registration_id); if (registration_path == NULL) { LogError("Failed to construct a registration path"); result = __FAILURE__; } else { HTTP_HEADERS_HANDLE request_headers; if ((request_headers = construct_http_headers(prov_client, NULL, HTTP_CLIENT_REQUEST_POST)) == NULL) { LogError("Failure constructing http headers"); result = __FAILURE__; } else if ((add_query_headers(request_headers, query_spec->page_size, *cont_token_ptr)) != 0) { LogError("Failure adding query headers"); result = __FAILURE__; } else { result = rest_call(prov_client, HTTP_CLIENT_REQUEST_POST, STRING_c_str(registration_path), request_headers, content); if (result == 0) { const char* resp_type = NULL; char* new_cont_token = NULL; PROVISIONING_QUERY_TYPE type; if (get_response_headers(prov_client, &new_cont_token, &resp_type) != 0) { LogError("Failure reading response headers"); result = __FAILURE__; } else if ((type = queryType_stringToEnum(resp_type)) == QUERY_TYPE_INVALID) { LogError("Failure to parse response type"); result = __FAILURE__; } else if ((*query_res_ptr = queryResponse_deserializeFromJson(prov_client->response, type)) == NULL) { LogError("Failure deserializing query response"); result = __FAILURE__; } free(*cont_token_ptr); *cont_token_ptr = new_cont_token; } else { LogError("Rest call failed"); } clear_response(prov_client); } HTTPHeaders_Free(request_headers); } STRING_delete(registration_path); } free(content); } return result; }
static int prov_sc_run_bulk_operation(PROVISIONING_SERVICE_CLIENT_HANDLE prov_client, PROVISIONING_BULK_OPERATION* bulk_op, PROVISIONING_BULK_OPERATION_RESULT** bulk_res_ptr , const char* path_format) { int result = 0; if (prov_client == NULL) { LogError("Invalid Provisioning Client Handle"); result = __FAILURE__; } else if (bulk_op == NULL) { LogError("Invalid Bulk Op"); result = __FAILURE__; } else if (bulk_op->version != PROVISIONING_BULK_OPERATION_VERSION_1) { LogError("Invalid Bulk Op Version #"); result = __FAILURE__; } else if (bulk_res_ptr == NULL) { LogError("Invalid Bulk Op Result pointer"); result = __FAILURE__; } else { char* content; if ((content = bulkOperation_serializeToJson(bulk_op)) == NULL) { LogError("Failure serializing bulk operation"); result = __FAILURE__; } else { STRING_HANDLE registration_path = create_registration_path(path_format, NULL); if (registration_path == NULL) { LogError("Failed to construct a registration path"); result = __FAILURE__; } else { HTTP_HEADERS_HANDLE request_headers; if ((request_headers = construct_http_headers(prov_client, NULL, HTTP_CLIENT_REQUEST_POST)) == NULL) { LogError("Failure constructing http headers"); result = __FAILURE__; } else { result = rest_call(prov_client, HTTP_CLIENT_REQUEST_POST, STRING_c_str(registration_path), request_headers, content); if (result == 0) { if ((*bulk_res_ptr = bulkOperationResult_deserializeFromJson(prov_client->response)) == NULL) { LogError("Failure deserializing bulk operation result"); result = __FAILURE__; } } else { LogError("Rest call failed"); } clear_response(prov_client); } HTTPHeaders_Free(request_headers); } STRING_delete(registration_path); } free(content); } return result; }
static int prov_sc_create_or_update_record(PROVISIONING_SERVICE_CLIENT_HANDLE prov_client, void** handle_ptr, HANDLE_FUNCTION_VECTOR vector, const char* path_format) { int result = 0; void* handle; if (prov_client == NULL) { LogError("Invalid Provisioning Client Handle"); result = __FAILURE__; } else if ((handle_ptr == NULL) || ((handle = *handle_ptr) == NULL)) { LogError("Invalid handle"); result = __FAILURE__; } else { char* content; if ((content = vector.serializeToJson(handle)) == NULL) { LogError("Failure serializing enrollment"); result = __FAILURE__; } else { STRING_HANDLE registration_path = NULL; const char* id = NULL; if ((id = vector.getId(handle)) == NULL) { LogError("Given model does not have a valid ID"); result = __FAILURE__; } else if ((registration_path = create_registration_path(path_format, id)) == NULL) { LogError("Failed to construct a registration path"); result = __FAILURE__; } else { HTTP_HEADERS_HANDLE request_headers; if ((request_headers = construct_http_headers(prov_client, vector.getEtag(handle), HTTP_CLIENT_REQUEST_PUT)) == NULL) { LogError("Failure constructing headers"); result = __FAILURE__; } else { result = rest_call(prov_client, HTTP_CLIENT_REQUEST_PUT, STRING_c_str(registration_path), request_headers, content); if (result == 0) { INDIVIDUAL_ENROLLMENT_HANDLE new_handle; if ((new_handle = vector.deserializeFromJson(prov_client->response)) == NULL) { LogError("Failure constructing new enrollment structure from json response"); result = __FAILURE__; } //Free the user submitted enrollment, and replace the pointer reference to a new enrollment from the provisioning service vector.destroy(handle); *handle_ptr = new_handle; } else { LogError("Rest call failed"); } clear_response(prov_client); } HTTPHeaders_Free(request_headers); } STRING_delete(registration_path); } free(content); } return result; }
static IOTHUB_DEVICE_METHOD_RESULT sendHttpRequestDeviceMethod(IOTHUB_SERVICE_CLIENT_DEVICE_METHOD_HANDLE serviceClientDeviceMethodHandle, IOTHUB_DEVICEMETHOD_REQUEST_MODE iotHubDeviceMethodRequestMode, const char* deviceName, BUFFER_HANDLE deviceJsonBuffer, BUFFER_HANDLE responseBuffer) { IOTHUB_DEVICE_METHOD_RESULT result; STRING_HANDLE uriResouce; STRING_HANDLE accessKey; STRING_HANDLE keyName; HTTPAPIEX_SAS_HANDLE httpExApiSasHandle; HTTPAPIEX_HANDLE httpExApiHandle; HTTP_HEADERS_HANDLE httpHeader; if ((uriResouce = STRING_construct(serviceClientDeviceMethodHandle->hostname)) == NULL) { LogError("STRING_construct failed for uriResource"); result = IOTHUB_DEVICE_METHOD_ERROR; } else if ((accessKey = STRING_construct(serviceClientDeviceMethodHandle->sharedAccessKey)) == NULL) { LogError("STRING_construct failed for accessKey"); STRING_delete(uriResouce); result = IOTHUB_DEVICE_METHOD_ERROR; } else if ((keyName = STRING_construct(serviceClientDeviceMethodHandle->keyName)) == NULL) { LogError("STRING_construct failed for keyName"); STRING_delete(accessKey); STRING_delete(uriResouce); result = IOTHUB_DEVICE_METHOD_ERROR; } else if ((httpHeader = createHttpHeader()) == NULL) { LogError("HttpHeader creation failed"); STRING_delete(keyName); STRING_delete(accessKey); STRING_delete(uriResouce); result = IOTHUB_DEVICE_METHOD_ERROR; } else if ((httpExApiSasHandle = HTTPAPIEX_SAS_Create(accessKey, uriResouce, keyName)) == NULL) { LogError("HTTPAPIEX_SAS_Create failed"); HTTPHeaders_Free(httpHeader); STRING_delete(keyName); STRING_delete(accessKey); STRING_delete(uriResouce); result = IOTHUB_DEVICE_METHOD_HTTPAPI_ERROR; } else if ((httpExApiHandle = HTTPAPIEX_Create(serviceClientDeviceMethodHandle->hostname)) == NULL) { LogError("HTTPAPIEX_Create failed"); HTTPAPIEX_SAS_Destroy(httpExApiSasHandle); HTTPHeaders_Free(httpHeader); STRING_delete(keyName); STRING_delete(accessKey); STRING_delete(uriResouce); result = IOTHUB_DEVICE_METHOD_HTTPAPI_ERROR; } else { HTTPAPI_REQUEST_TYPE httpApiRequestType = HTTPAPI_REQUEST_GET; STRING_HANDLE relativePath; unsigned int statusCode = 0; unsigned char is_error = 0; if (iotHubDeviceMethodRequestMode == IOTHUB_DEVICEMETHOD_REQUEST_INVOKE) { httpApiRequestType = HTTPAPI_REQUEST_POST; } else { is_error = 1; } if (is_error) { LogError("Invalid request type"); result = IOTHUB_DEVICE_METHOD_HTTPAPI_ERROR; } else { if ((relativePath = createRelativePath(iotHubDeviceMethodRequestMode, deviceName)) == NULL) { LogError("Failure creating relative path"); result = IOTHUB_DEVICE_METHOD_ERROR; } else if (HTTPAPIEX_SAS_ExecuteRequest(httpExApiSasHandle, httpExApiHandle, httpApiRequestType, STRING_c_str(relativePath), httpHeader, deviceJsonBuffer, &statusCode, NULL, responseBuffer) != HTTPAPIEX_OK) { LogError("HTTPAPIEX_SAS_ExecuteRequest failed"); STRING_delete(relativePath); result = IOTHUB_DEVICE_METHOD_HTTPAPI_ERROR; } else { STRING_delete(relativePath); if (statusCode == 200) { result = IOTHUB_DEVICE_METHOD_OK; } else { LogError("Http Failure status code %d.", statusCode); result = IOTHUB_DEVICE_METHOD_ERROR; } } } HTTPAPIEX_Destroy(httpExApiHandle); HTTPAPIEX_SAS_Destroy(httpExApiSasHandle); HTTPHeaders_Free(httpHeader); STRING_delete(keyName); STRING_delete(accessKey); STRING_delete(uriResouce); } return result; }
BLOB_RESULT Blob_UploadFromSasUri(const char* SASURI, const unsigned char* source, size_t size) { BLOB_RESULT result; /*Codes_SRS_BLOB_02_001: [ If SASURI is NULL then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ if (SASURI == NULL) { LogError("parameter SASURI is NULL"); result = BLOB_INVALID_ARG; } else { /*Codes_SRS_BLOB_02_002: [ If source is NULL and size is not zero then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ if ( (size > 0) && (source == NULL) ) { LogError("combination of source = %p and size = %zd is invalid", source, size); result = BLOB_INVALID_ARG; } /*Codes_SRS_BLOB_02_003: [ If size is bigger or equal to 64M then Blob_UploadFromSasUri shall fail and return BLOB_NOT_IMPLEMENTED. ]*/ else if (size >= 64 * 1024 * 1024) { LogError("upload of files greater than 64M is not implemented"); result = BLOB_NOT_IMPLEMENTED; } else { /*Codes_SRS_BLOB_02_004: [ Blob_UploadFromSasUri shall copy from SASURI the hostname to a new const char*. ]*/ /*to find the hostname, the following logic is applied:*/ /*the hostname starts at the first character after ":\\"*/ /*the hostname ends at the first character before the next "\" after ":\\"*/ const char* hostnameBegin = strstr(SASURI, ":\\\\"); if (hostnameBegin == NULL) { /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ LogError("hostname cannot be determined"); result = BLOB_INVALID_ARG; } else { hostnameBegin += 3; /*have to skip 3 characters which are ":\\"*/ const char* hostnameEnd = strchr(hostnameBegin, '\\'); if (hostnameEnd == NULL) { /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ LogError("hostname cannot be determined"); result = BLOB_INVALID_ARG; } else { size_t hostnameSize = hostnameEnd - hostnameBegin; char* hostname = (char*)malloc(hostnameSize + 1); /*+1 because of '\0' at the end*/ if (hostname == NULL) { /*Codes_SRS_BLOB_02_016: [ If the hostname copy cannot be made then then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("oom - out of memory"); result = BLOB_ERROR; } else { HTTPAPIEX_HANDLE httpApiExHandle; memcpy(hostname, hostnameBegin, hostnameSize); hostname[hostnameSize] = '\0'; /*Codes_SRS_BLOB_02_006: [ Blob_UploadFromSasUri shall create a new HTTPAPI_EX_HANDLE by calling HTTPAPIEX_Create passing the hostname. ]*/ httpApiExHandle = HTTPAPIEX_Create(hostname); if (httpApiExHandle == NULL) { /*Codes_SRS_BLOB_02_007: [ If HTTPAPIEX_Create fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR. ]*/ LogError("unable to create a HTTPAPIEX_HANDLE"); result = BLOB_ERROR; } else { /*Codes_SRS_BLOB_02_008: [ Blob_UploadFromSasUri shall compute the relative path of the request from the SASURI parameter. ]*/ const char* relativePath = hostnameEnd; /*this is where the relative path begins in the SasUri*/ /*Codes_SRS_BLOB_02_010: [ Blob_UploadFromSasUri shall create a BUFFER_HANDLE from source and size parameters. ]*/ BUFFER_HANDLE requestBuffer = BUFFER_create(source, size); if (requestBuffer == NULL) { /*Codes_SRS_BLOB_02_011: [ If any of the previous steps related to building the HTTPAPI_EX_ExecuteRequest parameters fails, then Blob_UploadFromSasUri shall fail and return BLOB_ERROR. ]*/ LogError("unable to BUFFER_create"); result = BLOB_ERROR; } else { /*Codes_SRS_BLOB_02_009: [ Blob_UploadFromSasUri shall create an HTTP_HEADERS_HANDLE for the request HTTP headers carrying the following headers: ]*/ HTTP_HEADERS_HANDLE requestHttpHeaders = HTTPHeaders_Alloc(); if (requestHttpHeaders == NULL) { /*Codes_SRS_BLOB_02_011: [ If any of the previous steps related to building the HTTPAPI_EX_ExecuteRequest parameters fails, then Blob_UploadFromSasUri shall fail and return BLOB_ERROR. ]*/ LogError("unable to HTTPHeaders_Alloc"); result = BLOB_ERROR; } else { if (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "x-ms-blob-type", "BlockBlob") != HTTP_HEADERS_OK) { /*Codes_SRS_BLOB_02_011: [ If any of the previous steps related to building the HTTPAPI_EX_ExecuteRequest parameters fails, then Blob_UploadFromSasUri shall fail and return BLOB_ERROR. ]*/ LogError("unable to HTTPHeaders_AddHeaderNameValuePair"); result = BLOB_ERROR; } else { int statusCode; /*Codes_SRS_BLOB_02_012: [ Blob_UploadFromSasUri shall call HTTPAPIEX_ExecuteRequest passing the parameters previously build. ]*/ if (HTTPAPIEX_ExecuteRequest(httpApiExHandle, HTTPAPI_REQUEST_PUT, relativePath, requestHttpHeaders, requestBuffer, &statusCode, NULL, NULL) != HTTPAPIEX_OK) { /*Codes_SRS_BLOB_02_013: [ If HTTPAPIEX_ExecuteRequest fails, then Blob_UploadFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/ LogError("failed to HTTPAPIEX_ExecuteRequest"); result = BLOB_HTTP_ERROR; } else { if (statusCode >= 300) { /*Codes_SRS_BLOB_02_014: [ If the statusCode returned by HTTPAPIEX_ExecuteRequest is greater or equal to 300, then Blob_UploadFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/ LogError("server returns %d HTTP code", statusCode); result = BLOB_HTTP_ERROR; } else { /*Codes_SRS_BLOB_02_015: [ Otherwise, HTTPAPIEX_ExecuteRequest shall succeed and return BLOB_OK. ]*/ result = BLOB_OK; } } } HTTPHeaders_Free(requestHttpHeaders); } BUFFER_delete(requestBuffer); } HTTPAPIEX_Destroy(httpApiExHandle); } free(hostname); } } } } } return result; }
BLOB_RESULT Blob_UploadFromSasUri(const char* SASURI, const unsigned char* source, size_t size, unsigned int* httpStatus, BUFFER_HANDLE httpResponse) { BLOB_RESULT result; /*Codes_SRS_BLOB_02_001: [ If SASURI is NULL then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ if (SASURI == NULL) { LogError("parameter SASURI is NULL"); result = BLOB_INVALID_ARG; } else { /*Codes_SRS_BLOB_02_002: [ If source is NULL and size is not zero then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ if ( (size > 0) && (source == NULL) ) { LogError("combination of source = %p and size = %zu is invalid", source, size); result = BLOB_INVALID_ARG; } /*Codes_SRS_BLOB_02_034: [ If size is bigger than 50000*4*1024*1024 then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ else if (size > 50000ULL * 4 * 1024 * 1024) /*https://msdn.microsoft.com/en-us/library/azure/dd179467.aspx says "Each block can be a different size, up to a maximum of 4 MB, and a block blob can include a maximum of 50,000 blocks."*/ { LogError("size too big (%zu)", size); result = BLOB_INVALID_ARG; } else { /*Codes_SRS_BLOB_02_017: [ Blob_UploadFromSasUri shall copy from SASURI the hostname to a new const char* ]*/ /*Codes_SRS_BLOB_02_004: [ Blob_UploadFromSasUri shall copy from SASURI the hostname to a new const char*. ]*/ /*to find the hostname, the following logic is applied:*/ /*the hostname starts at the first character after "://"*/ /*the hostname ends at the first character before the next "/" after "://"*/ const char* hostnameBegin = strstr(SASURI, "://"); if (hostnameBegin == NULL) { /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ LogError("hostname cannot be determined"); result = BLOB_INVALID_ARG; } else { hostnameBegin += 3; /*have to skip 3 characters which are "://"*/ const char* hostnameEnd = strchr(hostnameBegin, '/'); if (hostnameEnd == NULL) { /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ LogError("hostname cannot be determined"); result = BLOB_INVALID_ARG; } else { size_t hostnameSize = hostnameEnd - hostnameBegin; char* hostname = (char*)malloc(hostnameSize + 1); /*+1 because of '\0' at the end*/ if (hostname == NULL) { /*Codes_SRS_BLOB_02_016: [ If the hostname copy cannot be made then then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("oom - out of memory"); result = BLOB_ERROR; } else { HTTPAPIEX_HANDLE httpApiExHandle; memcpy(hostname, hostnameBegin, hostnameSize); hostname[hostnameSize] = '\0'; /*Codes_SRS_BLOB_02_006: [ Blob_UploadFromSasUri shall create a new HTTPAPI_EX_HANDLE by calling HTTPAPIEX_Create passing the hostname. ]*/ /*Codes_SRS_BLOB_02_018: [ Blob_UploadFromSasUri shall create a new HTTPAPI_EX_HANDLE by calling HTTPAPIEX_Create passing the hostname. ]*/ httpApiExHandle = HTTPAPIEX_Create(hostname); if (httpApiExHandle == NULL) { /*Codes_SRS_BLOB_02_007: [ If HTTPAPIEX_Create fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR. ]*/ LogError("unable to create a HTTPAPIEX_HANDLE"); result = BLOB_ERROR; } else { /*Codes_SRS_BLOB_02_008: [ Blob_UploadFromSasUri shall compute the relative path of the request from the SASURI parameter. ]*/ /*Codes_SRS_BLOB_02_019: [ Blob_UploadFromSasUri shall compute the base relative path of the request from the SASURI parameter. ]*/ const char* relativePath = hostnameEnd; /*this is where the relative path begins in the SasUri*/ if (size < 64 * 1024 * 1024) /*code path for sizes <64MB*/ { /*Codes_SRS_BLOB_02_010: [ Blob_UploadFromSasUri shall create a BUFFER_HANDLE from source and size parameters. ]*/ BUFFER_HANDLE requestBuffer = BUFFER_create(source, size); if (requestBuffer == NULL) { /*Codes_SRS_BLOB_02_011: [ If any of the previous steps related to building the HTTPAPI_EX_ExecuteRequest parameters fails, then Blob_UploadFromSasUri shall fail and return BLOB_ERROR. ]*/ LogError("unable to BUFFER_create"); result = BLOB_ERROR; } else { /*Codes_SRS_BLOB_02_009: [ Blob_UploadFromSasUri shall create an HTTP_HEADERS_HANDLE for the request HTTP headers carrying the following headers: ]*/ HTTP_HEADERS_HANDLE requestHttpHeaders = HTTPHeaders_Alloc(); if (requestHttpHeaders == NULL) { /*Codes_SRS_BLOB_02_011: [ If any of the previous steps related to building the HTTPAPI_EX_ExecuteRequest parameters fails, then Blob_UploadFromSasUri shall fail and return BLOB_ERROR. ]*/ LogError("unable to HTTPHeaders_Alloc"); result = BLOB_ERROR; } else { if (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "x-ms-blob-type", "BlockBlob") != HTTP_HEADERS_OK) { /*Codes_SRS_BLOB_02_011: [ If any of the previous steps related to building the HTTPAPI_EX_ExecuteRequest parameters fails, then Blob_UploadFromSasUri shall fail and return BLOB_ERROR. ]*/ LogError("unable to HTTPHeaders_AddHeaderNameValuePair"); result = BLOB_ERROR; } else { /*Codes_SRS_BLOB_02_012: [ Blob_UploadFromSasUri shall call HTTPAPIEX_ExecuteRequest passing the parameters previously build, httpStatus and httpResponse ]*/ if (HTTPAPIEX_ExecuteRequest(httpApiExHandle, HTTPAPI_REQUEST_PUT, relativePath, requestHttpHeaders, requestBuffer, httpStatus, NULL, httpResponse) != HTTPAPIEX_OK) { /*Codes_SRS_BLOB_02_013: [ If HTTPAPIEX_ExecuteRequest fails, then Blob_UploadFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/ LogError("failed to HTTPAPIEX_ExecuteRequest"); result = BLOB_HTTP_ERROR; } else { /*Codes_SRS_BLOB_02_015: [ Otherwise, HTTPAPIEX_ExecuteRequest shall succeed and return BLOB_OK. ]*/ result = BLOB_OK; } } HTTPHeaders_Free(requestHttpHeaders); } BUFFER_delete(requestBuffer); } } else /*code path for size >= 64MB*/ { size_t toUpload = size; /*Codes_SRS_BLOB_02_028: [ Blob_UploadFromSasUri shall construct an XML string with the following content: ]*/ STRING_HANDLE xml = STRING_construct("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<BlockList>"); /*the XML "build as we go"*/ if (xml == NULL) { /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("failed to STRING_construct"); result = BLOB_HTTP_ERROR; } else { /*Codes_SRS_BLOB_02_021: [ For every block of 4MB the following operations shall happen: ]*/ unsigned int blockID = 0; result = BLOB_ERROR; int isError = 0; /*used to cleanly exit the loop*/ do { /*setting this block size*/ size_t thisBlockSize = (toUpload > BLOCK_SIZE) ? BLOCK_SIZE : toUpload; /*Codes_SRS_BLOB_02_020: [ Blob_UploadFromSasUri shall construct a BASE64 encoded string from the block ID (000000... 0499999) ]*/ char temp[7]; /*this will contain 000000... 049999*/ if (sprintf(temp, "%6u", (unsigned int)blockID) != 6) /*produces 000000... 049999*/ { /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("failed to sprintf"); result = BLOB_ERROR; isError = 1; } else { STRING_HANDLE blockIdString = Base64_Encode_Bytes((const unsigned char*)temp, 6); if (blockIdString == NULL) { /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("unable to Base64_Encode_Bytes"); result = BLOB_ERROR; isError = 1; } else { /*add the blockId base64 encoded to the XML*/ if (!( (STRING_concat(xml, "<Latest>")==0) && (STRING_concat_with_STRING(xml, blockIdString)==0) && (STRING_concat(xml, "</Latest>") == 0) )) { /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("unable to STRING_concat"); result = BLOB_ERROR; isError = 1; } else { /*Codes_SRS_BLOB_02_022: [ Blob_UploadFromSasUri shall construct a new relativePath from following string: base relativePath + "&comp=block&blockid=BASE64 encoded string of blockId" ]*/ STRING_HANDLE newRelativePath = STRING_construct(relativePath); if (newRelativePath == NULL) { /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("unable to STRING_construct"); result = BLOB_ERROR; isError = 1; } else { if (!( (STRING_concat(newRelativePath, "&comp=block&blockid=") == 0) && (STRING_concat_with_STRING(newRelativePath, blockIdString) == 0) )) { /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("unable to STRING concatenate"); result = BLOB_ERROR; isError = 1; } else { /*Codes_SRS_BLOB_02_023: [ Blob_UploadFromSasUri shall create a BUFFER_HANDLE from source and size parameters. ]*/ BUFFER_HANDLE requestContent = BUFFER_create(source + (size - toUpload), thisBlockSize); if (requestContent == NULL) { /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("unable to BUFFER_create"); result = BLOB_ERROR; isError = 1; } else { /*Codes_SRS_BLOB_02_024: [ Blob_UploadFromSasUri shall call HTTPAPIEX_ExecuteRequest with a PUT operation, passing httpStatus and httpResponse. ]*/ if (HTTPAPIEX_ExecuteRequest( httpApiExHandle, HTTPAPI_REQUEST_PUT, STRING_c_str(newRelativePath), NULL, requestContent, httpStatus, NULL, httpResponse) != HTTPAPIEX_OK ) { /*Codes_SRS_BLOB_02_025: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/ LogError("unable to HTTPAPIEX_ExecuteRequest"); result = BLOB_HTTP_ERROR; isError = 1; } else if (*httpStatus >= 300) { /*Codes_SRS_BLOB_02_026: [ Otherwise, if HTTP response code is >=300 then Blob_UploadFromSasUri shall succeed and return BLOB_OK. ]*/ LogError("HTTP status from storage does not indicate success (%d)", (int)*httpStatus); result = BLOB_OK; isError = 1; } else { /*Codes_SRS_BLOB_02_027: [ Otherwise Blob_UploadFromSasUri shall continue execution. ]*/ } BUFFER_delete(requestContent); } } STRING_delete(newRelativePath); } } STRING_delete(blockIdString); } } blockID++; toUpload -= thisBlockSize; } while ((toUpload > 0) && !isError); if (isError) { /*do nothing, it will be reported "as is"*/ } else { /*complete the XML*/ if (STRING_concat(xml, "</BlockList>") != 0) { /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("failed to STRING_concat"); result = BLOB_ERROR; } else { /*Codes_SRS_BLOB_02_029: [Blob_UploadFromSasUri shall construct a new relativePath from following string : base relativePath + "&comp=blocklist"]*/ STRING_HANDLE newRelativePath = STRING_construct(relativePath); if (newRelativePath == NULL) { /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("failed to STRING_construct"); result = BLOB_ERROR; } else { if (STRING_concat(newRelativePath, "&comp=blocklist") != 0) { /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("failed to STRING_concat"); result = BLOB_ERROR; } else { /*Codes_SRS_BLOB_02_030: [ Blob_UploadFromSasUri shall call HTTPAPIEX_ExecuteRequest with a PUT operation, passing the new relativePath, httpStatus and httpResponse and the XML string as content. ]*/ const char* s = STRING_c_str(xml); BUFFER_HANDLE xmlAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s)); if (xmlAsBuffer == NULL) { /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ LogError("failed to BUFFER_create"); result = BLOB_ERROR; } else { if (HTTPAPIEX_ExecuteRequest( httpApiExHandle, HTTPAPI_REQUEST_PUT, STRING_c_str(newRelativePath), NULL, xmlAsBuffer, httpStatus, NULL, httpResponse ) != HTTPAPIEX_OK) { /*Codes_SRS_BLOB_02_031: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/ LogError("unable to HTTPAPIEX_ExecuteRequest"); result = BLOB_HTTP_ERROR; } else { /*Codes_SRS_BLOB_02_032: [ Otherwise, Blob_UploadFromSasUri shall succeed and return BLOB_OK. ]*/ result = BLOB_OK; } BUFFER_delete(xmlAsBuffer); } } STRING_delete(newRelativePath); } } } STRING_delete(xml); } } HTTPAPIEX_Destroy(httpApiExHandle); } free(hostname); } } } } } 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; }
static int buildAllRequests(HTTPAPIEX_HANDLE_DATA* 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, 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) { int result; (void)requestType; /*Codes_SRS_HTTPAPIEX_02_013: [If requestContent is NULL then HTTPAPIEX_ExecuteRequest shall behave as if a buffer of zero size would have been used, that is, it shall call HTTPAPI_ExecuteRequest with parameter content = NULL and contentLength = 0.]*/ /*Codes_SRS_HTTPAPIEX_02_014: [If requestContent is not NULL then its content and its size shall be used for parameters content and contentLength of HTTPAPI_ExecuteRequest.] */ if (buildBufferIfNotExist(requestContent, isOriginalRequestContent, toBeUsedRequestContent) != 0) { result = __LINE__; LogError("unable to build the request content\r\n"); } else { if (buildRequestHttpHeadersHandle(handle, *toBeUsedRequestContent, requestHttpHeadersHandle, isOriginalRequestHttpHeadersHandle, toBeUsedRequestHttpHeadersHandle) != 0) { /*Codes_SRS_HTTPAPIEX_02_010: [If any of the operations in SRS_HTTAPIEX_02_009 fails, then HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_ERROR.] */ result = __LINE__; if (*isOriginalRequestContent == false) { BUFFER_delete(*toBeUsedRequestContent); } LogError("unable to build the request http headers handle\r\n"); } else { /*Codes_SRS_HTTPAPIEX_02_008: [If parameter relativePath is NULL then HTTPAPIEX_INVALID_ARG shall not assume a relative path - that is, it will assume an empty path ("").] */ if (relativePath == NULL) { *toBeUsedRelativePath = ""; } else { *toBeUsedRelativePath = relativePath; } /*Codes_SRS_HTTPAPIEX_02_015: [If statusCode is NULL then HTTPAPIEX_ExecuteRequest shall not write in statusCode the HTTP status code, and it will use a temporary internal int for parameter statusCode to the calls of HTTPAPI_ExecuteRequest.] */ if (statusCode == NULL) { /*Codes_SRS_HTTPAPIEX_02_016: [If statusCode is not NULL then If statusCode is NULL then HTTPAPIEX_ExecuteRequest shall use it for parameter statusCode to the calls of HTTPAPI_ExecuteRequest.] */ *toBeUsedStatusCode = &dummyStatusCode; } else { *toBeUsedStatusCode = statusCode; } /*Codes_SRS_HTTPAPIEX_02_017: [If responseHeaders handle is NULL then HTTPAPIEX_ExecuteRequest shall create a temporary internal instance of HTTPHEADERS object and use that for responseHeaders parameter of HTTPAPI_ExecuteRequest call.] */ /*Codes_SRS_HTTPAPIEX_02_019: [If responseHeaders is not NULL, then then HTTPAPIEX_ExecuteRequest shall use that object as parameter responseHeaders of HTTPAPI_ExecuteRequest call.] */ if (buildResponseHttpHeadersHandle(responseHttpHeadersHandle, isOriginalResponseHttpHeadersHandle, toBeUsedResponseHttpHeadersHandle) != 0) { /*Codes_SRS_HTTPAPIEX_02_018: [If creating the temporary http headers in SRS_HTTPAPIEX_02_017 fails then HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_ERROR.] */ result = __LINE__; if (*isOriginalRequestContent == false) { BUFFER_delete(*toBeUsedRequestContent); } if (*isOriginalRequestHttpHeadersHandle == false) { HTTPHeaders_Free(*toBeUsedRequestHttpHeadersHandle); } LogError("unable to build response content\r\n"); } else { /*Codes_SRS_HTTPAPIEX_02_020: [If responseContent is NULL then HTTPAPIEX_ExecuteRequest shall create a temporary internal BUFFER object and use that as parameter responseContent of HTTPAPI_ExecuteRequest call.] */ /*Codes_SRS_HTTPAPIEX_02_022: [If responseContent is not NULL then HTTPAPIEX_ExecuteRequest use that as parameter responseContent of HTTPAPI_ExecuteRequest call.] */ if (buildBufferIfNotExist(responseContent, isOriginalResponseContent, toBeUsedResponseContent) != 0) { /*Codes_SRS_HTTPAPIEX_02_021: [If creating the BUFFER_HANDLE in SRS_HTTPAPIEX_02_020 fails, then HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_ERROR.] */ result = __LINE__; if (*isOriginalRequestContent == false) { BUFFER_delete(*toBeUsedRequestContent); } if (*isOriginalRequestHttpHeadersHandle == false) { HTTPHeaders_Free(*toBeUsedRequestHttpHeadersHandle); } if (*isOriginalResponseHttpHeadersHandle == false) { HTTPHeaders_Free(*toBeUsedResponseHttpHeadersHandle); } LogError("unable to build response content\r\n"); } else { result = 0; } } } } return result; }
static BUFFER_HANDLE sendDeviceRegistryInfo(IOTHUB_ACCOUNT_INFO* accountInfo, BUFFER_HANDLE deviceBuffer, HTTPAPI_REQUEST_TYPE requestType) { BUFFER_HANDLE result; STRING_HANDLE accessKey = STRING_construct(accountInfo->sharedAccessKey); STRING_HANDLE uriResouce = STRING_construct(accountInfo->hostname); STRING_HANDLE keyName = STRING_construct(accountInfo->keyName); if (accessKey != NULL && uriResouce != NULL && keyName != NULL) { HTTPAPIEX_SAS_HANDLE httpHandle = HTTPAPIEX_SAS_Create(accessKey, uriResouce, keyName); if (httpHandle != NULL) { HTTPAPIEX_HANDLE httpExApi = HTTPAPIEX_Create(accountInfo->hostname); if (httpExApi == NULL) { LogError("Failure creating httpApiEx with hostname: %s.\r\n", accountInfo->hostname); result = NULL; } else { char relativePath[256]; if (sprintf_s(relativePath, 256, RELATIVE_PATH_FMT, accountInfo->deviceId, URL_API_VERSION) <= 0) { LogError("Failure creating relative path.\r\n"); result = NULL; } else { unsigned int statusCode = 0; // Send PUT method to url HTTP_HEADERS_HANDLE httpHeader = getContentHeaders((deviceBuffer == NULL) ? true : false); if (httpHeader == NULL) { result = NULL; } else { BUFFER_HANDLE responseContent = BUFFER_new(); if (HTTPAPIEX_SAS_ExecuteRequest(httpHandle, httpExApi, requestType, relativePath, httpHeader, deviceBuffer, &statusCode, NULL, responseContent) != HTTPAPIEX_OK) { LogError("Failure calling HTTPAPIEX_SAS_ExecuteRequest.\r\n"); result = NULL; } else { // 409 means the device is already created so we don't need // to create another one. if (statusCode != 409 && statusCode > 300) { LogError("Http Failure status code %d.\r\n", statusCode); BUFFER_delete(responseContent); result = NULL; } else { result = responseContent; } } } HTTPHeaders_Free(httpHeader); } HTTPAPIEX_Destroy(httpExApi); } HTTPAPIEX_SAS_Destroy(httpHandle); } else { LogError("Http Failure with HTTPAPIEX_SAS_Create.\r\n"); result = NULL; } } STRING_delete(accessKey); STRING_delete(uriResouce); STRING_delete(keyName); return result; }