int prov_transport_common_mqtt_close(PROV_DEVICE_TRANSPORT_HANDLE handle)
{
    int result;
    if (handle == NULL)
    {
        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_011: [ If handle is NULL, prov_transport_common_mqtt_close shall return a non-zero value. ] */
        LogError("Invalid parameter specified handle: %p", handle);
        result = __FAILURE__;
    }
    else
    {
        PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
        BUFFER_delete(mqtt_info->ek);
        mqtt_info->ek = NULL;
        BUFFER_delete(mqtt_info->srk);
        mqtt_info->srk = NULL;
        free(mqtt_info->registration_id);
        mqtt_info->registration_id = NULL;

        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_012: [ prov_transport_common_mqtt_close shall close all connection associated with mqtt communication. ] */
        if (mqtt_client_disconnect(mqtt_info->mqtt_client, NULL, NULL) == 0)
        {
            mqtt_client_dowork(mqtt_info->mqtt_client);
        }
        xio_destroy(mqtt_info->transport_io);
        mqtt_info->transport_io = NULL;

        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_013: [ On success prov_transport_common_mqtt_close shall return a zero value. ] */
        mqtt_info->mqtt_state = MQTT_STATE_IDLE;
        result = 0;
    }
    return result;
}
int prov_transport_common_mqtt_open(PROV_DEVICE_TRANSPORT_HANDLE handle, const char* registration_id, BUFFER_HANDLE ek, BUFFER_HANDLE srk, PROV_DEVICE_TRANSPORT_REGISTER_CALLBACK data_callback, void* user_ctx, PROV_DEVICE_TRANSPORT_STATUS_CALLBACK status_cb, void* status_ctx)
{
    int result;
    PROV_TRANSPORT_MQTT_INFO* mqtt_info = (PROV_TRANSPORT_MQTT_INFO*)handle;
    if (mqtt_info == NULL || data_callback == NULL || status_cb == NULL || registration_id == NULL)
    {
        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_007: [ If handle, data_callback, or status_cb is NULL, prov_transport_common_mqtt_open shall return a non-zero value. ] */
        LogError("Invalid parameter specified handle: %p, data_callback: %p, status_cb: %p, registration_id: %p", handle, data_callback, status_cb, registration_id);
        result = __FAILURE__;
    }
    else if ( (mqtt_info->hsm_type == TRANSPORT_HSM_TYPE_TPM) && (ek == NULL || srk == NULL) )
    {
        /* Codes_PROV_TRANSPORT_MQTT_COMMON_07_008: [ If hsm_type is TRANSPORT_HSM_TYPE_TPM and ek or srk is NULL, prov_transport_common_mqtt_open shall return a non-zero value. ] */
        LogError("Invalid parameter specified ek: %p, srk: %p", ek, srk);
        result = __FAILURE__;
    }
    /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_009: [ prov_transport_common_mqtt_open shall clone the ek and srk values.] */
    else if (ek != NULL && (mqtt_info->ek = BUFFER_clone(ek)) == NULL)
    {
        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_041: [ If a failure is encountered, prov_transport_common_mqtt_open shall return a non-zero value. ] */
        LogError("Unable to allocate endorsement key");
        result = __FAILURE__;
    }
    else if (srk != NULL && (mqtt_info->srk = BUFFER_clone(srk)) == NULL)
    {
        /* Tests_PROV_TRANSPORT_MQTT_COMMON_07_041: [ If a failure is encountered, prov_transport_common_mqtt_open shall return a non-zero value. ] */
        LogError("Unable to allocate storage root key");
        BUFFER_delete(mqtt_info->ek);
        mqtt_info->ek = NULL;
        result = __FAILURE__;
    }
    else if (mallocAndStrcpy_s(&mqtt_info->registration_id, registration_id) != 0)
    {
        /* Codes_PROV_TRANSPORT_HTTP_CLIENT_07_003: [ If any error is encountered prov_transport_http_create shall return NULL. ] */
        LogError("failure constructing registration Id");
        BUFFER_delete(mqtt_info->ek);
        mqtt_info->ek = NULL;
        BUFFER_delete(mqtt_info->srk);
        mqtt_info->srk = NULL;
        result = __FAILURE__;
    }
    else
    {
        mqtt_info->register_data_cb = data_callback;
        mqtt_info->user_ctx = user_ctx;
        mqtt_info->status_cb = status_cb;
        mqtt_info->status_ctx = status_ctx;
        mqtt_info->mqtt_state = MQTT_STATE_DISCONNECTED;
        result = 0;
    }
    return result;
}
static int create_Device(IOTHUB_ACCOUNT_INFO* accountInfo, const char* callerName)
{
    int result = 0;
    if (generateDeviceName(accountInfo, callerName) != 0)
    {
        result = __LINE__;
    }
    else
    {
        BUFFER_HANDLE deviceJson = constructDeviceJson(accountInfo);
        if (deviceJson == NULL)
        {
            result = __LINE__;
            free(accountInfo->deviceId);
            accountInfo->deviceId = NULL;
        }
        else
        {
            BUFFER_HANDLE deviceResp = sendDeviceRegistryInfo(accountInfo, deviceJson, HTTPAPI_REQUEST_PUT);
            if (deviceResp != NULL)
            {
                if (parseDeviceJson(accountInfo, deviceResp) != 0)
                {
                    result = __LINE__;
                    free(accountInfo->deviceId);
                    accountInfo->deviceId = NULL;
                }
                else
                {
                    result = 0;
                }
                BUFFER_delete(deviceResp);
            }
            else
            {
                result = __LINE__;
                free(accountInfo->deviceId);
                accountInfo->deviceId = NULL;
            }
            BUFFER_delete(deviceJson);
        }
    }
    return result;
}
static void free_json_parse_info(PROV_JSON_INFO* parse_info)
{
    switch (parse_info->prov_status)
    {
        case PROV_DEVICE_TRANSPORT_STATUS_UNASSIGNED:
            BUFFER_delete(parse_info->authorization_key);
            free(parse_info->key_name);
            break;
        case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNED:
            BUFFER_delete(parse_info->authorization_key);
            free(parse_info->iothub_uri);
            free(parse_info->device_id);
            break;
        case PROV_DEVICE_TRANSPORT_STATUS_ASSIGNING:
            free(parse_info->operation_id);
            break;
        default:
            break;
    }
    free(parse_info);
}
static void on_write_complete(BLEIO_GATT_HANDLE bleio_gatt_handle, void* write_context, BLEIO_GATT_RESULT result)
{
    // this MUST NOT be NULL
    WRITE_CONTEXT* context = (WRITE_CONTEXT*)write_context;
    if (context->handle_data->on_write_complete != NULL)
    {
        if (result != BLEIO_GATT_OK)
        {
            LogError("An error occurred while executing instruction of type %d for characteristic %s",
                context->instruction->instruction_type,
                STRING_c_str(context->instruction->characteristic_uuid)
            );
        }

        /*Codes_SRS_BLEIO_SEQ_13_021: [ When the WRITE_AT_EXIT instruction completes execution this API shall invoke the on_write_complete callback passing in the status of the operation and the callback context that was passed in via the BLEIO_SEQ_INSTRUCTION structure. ]*/
        /*Codes_SRS_BLEIO_SEQ_13_020: [ When the WRITE_AT_INIT instruction completes execution this API shall invoke the on_write_complete callback passing in the status of the operation and the callback context that was passed in via the BLEIO_SEQ_INSTRUCTION structure. ]*/
        /*Codes_SRS_BLEIO_SEQ_13_034: [ When the WRITE_ONCE instruction completes execution this API shall invoke the on_write_complete callback passing in the status of the operation and the callback context that was passed in via the BLEIO_SEQ_INSTRUCTION structure. ]*/
        /*Codes_SRS_BLEIO_SEQ_13_042: [ When a WRITE_ONCE or a WRITE_AT_INIT instruction completes execution this API shall invoke the on_write_complete callback passing in the status of the operation and the callback context that was passed in via the BLEIO_SEQ_INSTRUCTION structure. ]*/
        context->handle_data->on_write_complete(
            (BLEIO_SEQ_HANDLE)context->handle_data,
            context->instruction->context,
            STRING_c_str(context->instruction->characteristic_uuid),
            context->instruction->instruction_type,
            result == BLEIO_GATT_OK ? BLEIO_SEQ_OK : BLEIO_SEQ_ERROR
        );
    }

    /*Codes_SRS_BLEIO_SEQ_13_026: [ When the WRITE_AT_INIT instruction completes execution this API shall free the buffer that was passed in via the instruction. ]*/
    /*Codes_SRS_BLEIO_SEQ_13_041: [ When a WRITE_AT_INIT or a WRITE_ONCE instruction completes execution this API shall free the buffer that was passed in via the instruction. ]*/
    /*Codes_SRS_BLEIO_SEQ_13_027: [ When the WRITE_AT_EXIT instruction completes execution this API shall free the buffer that was passed in via the instruction. ]*/
    /*Codes_SRS_BLEIO_SEQ_13_035: [ When the WRITE_ONCE instruction completes execution this API shall free the buffer that was passed in via the instruction. ]*/
    // free the buffer that was written
    BUFFER_delete(context->instruction->data.buffer);
    context->instruction->data.buffer = NULL;

    // invoke the internal complete callback if we have one
    if (context->on_internal_read_complete != NULL)
    {
        context->on_internal_read_complete(context->handle_data, context->instruction);
    }

    // dec ref the handle data
    // NOTE: The call below MUST occur *after* the BUFFER_delete call above
    // because `dec_ref_handle` might end up destroying the sequence itself
    // at which point context->instruction no longer exists (because it is
    // simply a pointer to the instructions vector in the sequence).
    dec_ref_handle(context->handle_data);

    free(context);
}
void IoTHubMessage_Destroy(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    /*Codes_SRS_IOTHUBMESSAGE_01_004: [If iotHubMessageHandle is NULL, IoTHubMessage_Destroy shall do nothing.] */
    if (iotHubMessageHandle != NULL)
    {
        /*Codes_SRS_IOTHUBMESSAGE_01_003: [IoTHubMessage_Destroy shall free all resources associated with iotHubMessageHandle.]  */
        IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle;
        if (handleData->contentType == IOTHUBMESSAGE_BYTEARRAY)
        {
            BUFFER_delete(handleData->value.byteArray);
        }
        else
        {
            /*can only be STRING*/
            STRING_delete(handleData->value.string);
        }
        Map_Destroy(handleData->properties);
        free(handleData);
    }
}
void create_tpm_enrollment_device(const char* prov_conn_string, bool use_tracing)
{
    INDIVIDUAL_ENROLLMENT_HANDLE indiv_enrollment = NULL;

    PROVISIONING_SERVICE_CLIENT_HANDLE prov_sc_handle = prov_sc_create_from_connection_string(prov_conn_string);
    ASSERT_IS_NOT_NULL(prov_sc_handle, "Failure creating provisioning service client");

    if (use_tracing)
    {
        prov_sc_set_trace(prov_sc_handle, TRACING_STATUS_ON);
    }

#ifdef SET_TRUSTED_CERT_IN_SAMPLES
    ASSERT_ARE_EQUAL(PROV_DEVICE_RESULT, PROV_DEVICE_RESULT_OK, prov_sc_set_certificate(prov_sc_handle, certificates), "Failure setting Trusted Cert option");
#endif // SET_TRUSTED_CERT_IN_SAMPLES

    PROV_AUTH_HANDLE auth_handle = prov_auth_create();
    ASSERT_IS_NOT_NULL(auth_handle, "Failure creating auth client");

    char* registration_id = prov_auth_get_registration_id(auth_handle);
    ASSERT_IS_NOT_NULL(registration_id, "Failure prov_auth_get_common_name");

    if (prov_sc_get_individual_enrollment(prov_sc_handle, registration_id, &indiv_enrollment) != 0)
    {
        BUFFER_HANDLE ek_handle = prov_auth_get_endorsement_key(auth_handle);
        ASSERT_IS_NOT_NULL(ek_handle, "Failure prov_auth_get_endorsement_key");

        STRING_HANDLE ek_value = Azure_Base64_Encode(ek_handle);
        ASSERT_IS_NOT_NULL(ek_value, "Failure Base64_Encode Endorsement key");

        ATTESTATION_MECHANISM_HANDLE attest_handle = attestationMechanism_createWithTpm(STRING_c_str(ek_value), NULL);
        ASSERT_IS_NOT_NULL(attest_handle, "Failure attestationMechanism_createWithTpm");

        indiv_enrollment = individualEnrollment_create(registration_id, attest_handle);
        ASSERT_IS_NOT_NULL(indiv_enrollment, "Failure hsm_client_riot_get_certificate ");

        ASSERT_ARE_EQUAL(int, 0, prov_sc_create_or_update_individual_enrollment(prov_sc_handle, &indiv_enrollment), "Failure prov_sc_create_or_update_individual_enrollment");

        BUFFER_delete(ek_handle);
        STRING_delete(ek_value);
    }
static void DestroyMessageData(IOTHUB_MESSAGE_HANDLE_DATA* handleData)
{
    if (handleData->contentType == IOTHUBMESSAGE_BYTEARRAY)
    {
        BUFFER_delete(handleData->value.byteArray);
    }
    else if (handleData->contentType == IOTHUBMESSAGE_STRING)
    {
        STRING_delete(handleData->value.string);
    }

    Map_Destroy(handleData->properties);
    free(handleData->messageId);
    handleData->messageId = NULL;
    free(handleData->correlationId);
    handleData->correlationId = NULL;
    free(handleData->userDefinedContentType);
    free(handleData->contentEncoding);
    DestroyDiagnosticPropertyData(handleData->diagnosticData);
    free(handleData);
}
static int delete_Device(IOTHUB_ACCOUNT_INFO* accountInfo)
{
    int result = 0;
    if (accountInfo->deviceId != NULL)
    {
        BUFFER_HANDLE deleteDevice = sendDeviceRegistryInfo(accountInfo, NULL, HTTPAPI_REQUEST_DELETE);
        if (deleteDevice == NULL)
        {
            LogError("Unable to delete created device %s.\r\n", accountInfo->deviceId);
            result = __LINE__;
        }
        else
        {
            BUFFER_delete(deleteDevice);
            result = 0;
        }

        free(accountInfo->deviceId);
        free(accountInfo->deviceKey);
    }
    return result;
}
static void create_tpm_enrollment_device()
{
    INDIVIDUAL_ENROLLMENT_HANDLE indiv_enrollment = NULL;

    PROVISIONING_SERVICE_CLIENT_HANDLE prov_sc_handle = prov_sc_create_from_connection_string(g_prov_conn_string);
    ASSERT_IS_NOT_NULL(prov_sc_handle, "Failure creating provisioning service client");

    prov_sc_set_trace(prov_sc_handle, TRACING_STATUS_ON);

    PROV_AUTH_HANDLE auth_handle = prov_auth_create();
    ASSERT_IS_NOT_NULL(auth_handle, "Failure creating auth client");

    char* registration_id = prov_auth_get_registration_id(auth_handle);
    ASSERT_IS_NOT_NULL(registration_id, "Failure prov_auth_get_common_name");

    if (prov_sc_get_individual_enrollment(prov_sc_handle, registration_id, &indiv_enrollment) != 0)
    {
        BUFFER_HANDLE ek_handle = prov_auth_get_endorsement_key(auth_handle);
        ASSERT_IS_NOT_NULL(ek_handle, "Failure prov_auth_get_endorsement_key");

        STRING_HANDLE ek_value = Base64_Encode(ek_handle);
        ASSERT_IS_NOT_NULL(ek_value, "Failure Base64_Encode Endorsement key");

        ATTESTATION_MECHANISM_HANDLE attest_handle = attestationMechanism_createWithTpm(STRING_c_str(ek_value), NULL);
        ASSERT_IS_NOT_NULL(attest_handle, "Failure attestationMechanism_createWithTpm");

        indiv_enrollment = individualEnrollment_create(registration_id, attest_handle);
        ASSERT_IS_NOT_NULL(indiv_enrollment, "Failure hsm_client_riot_get_certificate ");

        BUFFER_delete(ek_handle);
        STRING_delete(ek_value);
    }
    free(registration_id);
    individualEnrollment_destroy(indiv_enrollment);
    prov_auth_destroy(auth_handle);
    prov_sc_destroy(prov_sc_handle);
}
Beispiel #11
0
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;
}
Beispiel #12
0
BLOB_RESULT Blob_UploadMultipleBlocksFromSasUri(const char* SASURI, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context, unsigned int* httpStatus, BUFFER_HANDLE httpResponse, const char* certificates, HTTP_PROXY_OPTIONS *proxyOptions)
{
    BLOB_RESULT result;
    /*Codes_SRS_BLOB_02_001: [ If SASURI is NULL then Blob_UploadMultipleBlocksFromSasUri 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 getDataCallbackEx is NULL then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
        if (getDataCallbackEx == NULL)
        {
            LogError("IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx is NULL");
            result = BLOB_INVALID_ARG;
        }
        /*the below define avoid a "condition always false" on some compilers*/
        else
        {
            /*Codes_SRS_BLOB_02_017: [ Blob_UploadMultipleBlocksFromSasUri 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_UploadMultipleBlocksFromSasUri 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_UploadMultipleBlocksFromSasUri 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_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
                        LogError("oom - out of memory");
                        result = BLOB_ERROR;
                    }
                    else
                    {
                        HTTPAPIEX_HANDLE httpApiExHandle;
                        (void)memcpy(hostname, hostnameBegin, hostnameSize);
                        hostname[hostnameSize] = '\0';

                        /*Codes_SRS_BLOB_02_018: [ Blob_UploadMultipleBlocksFromSasUri 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_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR. ]*/
                            LogError("unable to create a HTTPAPIEX_HANDLE");
                            result = BLOB_ERROR;
                        }
                        else
                        {
                            if ((certificates != NULL)&& (HTTPAPIEX_SetOption(httpApiExHandle, "TrustedCerts", certificates) == HTTPAPIEX_ERROR))
                            {
                                LogError("failure in setting trusted certificates");
                                result = BLOB_ERROR;
                            }
                            else if ((proxyOptions != NULL && proxyOptions->host_address != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_PROXY, proxyOptions) == HTTPAPIEX_ERROR)
                            {
                                LogError("failure in setting proxy options");
                                result = BLOB_ERROR;
                            }
                            else
                            {
                                /*Codes_SRS_BLOB_02_019: [ Blob_UploadMultipleBlocksFromSasUri 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*/

                                /*Codes_SRS_BLOB_02_028: [ Blob_UploadMultipleBlocksFromSasUri shall construct an XML string with the following content: ]*/
                                STRING_HANDLE blockIDList = STRING_construct("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<BlockList>"); /*the XML "build as we go"*/
                                if (blockIDList == NULL)
                                {
                                    /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
                                    LogError("failed to STRING_construct");
                                    result = BLOB_HTTP_ERROR;
                                }
                                else
                                {
                                    /*Codes_SRS_BLOB_02_021: [ For every block returned by `getDataCallbackEx` the following operations shall happen: ]*/
                                    unsigned int blockID = 0; /* incremented for each new block */
                                    unsigned int isError = 0; /* set to 1 if a block upload fails or if getDataCallbackEx returns incorrect blocks to upload */
                                    unsigned int uploadOneMoreBlock = 1; /* set to 1 while getDataCallbackEx returns correct blocks to upload */
                                    unsigned char const * source; /* data set by getDataCallbackEx */
                                    size_t size; /* source size set by getDataCallbackEx */
                                    IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataReturnValue;

                                    do
                                    {
                                        getDataReturnValue = getDataCallbackEx(FILE_UPLOAD_OK, &source, &size, context);
                                        if (getDataReturnValue == IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT)
                                        {
                                            /*Codes_SRS_BLOB_99_004: [ If `getDataCallbackEx` returns `IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT_ABORT`, then `Blob_UploadMultipleBlocksFromSasUri` shall exit the loop and return `BLOB_ABORTED`. ]*/
                                            LogInfo("Upload to blob has been aborted by the user");
                                            uploadOneMoreBlock = 0;
                                            result = BLOB_ABORTED;
                                        }
                                        else if (source == NULL || size == 0)
                                        {
                                            /*Codes_SRS_BLOB_99_002: [ If the size of the block returned by `getDataCallbackEx` is 0 or if the data is NULL, then `Blob_UploadMultipleBlocksFromSasUri` shall exit the loop. ]*/
                                            uploadOneMoreBlock = 0;
                                            result = BLOB_OK;
                                        }
                                        else
                                        {
                                            if (size > BLOCK_SIZE)
                                            {
                                                /*Codes_SRS_BLOB_99_001: [ If the size of the block returned by `getDataCallbackEx` is bigger than 4MB, then `Blob_UploadMultipleBlocksFromSasUri` shall fail and return `BLOB_INVALID_ARG`. ]*/
                                                LogError("tried to upload block of size %lu, max allowed size is %d", (unsigned long)size, BLOCK_SIZE);
                                                result = BLOB_INVALID_ARG;
                                                isError = 1;
                                            }
                                            else if (blockID >= MAX_BLOCK_COUNT)
                                            {
                                                /*Codes_SRS_BLOB_99_003: [ If `getDataCallbackEx` returns more than 50000 blocks, then `Blob_UploadMultipleBlocksFromSasUri` shall fail and return `BLOB_INVALID_ARG`. ]*/
                                                LogError("unable to upload more than %lu blocks in one blob", (unsigned long)MAX_BLOCK_COUNT);
                                                result = BLOB_INVALID_ARG;
                                                isError = 1;
                                            }
                                            else
                                            {
                                                /*Codes_SRS_BLOB_02_023: [ Blob_UploadMultipleBlocksFromSasUri shall create a BUFFER_HANDLE from source and size parameters. ]*/
                                                BUFFER_HANDLE requestContent = BUFFER_create(source, size);
                                                if (requestContent == NULL)
                                                {
                                                    /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
                                                    LogError("unable to BUFFER_create");
                                                    result = BLOB_ERROR;
                                                    isError = 1;
                                                }
                                                else
                                                {
                                                    result = Blob_UploadBlock(
                                                            httpApiExHandle,
                                                            relativePath,
                                                            requestContent,
                                                            blockID,
                                                            blockIDList,
                                                            httpStatus,
                                                            httpResponse);

                                                    BUFFER_delete(requestContent);
                                                }

                                                /*Codes_SRS_BLOB_02_026: [ Otherwise, if HTTP response code is >=300 then Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/
                                                if (result != BLOB_OK || *httpStatus >= 300)
                                                {
                                                    LogError("unable to Blob_UploadBlock. Returned value=%d, httpStatus=%u", result, (unsigned int)*httpStatus);
                                                    isError = 1;
                                                }
                                            }
                                            blockID++;
                                        }
                                    }
                                    while(uploadOneMoreBlock && !isError);

                                    if (isError || result != BLOB_OK)
                                    {
                                        /*do nothing, it will be reported "as is"*/
                                    }
                                    else
                                    {
                                        /*complete the XML*/
                                        if (STRING_concat(blockIDList, "</BlockList>") != 0)
                                        {
                                            /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
                                            LogError("failed to STRING_concat");
                                            result = BLOB_ERROR;
                                        }
                                        else
                                        {
                                            /*Codes_SRS_BLOB_02_029: [Blob_UploadMultipleBlocksFromSasUri 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_UploadMultipleBlocksFromSasUri 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_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
                                                    LogError("failed to STRING_concat");
                                                    result = BLOB_ERROR;
                                                }
                                                else
                                                {
                                                    /*Codes_SRS_BLOB_02_030: [ Blob_UploadMultipleBlocksFromSasUri 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(blockIDList);
                                                    BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s));
                                                    if (blockIDListAsBuffer == NULL)
                                                    {
                                                        /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri 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,
                                                            blockIDListAsBuffer,
                                                            httpStatus,
                                                            NULL,
                                                            httpResponse
                                                        ) != HTTPAPIEX_OK)
                                                        {
                                                            /*Codes_SRS_BLOB_02_031: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/
                                                            LogError("unable to HTTPAPIEX_ExecuteRequest");
                                                            result = BLOB_HTTP_ERROR;
                                                        }
                                                        else
                                                        {
                                                            /*Codes_SRS_BLOB_02_032: [ Otherwise, Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/
                                                            result = BLOB_OK;
                                                        }
                                                        BUFFER_delete(blockIDListAsBuffer);
                                                    }
                                                }
                                                STRING_delete(newRelativePath);
                                            }
                                        }
                                    }
                                    STRING_delete(blockIDList);
                                }

                            }
                            HTTPAPIEX_Destroy(httpApiExHandle);
                        }
                        free(hostname);
                    }
                }
            }
        }
    }
    return result;
}
Beispiel #13
0
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;
}
Beispiel #14
0
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;
}
STRING_HANDLE SASToken_Create(STRING_HANDLE key, STRING_HANDLE scope, STRING_HANDLE keyName, size_t expiry)
{
    STRING_HANDLE result = NULL;
    char tokenExpirationTime[32] = { 0 };

    /*Codes_SRS_SASTOKEN_06_001: [If key is NULL then SASToken_Create shall return NULL.]*/
    /*Codes_SRS_SASTOKEN_06_003: [If scope is NULL then SASToken_Create shall return NULL.]*/
    /*Codes_SRS_SASTOKEN_06_007: [If keyName is NULL then SASToken_Create shall return NULL.]*/
    if ((key == NULL) ||
        (scope == NULL) ||
        (keyName == NULL))
    {
        LogError("Invalid Parameter to SASToken_Create. handle key: %p, handle scope: %p, handle keyName: %p\r\n", key, scope, keyName);
    }
    else
    {
        BUFFER_HANDLE decodedKey;
        /*Codes_SRS_SASTOKEN_06_029: [The key parameter is decoded from base64.]*/
        if ((decodedKey = Base64_Decoder(STRING_c_str(key))) == NULL)
        {
            /*Codes_SRS_SASTOKEN_06_030: [If there is an error in the decoding then SASToken_Create shall return NULL.]*/
            LogError("Unable to decode the key for generating the SAS.\r\n");
        }
        else
        {
            /*Codes_SRS_SASTOKEN_06_026: [If the conversion to string form fails for any reason then SASToken_Create shall return NULL.]*/
            if (size_tToString(tokenExpirationTime, sizeof(tokenExpirationTime), expiry) != 0)
            {
                LogError("For some reason converting seconds to a string failed.  No SAS can be generated.\r\n");
            }
            else
            {
                STRING_HANDLE toBeHashed = NULL;
                BUFFER_HANDLE hash = NULL;
                if (((hash = BUFFER_new()) == NULL) ||
                    ((toBeHashed = STRING_new()) == NULL) ||
                    ((result = STRING_new()) == NULL))
                {
                    LogError("Unable to allocate memory to prepare SAS token.\r\n")
                }
                else
                {
                    /*Codes_SRS_SASTOKEN_06_009: [The scope is the basis for creating a STRING_HANDLE.]*/
                    /*Codes_SRS_SASTOKEN_06_010: [A "\n" is appended to that string.]*/
                    /*Codes_SRS_SASTOKEN_06_011: [tokenExpirationTime is appended to that string.]*/
                    if ((STRING_concat_with_STRING(toBeHashed, scope) != 0) ||
                        (STRING_concat(toBeHashed, "\n") != 0) ||
                        (STRING_concat(toBeHashed, tokenExpirationTime) != 0))
                    {
                        LogError("Unable to build the input to the HMAC to prepare SAS token.\r\n");
                        STRING_delete(result);
                        result = NULL;
                    }
                    else
                    {
                        STRING_HANDLE base64Signature = NULL;
                        STRING_HANDLE urlEncodedSignature = NULL;
                        /*Codes_SRS_SASTOKEN_06_013: [If an error is returned from the HMAC256 function then NULL is returned from SASToken_Create.]*/
                        /*Codes_SRS_SASTOKEN_06_012: [An HMAC256 hash is calculated using the decodedKey, over toBeHashed.]*/
                        /*Codes_SRS_SASTOKEN_06_014: [If there are any errors from the following operations then NULL shall be returned.]*/
                        /*Codes_SRS_SASTOKEN_06_015: [The hash is base 64 encoded.]*/
                        /*Codes_SRS_SASTOKEN_06_028: [base64Signature shall be url encoded.]*/
                        /*Codes_SRS_SASTOKEN_06_016: [The string "SharedAccessSignature sr=" is the first part of the result of SASToken_Create.]*/
                        /*Codes_SRS_SASTOKEN_06_017: [The scope parameter is appended to result.]*/
                        /*Codes_SRS_SASTOKEN_06_018: [The string "&sig=" is appended to result.]*/
                        /*Codes_SRS_SASTOKEN_06_019: [The string urlEncodedSignature shall be appended to result.]*/
                        /*Codes_SRS_SASTOKEN_06_020: [The string "&se=" shall be appended to result.]*/
                        /*Codes_SRS_SASTOKEN_06_021: [tokenExpirationTime is appended to result.]*/
                        /*Codes_SRS_SASTOKEN_06_022: [The string "&skn=" is appended to result.]*/
                        /*Codes_SRS_SASTOKEN_06_023: [The argument keyName is appended to result.]*/
                        if ((HMACSHA256_ComputeHash(BUFFER_u_char(decodedKey), BUFFER_length(decodedKey), (const unsigned char*)STRING_c_str(toBeHashed), STRING_length(toBeHashed), hash) != HMACSHA256_OK) ||
                            ((base64Signature = Base64_Encode(hash)) == NULL) ||
                            ((urlEncodedSignature = URL_Encode(base64Signature)) == NULL) ||
                            (STRING_copy(result, "SharedAccessSignature sr=") != 0) ||
                            (STRING_concat_with_STRING(result, scope) != 0) ||
                            (STRING_concat(result, "&sig=") != 0) ||
                            (STRING_concat_with_STRING(result, urlEncodedSignature) != 0) ||
                            (STRING_concat(result, "&se=") != 0) ||
                            (STRING_concat(result, tokenExpirationTime) != 0) ||
                            (STRING_concat(result, "&skn=") != 0) ||
                            (STRING_concat_with_STRING(result, keyName) != 0))
                        {
                            LogError("Unable to build the SAS token.\r\n");
                            STRING_delete(result);
                            result = NULL;
                        }
                        else
                        {
                            /* everything OK */
                        }
                        STRING_delete(base64Signature);
                        STRING_delete(urlEncodedSignature);
                    }
                }
                STRING_delete(toBeHashed);
                BUFFER_delete(hash);
            }
            BUFFER_delete(decodedKey);
        }
    }

    return result;
}
    static void setup_retrieve_persisted_key_mocks(bool json_file_found)
    {
        if (json_file_found)
        {
            STRICT_EXPECTED_CALL(json_parse_file(IGNORED_PTR_ARG))
                .IgnoreArgument_string();
            STRICT_EXPECTED_CALL(json_value_get_object(IGNORED_PTR_ARG))
                .IgnoreArgument_value();
            STRICT_EXPECTED_CALL(json_object_get_value(IGNORED_PTR_ARG, IGNORED_PTR_ARG))
                .IgnoreArgument_name()
                .IgnoreArgument_object();
            STRICT_EXPECTED_CALL(json_object_get_value(IGNORED_PTR_ARG, IGNORED_PTR_ARG))
                .IgnoreArgument_name()
                .IgnoreArgument_object();
            STRICT_EXPECTED_CALL(json_object_get_value(IGNORED_PTR_ARG, IGNORED_PTR_ARG))
                .IgnoreArgument_name()
                .IgnoreArgument_object();
            STRICT_EXPECTED_CALL(json_object_get_value(IGNORED_PTR_ARG, IGNORED_PTR_ARG))
                .IgnoreArgument_name()
                .IgnoreArgument_object();
            STRICT_EXPECTED_CALL(json_value_get_string(IGNORED_PTR_ARG))
                .IgnoreArgument_value();
            STRICT_EXPECTED_CALL(Azure_Base64_Decode(IGNORED_PTR_ARG))
                .IgnoreArgument_source();
            STRICT_EXPECTED_CALL(json_value_get_string(IGNORED_PTR_ARG))
                .IgnoreArgument_value();
            STRICT_EXPECTED_CALL(Azure_Base64_Decode(IGNORED_PTR_ARG))
                .IgnoreArgument_source();
            STRICT_EXPECTED_CALL(json_value_get_string(IGNORED_PTR_ARG))
                .IgnoreArgument_value();
            STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, IGNORED_PTR_ARG))
                .IgnoreArgument_destination()
                .IgnoreArgument_source();
            STRICT_EXPECTED_CALL(json_value_get_string(IGNORED_PTR_ARG))
                .IgnoreArgument_value();
            STRICT_EXPECTED_CALL(Azure_Base64_Decode(IGNORED_PTR_ARG))
                .IgnoreArgument_source();

            STRICT_EXPECTED_CALL(BUFFER_u_char(IGNORED_PTR_ARG))
                .IgnoreArgument_handle();
            STRICT_EXPECTED_CALL(BUFFER_length(IGNORED_PTR_ARG))
                .IgnoreArgument_handle();
            STRICT_EXPECTED_CALL(BIO_new_mem_buf(IGNORED_PTR_ARG, IGNORED_NUM_ARG))
                .IgnoreArgument_buf()
                .IgnoreArgument_len();
            STRICT_EXPECTED_CALL(PEM_read_bio_RSA_PUBKEY(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG))
                .IgnoreAllArguments();

            STRICT_EXPECTED_CALL(BUFFER_u_char(IGNORED_PTR_ARG))
                .IgnoreArgument_handle();
            STRICT_EXPECTED_CALL(BUFFER_length(IGNORED_PTR_ARG))
                .IgnoreArgument_handle();
            STRICT_EXPECTED_CALL(BIO_new_mem_buf(IGNORED_PTR_ARG, IGNORED_NUM_ARG))
                .IgnoreArgument_buf()
                .IgnoreArgument_len();
            STRICT_EXPECTED_CALL(PEM_read_bio_RSAPrivateKey(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG))
                .IgnoreAllArguments();

            STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG))
                .IgnoreArgument_handle();
            STRICT_EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG))
                .IgnoreArgument_handle();

        }
        else
        {
            STRICT_EXPECTED_CALL(json_parse_file(IGNORED_PTR_ARG))
                .IgnoreArgument_string()
                .SetReturn(NULL);
        }
    }
Beispiel #17
0
int main(int argc, char** argv)
{
    int result;

    (void)argc;
    (void)argv;

    if (platform_init() != 0)
    {
        result = -1;
    }
    else
    {
        XIO_HANDLE sasl_io;
        CONNECTION_HANDLE connection;
        SESSION_HANDLE session;
        LINK_HANDLE link;
        MESSAGE_SENDER_HANDLE message_sender;
        MESSAGE_HANDLE message;

        size_t last_memory_used = 0;

        /* create SASL PLAIN handler */
        SASL_MECHANISM_HANDLE sasl_mechanism_handle = saslmechanism_create(saslmssbcbs_get_interface(), NULL);
        XIO_HANDLE tls_io;
        STRING_HANDLE sas_key_name;
        STRING_HANDLE sas_key_value;
        STRING_HANDLE resource_uri;
        STRING_HANDLE encoded_resource_uri;
        STRING_HANDLE sas_token;
        BUFFER_HANDLE buffer;
        TLSIO_CONFIG tls_io_config = { EH_HOST, 5671 };
        const IO_INTERFACE_DESCRIPTION* tlsio_interface;
        SASLCLIENTIO_CONFIG sasl_io_config;
        time_t currentTime;
        size_t expiry_time;
        CBS_HANDLE cbs;
        AMQP_VALUE source;
        AMQP_VALUE target;
        unsigned char hello[] = { 'H', 'e', 'l', 'l', 'o' };
        BINARY_DATA binary_data;

        gballoc_init();

        /* create the TLS IO */
        tlsio_interface = platform_get_default_tlsio();
        tls_io = xio_create(tlsio_interface, &tls_io_config);

        /* create the SASL client IO using the TLS IO */
        sasl_io_config.underlying_io = tls_io;
        sasl_io_config.sasl_mechanism = sasl_mechanism_handle;
        sasl_io = xio_create(saslclientio_get_interface_description(), &sasl_io_config);

        /* create the connection, session and link */
        connection = connection_create(sasl_io, EH_HOST, "some", NULL, NULL);
        session = session_create(connection, NULL, NULL);
        session_set_incoming_window(session, 2147483647);
        session_set_outgoing_window(session, 65536);

        /* Construct a SAS token */
        sas_key_name = STRING_construct(EH_KEY_NAME);

        /* unfortunately SASToken wants an encoded key - this should be fixed at a later time */
        buffer = BUFFER_create((unsigned char*)EH_KEY, strlen(EH_KEY));
        sas_key_value = Base64_Encoder(buffer);
        BUFFER_delete(buffer);
        resource_uri = STRING_construct("sb://" EH_HOST "/" EH_NAME "/publishers/" EH_PUBLISHER);
        encoded_resource_uri = URL_EncodeString(STRING_c_str(resource_uri));

        /* Make a token that expires in one hour */
        currentTime = time(NULL);
        expiry_time = (size_t)(difftime(currentTime, 0) + 3600);

        sas_token = SASToken_Create(sas_key_value, encoded_resource_uri, sas_key_name, expiry_time);

        cbs = cbs_create(session);
        if (cbs_open_async(cbs, on_cbs_open_complete, cbs, on_cbs_error, cbs) == 0)
        {
            (void)cbs_put_token_async(cbs, "servicebus.windows.net:sastoken", "sb://" EH_HOST "/" EH_NAME "/publishers/" EH_PUBLISHER, STRING_c_str(sas_token), on_cbs_put_token_complete, cbs);

            while (!auth)
            {
                size_t current_memory_used;
                size_t maximum_memory_used;
                connection_dowork(connection);

                current_memory_used = gballoc_getCurrentMemoryUsed();
                maximum_memory_used = gballoc_getMaximumMemoryUsed();

                if (current_memory_used != last_memory_used)
                {
                    (void)printf("Current memory usage:%lu (max:%lu)\r\n", (unsigned long)current_memory_used, (unsigned long)maximum_memory_used);
                    last_memory_used = current_memory_used;
                }
            }
        }

        STRING_delete(sas_token);
        STRING_delete(sas_key_name);
        STRING_delete(sas_key_value);
        STRING_delete(resource_uri);
        STRING_delete(encoded_resource_uri);

        source = messaging_create_source("ingress");
        target = messaging_create_target("amqps://" EH_HOST "/" EH_NAME);
        link = link_create(session, "sender-link", role_sender, source, target);
        link_set_snd_settle_mode(link, sender_settle_mode_settled);
        (void)link_set_max_message_size(link, 65536);

        amqpvalue_destroy(source);
        amqpvalue_destroy(target);

        message = message_create();

        binary_data.bytes = hello;
        binary_data.length = sizeof(hello);
        message_add_body_amqp_data(message, binary_data);

        /* create a message sender */
        message_sender = messagesender_create(link, NULL, NULL);
        if (messagesender_open(message_sender) == 0)
        {
            uint32_t i;
            bool keep_running = true;
            tickcounter_ms_t start_time;
            TICK_COUNTER_HANDLE tick_counter = tickcounter_create();

            if (tickcounter_get_current_ms(tick_counter, &start_time) != 0)
            {
                (void)printf("Error getting start time\r\n");
            }
            else
            {
                for (i = 0; i < msg_count; i++)
                {
                    (void)messagesender_send(message_sender, message, on_message_send_complete, message);
                }

                message_destroy(message);

                while (keep_running)
                {
                    size_t current_memory_used;
                    size_t maximum_memory_used;
                    connection_dowork(connection);

                    current_memory_used = gballoc_getCurrentMemoryUsed();
                    maximum_memory_used = gballoc_getMaximumMemoryUsed();

                    if (current_memory_used != last_memory_used)
                    {
                        (void)printf("Current memory usage:%lu (max:%lu)\r\n", (unsigned long)current_memory_used, (unsigned long)maximum_memory_used);
                        last_memory_used = current_memory_used;
                    }

                    if (sent_messages == msg_count)
                    {
                        break;
                    }
                }

                {
                    tickcounter_ms_t end_time;
                    if (tickcounter_get_current_ms(tick_counter, &end_time) != 0)
                    {
                        (void)printf("Error getting end time\r\n");
                    }
                    else
                    {
                        (void)printf("Send %u messages in %lu ms: %.02f msgs/sec\r\n", (unsigned int)msg_count, (unsigned long)(end_time - start_time), (float)msg_count / ((float)(end_time - start_time) / 1000));
                    }
                }
            }
        }

        messagesender_destroy(message_sender);
        link_destroy(link);
        session_destroy(session);
        connection_destroy(connection);
        xio_destroy(sasl_io);
        xio_destroy(tls_io);
        saslmechanism_destroy(sasl_mechanism_handle);
        platform_deinit();

        (void)printf("Max memory usage:%lu\r\n", (unsigned long)gballoc_getCurrentMemoryUsed());
        (void)printf("Current memory usage:%lu\r\n", (unsigned long)gballoc_getMaximumMemoryUsed());

        gballoc_deinit();

        result = 0;
    }

    return result;
}
IOTHUB_DEVICE_METHOD_RESULT  IoTHubDeviceMethod_Invoke(IOTHUB_SERVICE_CLIENT_DEVICE_METHOD_HANDLE serviceClientDeviceMethodHandle, const char* deviceId, const char* methodName, const char* methodPayload, unsigned int timeout, int* responseStatus, unsigned char** responsePayload, size_t* responsePayloadSize)
{
    IOTHUB_DEVICE_METHOD_RESULT result;
    
    /*Codes_SRS_IOTHUBDEVICEMETHOD_12_031: [ IoTHubDeviceMethod_Invoke shall verify the input parameters and if any of them (except the timeout) are NULL then return IOTHUB_DEVICE_METHOD_INVALID_ARG ]*/
    if ((serviceClientDeviceMethodHandle == NULL) || (deviceId == NULL) || (methodName == NULL) || (methodPayload == NULL) || (responseStatus == NULL) || (responsePayload == NULL) || (responsePayloadSize == NULL))
    {
        LogError("Input parameter cannot be NULL");
        result = IOTHUB_DEVICE_METHOD_INVALID_ARG;
    }
    else
    {
        BUFFER_HANDLE httpPayloadBuffer;
        BUFFER_HANDLE responseBuffer;
        
        /*Codes_SRS_IOTHUBDEVICEMETHOD_12_032: [ IoTHubDeviceMethod_Invoke shall create a BUFFER_HANDLE from methodName, timeout and methodPayload by calling BUFFER_create ]*/
        if ((httpPayloadBuffer = createMethodPayloadJson(methodName, timeout, methodPayload)) == NULL)
        {
            /*Codes_SRS_IOTHUBDEVICEMETHOD_12_033: [ If the creation fails, IoTHubDeviceMethod_Invoke shall return IOTHUB_DEVICE_METHOD_ERROR ]*/
            LogError("BUFFER creation failed for httpPayloadBuffer");
            result = IOTHUB_DEVICE_METHOD_ERROR;
        }
        /*Codes_SRS_IOTHUBDEVICEMETHOD_12_034: [ IoTHubDeviceMethod_Invoke shall allocate memory for response buffer by calling BUFFER_new ]*/
        else if ((responseBuffer = BUFFER_new()) == NULL)
        {
            /*Codes_SRS_IOTHUBDEVICEMETHOD_12_035: [ If the allocation failed, IoTHubDeviceMethod_Invoke shall return IOTHUB_DEVICE_METHOD_ERROR ]*/
            LogError("BUFFER_new failed for responseBuffer");
            BUFFER_delete(httpPayloadBuffer);
            result = IOTHUB_DEVICE_METHOD_ERROR;
        }
        /*Codes_SRS_IOTHUBDEVICEMETHOD_12_039: [ IoTHubDeviceMethod_Invoke shall create an HTTP POST request using methodPayloadBuffer ]*/
        /*Codes_SRS_IOTHUBDEVICEMETHOD_12_040: [ IoTHubDeviceMethod_Invoke shall create an HTTP POST request using the following HTTP headers: authorization=sasToken,Request-Id=1001,Accept=application/json,Content-Type=application/json,charset=utf-8 ]*/
        /*Codes_SRS_IOTHUBDEVICEMETHOD_12_041: [ IoTHubDeviceMethod_Invoke shall create an HTTPAPIEX_SAS_HANDLE handle by calling HTTPAPIEX_SAS_Create ]*/
        /*Codes_SRS_IOTHUBDEVICEMETHOD_12_042: [ IoTHubDeviceMethod_Invoke shall create an HTTPAPIEX_HANDLE handle by calling HTTPAPIEX_Create ]*/
        /*Codes_SRS_IOTHUBDEVICEMETHOD_12_043: [ IoTHubDeviceMethod_Invoke shall execute the HTTP POST request by calling HTTPAPIEX_ExecuteRequest ]*/
        else if (sendHttpRequestDeviceMethod(serviceClientDeviceMethodHandle, IOTHUB_DEVICEMETHOD_REQUEST_INVOKE, deviceId, httpPayloadBuffer, responseBuffer) != IOTHUB_DEVICE_METHOD_OK)
        {
            /*Codes_SRS_IOTHUBDEVICEMETHOD_12_044: [ If any of the call fails during the HTTP creation IoTHubDeviceMethod_Invoke shall fail and return IOTHUB_DEVICE_METHOD_HTTPAPI_ERROR ]*/
            /*Codes_SRS_IOTHUBDEVICEMETHOD_12_045: [ If any of the HTTPAPI call fails IoTHubDeviceMethod_Invoke shall fail and return IOTHUB_DEVICE_METHOD_HTTPAPI_ERROR ]*/
            /*Codes_SRS_IOTHUBDEVICEMETHOD_12_046: [ IoTHubDeviceMethod_Invoke shall verify the received HTTP status code and if it is not equal to 200 then return IOTHUB_DEVICE_METHOD_ERROR ]*/
            LogError("Failure sending HTTP request for device method invoke");
            BUFFER_delete(responseBuffer);
            BUFFER_delete(httpPayloadBuffer);
            result = IOTHUB_DEVICE_METHOD_ERROR;
        }
        /*Codes_SRS_IOTHUBDEVICEMETHOD_12_049: [ Otherwise IoTHubDeviceMethod_Invoke shall save the received status and payload to the corresponding out parameter and return with IOTHUB_DEVICE_METHOD_OK ]*/
        else if ((parseResponseJson(responseBuffer, responseStatus, responsePayload, responsePayloadSize)) != IOTHUB_DEVICE_METHOD_OK)
        {
            /*Codes_SRS_IOTHUBDEVICEMETHOD_12_047: [ If parsing the response fails IoTHubDeviceMethod_Invoke shall return IOTHUB_DEVICE_METHOD_ERROR ]*/
            LogError("Failure parsing response");
            BUFFER_delete(responseBuffer);
            BUFFER_delete(httpPayloadBuffer);
            result = IOTHUB_DEVICE_METHOD_ERROR;
        }
        else
        {
            /*Codes_SRS_IOTHUBDEVICEMETHOD_12_049: [ Otherwise IoTHubDeviceMethod_Invoke shall save the received status and payload to the corresponding out parameter and return with IOTHUB_DEVICE_METHOD_OK ]*/
            result = IOTHUB_DEVICE_METHOD_OK;

            BUFFER_delete(responseBuffer);
            BUFFER_delete(httpPayloadBuffer);
        }
    }
    return result;
}
Beispiel #19
0
static void compile_file(const char *file)
{
	int i;
	time_t time_src, time_form, time_pot, time_output;
	char *source;

	COMPILE_begin(file, main_trans, main_debug);

	if (!main_compile_all)
	{
		if (FILE_exist(JOB->output))
		{
			time_src = FILE_get_time(JOB->name);
			time_output = FILE_get_time(JOB->output);

			if (JOB->form)
				time_form = FILE_get_time(JOB->form);
			else
				time_form = time_src;

			if (main_trans)
				time_pot = FILE_get_time(JOB->tname);
			else
				time_pot = time_src;

			if (time_src <= time_output && time_src <= time_pot && time_form <= time_output)
				goto _FIN;
		}
	}

	JOB->all = main_compile_all;
	JOB->exec = main_exec;
	JOB->verbose = main_verbose;
	JOB->warnings = main_warnings;
	JOB->swap = main_swap;
	JOB->public_module = main_public_module;
	JOB->no_old_read_syntax = main_no_old_read_syntax;
	//JOB->class_file = main_class_file;

	if (JOB->verbose)
	{
		putchar('\n');
		for (i = 1; i <= 9; i++)
			printf("--------");
		printf("\nCompiling %s...\n", FILE_get_name(JOB->name));
	}

	JOB->first_line = 1;

	if (JOB->form)
	{
		JOB->first_line = FORM_FIRST_LINE;
		BUFFER_add(&JOB->source, "#Line " FORM_FIRST_LINE_STRING "\n", -1);
		
		BUFFER_create(&source);
		BUFFER_load_file(&source, JOB->form);
		BUFFER_add(&source, "\n\0", 2);

		switch (JOB->family->type)
		{
			case FORM_WEBPAGE:
				FORM_webpage(source);
				break;
				
			case FORM_NORMAL:
			default:
				FORM_do(source, main_public);
				break;
		}
				
		BUFFER_delete(&source);
		
		BUFFER_add(&JOB->source, "#Line 1\n", -1);
	}
	
	COMPILE_load();
	BUFFER_add(&JOB->source, "\n\0", 2);
	
	#if 0
	fprintf(stderr, "-----------------\n");
	fputs(JOB->source, stderr);
	fprintf(stderr, "-----------------\n");
	#endif

	READ_do();

	#ifdef DEBUG
	TABLE_print(JOB->class->table, TRUE);
	#endif

	HEADER_do();
	TRANS_code();

	#ifdef DEBUG
	TABLE_print(JOB->class->string, FALSE);
	#endif

	OUTPUT_do(main_swap);
	CLASS_export();

_FIN:
	COMPILE_end();
}
Beispiel #20
0
/*Codes_SRS_IOTHUBMESSAGE_03_001: [IoTHubMessage_Clone shall create a new IoT hub message with data content identical to that of the iotHubMessageHandle parameter.]*/
IOTHUB_MESSAGE_HANDLE IoTHubMessage_Clone(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
{
    IOTHUB_MESSAGE_HANDLE_DATA* result;
    const IOTHUB_MESSAGE_HANDLE_DATA* source = (const IOTHUB_MESSAGE_HANDLE_DATA*)iotHubMessageHandle;
    /* Codes_SRS_IOTHUBMESSAGE_03_005: [IoTHubMessage_Clone shall return NULL if iotHubMessageHandle is NULL.] */
    if (source == NULL)
    {
        result = NULL;
        LogError("iotHubMessageHandle parameter cannot be NULL for IoTHubMessage_Clone\r\n");
    }
    else
    {
        result = (IOTHUB_MESSAGE_HANDLE_DATA*)malloc(sizeof(IOTHUB_MESSAGE_HANDLE_DATA));
        /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/
        if (result == NULL)
        {
            /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/
            /*do nothing and return as is*/
            LogError("unable to malloc\r\n");
        }
        else
        {
            result->messageId = NULL;
            result->correlationId = NULL;
            if (source->messageId != NULL && mallocAndStrcpy_s(&result->messageId, source->messageId) != 0)
            {
                LogError("unable to Copy messageId\r\n");
                free(result);
                result = NULL;
            }
            else if (source->correlationId != NULL && mallocAndStrcpy_s(&result->correlationId, source->correlationId) != 0)
            {
                LogError("unable to Copy correlationId\r\n");
                if (result->messageId != NULL)
                {
                    free(result->messageId);
                    result->messageId = NULL;
                }
                free(result);
                result = NULL;
            }
            else if (source->contentType == IOTHUBMESSAGE_BYTEARRAY)
            {
                /*Codes_SRS_IOTHUBMESSAGE_02_006: [IoTHubMessage_Clone shall clone to content by a call to BUFFER_clone] */
                if ((result->value.byteArray = BUFFER_clone(source->value.byteArray)) == NULL)
                {
                    /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/
                    LogError("unable to BUFFER_clone\r\n");
                    if (result->messageId)
                    {
                        free(result->messageId);
                        result->messageId = NULL;
                    }
                    if (result->correlationId != NULL)
                    {
                        free(result->correlationId);
                        result->correlationId = NULL;
                    }
                    free(result);
                    result = NULL;
                }
                /*Codes_SRS_IOTHUBMESSAGE_02_005: [IoTHubMessage_Clone shall clone the properties map by using Map_Clone.] */
                else if ((result->properties = Map_Clone(source->properties)) == NULL)
                {
                    /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/
                    LogError("unable to Map_Clone\r\n");
                    BUFFER_delete(result->value.byteArray);
                    if (result->messageId)
                    {
                        free(result->messageId);
                        result->messageId = NULL;
                    }
                    if (result->correlationId != NULL)
                    {
                        free(result->correlationId);
                        result->correlationId = NULL;
                    }
                    free(result);
                    result = NULL;
                }
                else
                {
                    result->contentType = IOTHUBMESSAGE_BYTEARRAY;
                    /*Codes_SRS_IOTHUBMESSAGE_03_002: [IoTHubMessage_Clone shall return upon success a non-NULL handle to the newly created IoT hub message.]*/
                    /*return as is, this is a good result*/
                }
            }
            else /*can only be STRING*/
            {
                /*Codes_SRS_IOTHUBMESSAGE_02_006: [IoTHubMessage_Clone shall clone the content by a call to BUFFER_clone or STRING_clone] */
                if ((result->value.string = STRING_clone(source->value.string)) == NULL)
                {
                    /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/
                    if (result->messageId)
                    {
                        free(result->messageId);
                        result->messageId = NULL;
                    }
                    if (result->correlationId != NULL)
                    {
                        free(result->correlationId);
                        result->correlationId = NULL;
                    }
                    free(result);
                    result = NULL;
                    LogError("failed to STRING_clone\r\n");
                }
                /*Codes_SRS_IOTHUBMESSAGE_02_005: [IoTHubMessage_Clone shall clone the properties map by using Map_Clone.] */
                else if ((result->properties = Map_Clone(source->properties)) == NULL)
                {
                    /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/
                    LogError("unable to Map_Clone\r\n");
                    STRING_delete(result->value.string);
                    if (result->messageId)
                    {
                        free(result->messageId);
                        result->messageId = NULL;
                    }
                    if (result->correlationId != NULL)
                    {
                        free(result->correlationId);
                        result->correlationId = NULL;
                    }
                    free(result);
                    result = NULL;
                }
                else
                {
                    result->contentType = IOTHUBMESSAGE_STRING;
                    /*all is fine*/
                }
            }
        }
    }
    return result;
}
Beispiel #21
0
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;
}
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;
}
HTTPAPI_RESULT HTTPAPI_ExecuteRequest(HTTP_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
    HTTP_HEADERS_HANDLE httpHeadersHandle, const unsigned char* content,
    size_t contentLength, unsigned int* statusCode,
    HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent)
{
    HTTPAPI_RESULT result;
    HTTP_HANDLE_DATA* handleData = (HTTP_HANDLE_DATA*)handle;

    if ((handleData == NULL) ||
        (relativePath == NULL) ||
        (httpHeadersHandle == NULL))
    {
        result = HTTPAPI_INVALID_ARG;
        LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
    }
    else
    {
        wchar_t* requestTypeString = NULL;

        switch (requestType)
        {
        default:
            break;

        case HTTPAPI_REQUEST_GET:
            requestTypeString = L"GET";
            break;

        case HTTPAPI_REQUEST_POST:
            requestTypeString = L"POST";
            break;

        case HTTPAPI_REQUEST_PUT:
            requestTypeString = L"PUT";
            break;

        case HTTPAPI_REQUEST_DELETE:
            requestTypeString = L"DELETE";
            break;

        case HTTPAPI_REQUEST_PATCH:
            requestTypeString = L"PATCH";
            break;
        }

        if (requestTypeString == NULL)
        {
            result = HTTPAPI_INVALID_ARG;
            LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
        }
        else
        {
            wchar_t relativePathTemp[1024];
            char headers[1024];
            wchar_t headersTemp[1024];

            result = ConstructHeadersString(httpHeadersHandle, headers, sizeof(headers));
            if (result == HTTPAPI_OK)
            {
                if (MultiByteToWideChar(CP_ACP, 0, relativePath, -1, relativePathTemp, sizeof(relativePathTemp) / sizeof(relativePathTemp[0])) == 0)
                {
                    result = HTTPAPI_STRING_PROCESSING_ERROR;
                    LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                }
                else
                {
                    if (MultiByteToWideChar(CP_ACP, 0, headers, -1, headersTemp, sizeof(headersTemp) / sizeof(headersTemp[0])) == 0)
                    {
                        result = HTTPAPI_STRING_PROCESSING_ERROR;
                        LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                    }
                    else
                    {
                        PCWSTR rgpszAcceptTypes[] = { L"text/*", NULL };
                        HINTERNET requestHandle = HttpOpenRequestW(
                            handleData->ConnectionHandle,
                            requestTypeString,
                            relativePathTemp,
                            NULL,
                            NULL,
                            rgpszAcceptTypes,
                            INTERNET_FLAG_SECURE,
                            0);
                        if (requestHandle == NULL)
                        {
                            result = HTTPAPI_OPEN_REQUEST_FAILED;
                            LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                        }
                        else
                        {
                            unsigned long int timeout = 55000;
                            if (!InternetSetOption(
                                requestHandle,
                                INTERNET_OPTION_RECEIVE_TIMEOUT, /*Sets or retrieves an unsigned long integer value that contains the time-out value, in milliseconds, to receive a response to a request.*/
                                &timeout,
                                sizeof(timeout)))
                            {
                                result = HTTPAPI_SET_TIMEOUTS_FAILED;
                                LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                            }
                            else
                            {
                                DWORD dwSecurityFlags = 0;
                                if (!InternetSetOption(
                                    requestHandle,
                                    INTERNET_OPTION_SECURITY_FLAGS,
                                    &dwSecurityFlags,
                                    sizeof(dwSecurityFlags)))
                                {
                                    result = HTTPAPI_SET_OPTION_FAILED;
                                    LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                }
                                else
                                {
                                    if (!HttpSendRequestW(
                                        requestHandle,
                                        headersTemp,
                                        -1,
                                        (void*)content,
                                        contentLength))
                                    {
                                        result = HTTPAPI_SEND_REQUEST_FAILED;
LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                    }
                                    else
                                    {
                                        DWORD dwStatusCode = 0;
                                        DWORD dwBufferLength = sizeof(DWORD);
                                        DWORD responseBytesAvailable;

                                        if (responseHeadersHandle != NULL)
                                        {
                                            wchar_t responseHeadersTemp[16384];
                                            DWORD responseHeadersTempLength = sizeof(responseHeadersTemp);

                                            if (HttpQueryInfo(
                                                requestHandle,
                                                HTTP_QUERY_RAW_HEADERS_CRLF,
                                                responseHeadersTemp,
                                                &responseHeadersTempLength,
                                                0))
                                            {
                                                wchar_t *next_token;
                                                wchar_t* token = wcstok_s(responseHeadersTemp, L"\r\n", &next_token);
                                                while ((token != NULL) &&
                                                    (token[0] != L'\0'))
                                                {
                                                    char tokenTemp[1024];

                                                    if (WideCharToMultiByte(CP_ACP, 0, token, -1, tokenTemp, sizeof(tokenTemp), NULL, NULL) > 0)
                                                    {
                                                        /*breaking the token in 2 parts: everything before the first ":" and everything after the first ":"*/
                                                        /* if there is no such character, then skip it*/
                                                        /*if there is a : then replace is by a '\0' and so it breaks the original string in name and value*/

                                                        char* whereIsColon = strchr(tokenTemp, ':');
                                                        if (whereIsColon != NULL)
                                                        {
                                                            *whereIsColon = '\0';
                                                            HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, tokenTemp, whereIsColon + 1);
                                                        }
                                                    }
                                                    token = wcstok_s(NULL, L"\r\n", &next_token);
                                                }
                                            }
                                        }

                                        if (!HttpQueryInfo(
                                            requestHandle,
                                            HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
                                            &dwStatusCode,
                                            &dwBufferLength,
                                            0))
                                        {
                                            result = HTTPAPI_QUERY_HEADERS_FAILED;
                                            LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                        }
                                        else
                                        {
                                            BUFFER_HANDLE useToReadAllResponse = (responseContent != NULL) ? responseContent : BUFFER_new();
                                            /*HTTP status code (dwStatusCode) can be either ok (<HTTP_STATUS_AMBIGUOUS) or "not ok (>=HTTP_STATUS_AMBIGUOUS)*/
                                            if (useToReadAllResponse == NULL)
                                            {
                                                result = HTTPAPI_ERROR;
                                                LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                            }
                                            else
                                            {
                                                int goOnAndReadEverything = 1;
                                                /*set the response code*/
                                                if (statusCode != NULL)
                                                {
                                                    *statusCode = dwStatusCode;
                                                }

                                                do
                                                {
                                                    /*from MSDN:  If there is currently no data available and the end of the file has not been reached, the request waits until data becomes available*/
                                                    if (!InternetQueryDataAvailable(requestHandle, &responseBytesAvailable, 0, 0))
                                                    {
                                                        result = HTTPAPI_QUERY_DATA_AVAILABLE_FAILED;
                                                        LogError("InternetQueryDataAvailable failed (result = %s) GetLastError = %d\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result), GetLastError());
                                                        goOnAndReadEverything = 0;
                                                    }
                                                    else if (responseBytesAvailable == 0)
                                                    {
                                                        /*end of the stream, go out*/
                                                        if (dwStatusCode >= HTTP_STATUS_AMBIGUOUS)
                                                        {
                                                            LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                        }

                                                        result = HTTPAPI_OK;
                                                        goOnAndReadEverything = 0;
                                                    }
                                                    else
                                                    {
                                                        /*add the needed space to the buffer*/
                                                        if (BUFFER_enlarge(useToReadAllResponse, responseBytesAvailable) != 0)
                                                        {
                                                            result = HTTPAPI_ERROR;
                                                            LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                            goOnAndReadEverything = 0;
                                                        }
                                                        else
                                                        {
                                                            unsigned char* bufferContent;
                                                            size_t bufferSize;
                                                            /*add the data to the buffer*/
                                                            if (BUFFER_content(useToReadAllResponse, &bufferContent) != 0)
                                                            {
                                                                result = HTTPAPI_ERROR;
                                                                LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                goOnAndReadEverything = 0;
                                                            }
                                                            else if (BUFFER_size(useToReadAllResponse, &bufferSize) != 0)
                                                            {
                                                                result = HTTPAPI_ERROR;
                                                                LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                goOnAndReadEverything = 0;
                                                            }
                                                            else
                                                            {
                                                                DWORD bytesReceived;
                                                                if (!InternetReadFile(requestHandle, bufferContent + bufferSize - responseBytesAvailable, responseBytesAvailable, &bytesReceived))
                                                                {
                                                                    result = HTTPAPI_READ_DATA_FAILED;
                                                                    LogError("InternetReadFile failed (result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                    goOnAndReadEverything = 0;
                                                                }
                                                                else
                                                                {
                                                                    /*if for some reason bytesReceived is zero, MSDN says To ensure all data is retrieved, an application must continue to call the InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero*/
                                                                    if (bytesReceived == 0)
                                                                    {
                                                                        /*end of everything, but this looks like an error still, or a non-conformance between InternetQueryDataAvailable and InternetReadFile*/
                                                                        result = HTTPAPI_READ_DATA_FAILED;
                                                                        LogError("InternetReadFile failed (result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                        goOnAndReadEverything = 0;
                                                                    }
                                                                    else
                                                                    {
                                                                        /*all is fine, keep going*/
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                } while (goOnAndReadEverything != 0);

                                                if (responseContent == NULL)
                                                {
                                                    BUFFER_delete(useToReadAllResponse);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            (void)InternetCloseHandle(requestHandle);
                        }
                    }
                }
            }
        }
    }

    return result;
}
static int sign_sas_data(PROV_AUTH_INFO* auth_info, const char* payload, unsigned char** output, size_t* len)
{
    int result;
    size_t payload_len = strlen(payload);
    if (auth_info->sec_type == PROV_AUTH_TYPE_TPM)
    {
        if (auth_info->hsm_client_sign_data(auth_info->hsm_client_handle, (const unsigned char*)payload, strlen(payload), output, len) != 0)
        {
            LogError("Failed signing data");
            result = MU_FAILURE;
        }
        else
        {
            result = 0;
        }
    }
    else
    {
        char* symmetrical_key = auth_info->hsm_client_get_symm_key(auth_info->hsm_client_handle);
        if (symmetrical_key == NULL)
        {
            LogError("Failed getting asymmetrical key");
            result = MU_FAILURE;
        }
        else
        {
            BUFFER_HANDLE decoded_key;
            BUFFER_HANDLE output_hash;
            if ((decoded_key = Azure_Base64_Decode(symmetrical_key)) == NULL)
            {
                LogError("Failed decoding symmetrical key");
                result = MU_FAILURE;
            }
            else if ((output_hash = BUFFER_new()) == NULL)
            {
                LogError("Failed allocating output hash buffer");
                BUFFER_delete(decoded_key);
                result = MU_FAILURE;
            }
            else
            {
                size_t decoded_key_len = BUFFER_length(decoded_key);
                const unsigned char* decoded_key_bytes = BUFFER_u_char(decoded_key);

                if (HMACSHA256_ComputeHash(decoded_key_bytes, decoded_key_len, (const unsigned char*)payload, payload_len, output_hash) != HMACSHA256_OK)
                {
                    LogError("Failed computing HMAC Hash");
                    result = MU_FAILURE;
                }
                else
                {
                    *len = BUFFER_length(output_hash);
                    if ((*output = malloc(*len)) == NULL)
                    {
                        LogError("Failed allocating output buffer");
                        result = MU_FAILURE;
                    }
                    else
                    {
                        const unsigned char* output_data = BUFFER_u_char(output_hash);
                        memcpy(*output, output_data, *len);
                        result = 0;
                    }
                }
                BUFFER_delete(decoded_key);
                BUFFER_delete(output_hash);
            }
        }
        free(symmetrical_key);
    }
    return result;
}
Beispiel #25
0
IOTHUB_MESSAGE_HANDLE IoTHubMessage_CreateFromByteArray(const unsigned char* byteArray, size_t size)
{
    IOTHUB_MESSAGE_HANDLE_DATA* result;
    result = malloc(sizeof(IOTHUB_MESSAGE_HANDLE_DATA));
    if (result == NULL)
    {
        LogError("unable to malloc\r\n");
        /*Codes_SRS_IOTHUBMESSAGE_02_024: [If there are any errors then IoTHubMessage_CreateFromByteArray shall return NULL.] */
        /*let it go through*/
    }
    else
    {
        const unsigned char* source;
        unsigned char temp = 0x00;
        if (size != 0)
        {
            /*Codes_SRS_IOTHUBMESSAGE_06_002: [If size is NOT zero then byteArray MUST NOT be NULL*/
            if (byteArray == NULL)
            {
                LogError("Attempted to create a Hub Message from a NULL pointer!\r\n");
                free(result);
                result = NULL;
                source = NULL;
            }
            else
            {
                source = byteArray;
            }
        }
        else
        {
            /*Codes_SRS_IOTHUBMESSAGE_06_001: [If size is zero then byteArray may be NULL.]*/
            source = &temp;
        }
        if (result != NULL)
        {
            /*Codes_SRS_IOTHUBMESSAGE_02_022: [IoTHubMessage_CreateFromByteArray shall call BUFFER_create passing byteArray and size as parameters.] */
            if ((result->value.byteArray = BUFFER_create(source, size)) == NULL)
            {
                LogError("BUFFER_create failed\r\n");
                /*Codes_SRS_IOTHUBMESSAGE_02_024: [If there are any errors then IoTHubMessage_CreateFromByteArray shall return NULL.] */
                free(result);
                result = NULL;
            }
            /*Codes_SRS_IOTHUBMESSAGE_02_023: [IoTHubMessage_CreateFromByteArray shall call Map_Create to create the message properties.] */
            else if ((result->properties = Map_Create(ValidateAsciiCharactersFilter)) == NULL)
            {
                LogError("Map_Create failed\r\n");
                /*Codes_SRS_IOTHUBMESSAGE_02_024: [If there are any errors then IoTHubMessage_CreateFromByteArray shall return NULL.] */
                BUFFER_delete(result->value.byteArray);
                free(result);
                result = NULL;
            }
            else
            {
                /*Codes_SRS_IOTHUBMESSAGE_02_025: [Otherwise, IoTHubMessage_CreateFromByteArray shall return a non-NULL handle.] */
                /*Codes_SRS_IOTHUBMESSAGE_02_026: [The type of the new message shall be IOTHUBMESSAGE_BYTEARRAY.] */
                result->contentType = IOTHUBMESSAGE_BYTEARRAY;
                result->messageId = NULL;
                result->correlationId = NULL;
                /*all is fine, return result*/
            }
        }
    }
    return result;
}
HTTPAPI_RESULT HTTPAPI_ExecuteRequest(HTTP_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
    HTTP_HEADERS_HANDLE httpHeadersHandle, const unsigned char* content,
    size_t contentLength, unsigned int* statusCode,
    HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent)
{
    HTTPAPI_RESULT result;
    if (g_HTTPAPIState != HTTPAPI_INITIALIZED)
    {
        LogError("g_HTTPAPIState not HTTPAPI_INITIALIZED\r\n");
        result = HTTPAPI_NOT_INIT;
    }
    else
    {
        HTTP_HANDLE_DATA* handleData = (HTTP_HANDLE_DATA*)handle;

        if ((handleData == NULL) ||
            (relativePath == NULL) ||
            (httpHeadersHandle == NULL))
        {
            result = HTTPAPI_INVALID_ARG;
            LogError("NULL parameter detected (result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
        }
        else
        {
            wchar_t* requestTypeString = NULL;

            switch (requestType)
            {
            default:
                break;

            case HTTPAPI_REQUEST_GET:
                requestTypeString = L"GET";
                break;

            case HTTPAPI_REQUEST_POST:
                requestTypeString = L"POST";
                break;

            case HTTPAPI_REQUEST_PUT:
                requestTypeString = L"PUT";
                break;

            case HTTPAPI_REQUEST_DELETE:
                requestTypeString = L"DELETE";
                break;

            case HTTPAPI_REQUEST_PATCH:
                requestTypeString = L"PATCH";
                break;
            }

            if (requestTypeString == NULL)
            {
                result = HTTPAPI_INVALID_ARG;
                LogError("requestTypeString was NULL (result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
            }
            else
            {
                const char* headers2;
                headers2 = ConstructHeadersString(httpHeadersHandle);
                if (headers2 != NULL)
                {
                    size_t requiredCharactersForRelativePath = MultiByteToWideChar(CP_ACP, 0, relativePath, -1, NULL, 0);
                    wchar_t* relativePathTemp = malloc((requiredCharactersForRelativePath+1) * sizeof(wchar_t));
                    result = HTTPAPI_OK; /*legacy code*/

                    if (relativePathTemp == NULL)
                    {
                        result = HTTPAPI_ALLOC_FAILED;
                        LogError("malloc failed (result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                    }
                    else
                    {
                        if (MultiByteToWideChar(CP_ACP, 0, relativePath, -1, relativePathTemp, requiredCharactersForRelativePath) == 0)
                        {
                            result = HTTPAPI_STRING_PROCESSING_ERROR;
                            LogError("MultiByteToWideChar was 0. (result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                        }
                        else
                        {
                            size_t requiredCharactersForHeaders = MultiByteToWideChar(CP_ACP, 0, headers2, -1, NULL, 0);

                            wchar_t* headersTemp = malloc((requiredCharactersForHeaders +1) * sizeof(wchar_t) );
                            if (headersTemp == NULL)
                            {
                                result = HTTPAPI_STRING_PROCESSING_ERROR;
                                LogError("MultiByteToWideChar was 0. (result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                            }
                            else
                            {
                                if (MultiByteToWideChar(CP_ACP, 0, headers2, -1, headersTemp, requiredCharactersForHeaders) == 0)
                                {
                                    result = HTTPAPI_STRING_PROCESSING_ERROR;
                                    LogError("MultiByteToWideChar was 0(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                }
                                else
                                {
                                    HINTERNET requestHandle = WinHttpOpenRequest(
                                        handleData->ConnectionHandle,
                                        requestTypeString,
                                        relativePathTemp,
                                        NULL,
                                        WINHTTP_NO_REFERER,
                                        WINHTTP_DEFAULT_ACCEPT_TYPES,
                                        WINHTTP_FLAG_SECURE);
                                    if (requestHandle == NULL)
                                    {
                                        result = HTTPAPI_OPEN_REQUEST_FAILED;
                                        LogErrorWinHTTPWithGetLastErrorAsString("WinHttpOpenRequest failed (result = %s).\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                    }
                                    else
                                    {
                                        if (WinHttpSetTimeouts(requestHandle,
                                            0,                      /*_In_  int dwResolveTimeout - The initial value is zero, meaning no time-out (infinite). */
                                            60000,                  /*_In_  int dwConnectTimeout, -  The initial value is 60,000 (60 seconds).*/
                                            handleData->timeout,    /*_In_  int dwSendTimeout, -  The initial value is 30,000 (30 seconds).*/
                                            handleData->timeout     /* int dwReceiveTimeout The initial value is 30,000 (30 seconds).*/
                                            ) == FALSE)
                                        {
                                            result = HTTPAPI_SET_TIMEOUTS_FAILED;
                                            LogErrorWinHTTPWithGetLastErrorAsString("WinHttpOpenRequest failed (result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                        }
                                        else
                                        {
                                            DWORD dwSecurityFlags = 0;

                                            if (!WinHttpSetOption(
                                                requestHandle,
                                                WINHTTP_OPTION_SECURITY_FLAGS,
                                                &dwSecurityFlags,
                                                sizeof(dwSecurityFlags)))
                                            {
                                                result = HTTPAPI_SET_OPTION_FAILED;
                                                LogErrorWinHTTPWithGetLastErrorAsString("WinHttpSetOption failed (result = %s).\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                            }
                                            else
                                            {
                                                if (!WinHttpSendRequest(
                                                    requestHandle,
                                                    headersTemp,
                                                    (DWORD)-1L, /*An unsigned long integer value that contains the length, in characters, of the additional headers. If this parameter is -1L ... */
                                                    (void*)content,
                                                    (DWORD)contentLength,
                                                    (DWORD)contentLength,
                                                    0))
                                                {
                                                    result = HTTPAPI_SEND_REQUEST_FAILED;
                                                    LogErrorWinHTTPWithGetLastErrorAsString("WinHttpSendRequest: (result = %s).\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                }
                                                else
                                                {
                                                    if (!WinHttpReceiveResponse(
                                                        requestHandle,
                                                        0))
                                                    {
                                                        result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
                                                        LogErrorWinHTTPWithGetLastErrorAsString("WinHttpReceiveResponse: (result = %s).\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                    }
                                                    else
                                                    {
                                                        DWORD dwStatusCode = 0;
                                                        DWORD dwBufferLength = sizeof(DWORD);
                                                        DWORD responseBytesAvailable;

                                                        if (!WinHttpQueryHeaders(
                                                            requestHandle,
                                                            WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
                                                            WINHTTP_HEADER_NAME_BY_INDEX,
                                                            &dwStatusCode,
                                                            &dwBufferLength,
                                                            WINHTTP_NO_HEADER_INDEX))
                                                        {
                                                            result = HTTPAPI_QUERY_HEADERS_FAILED;
                                                            LogErrorWinHTTPWithGetLastErrorAsString("WinHttpQueryHeaders failed (result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                        }
                                                        else
                                                        {
                                                            BUFFER_HANDLE useToReadAllResponse = (responseContent != NULL) ? responseContent : BUFFER_new();

                                                            if (statusCode != NULL)
                                                            {
                                                                *statusCode = dwStatusCode;
                                                            }

                                                            if (useToReadAllResponse == NULL)
                                                            {
                                                                result = HTTPAPI_ERROR;
                                                                LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                            }
                                                            else
                                                            {

                                                                int goOnAndReadEverything = 1;
                                                                do
                                                                {
                                                                    /*from MSDN: If no data is available and the end of the file has not been reached, one of two things happens. If the session is synchronous, the request waits until data becomes available.*/
                                                                    if (!WinHttpQueryDataAvailable(requestHandle, &responseBytesAvailable))
                                                                    {
                                                                        result = HTTPAPI_QUERY_DATA_AVAILABLE_FAILED;
                                                                        LogErrorWinHTTPWithGetLastErrorAsString("WinHttpQueryDataAvailable failed (result = %s).\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                        goOnAndReadEverything = 0;
                                                                    }
                                                                    else if (responseBytesAvailable == 0)
                                                                    {
                                                                        /*end of the stream, go out*/
                                                                        if (dwStatusCode >= HTTP_STATUS_AMBIGUOUS)
                                                                        {
                                                                            LogError("HTTP status code was: %d \r\n", (int)dwStatusCode);
                                                                            LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                        }

                                                                        result = HTTPAPI_OK;
                                                                        goOnAndReadEverything = 0;
                                                                    }
                                                                    else
                                                                    {
                                                                        if (BUFFER_enlarge(useToReadAllResponse, responseBytesAvailable) != 0)
                                                                        {
                                                                            result = HTTPAPI_ERROR;
                                                                            LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                            goOnAndReadEverything = 0;
                                                                        }
                                                                        else
                                                                        {
                                                                            /*Add the read bytes to the response buffer*/
                                                                            size_t bufferSize;
                                                                            const unsigned char* bufferContent;

                                                                            if (BUFFER_content(useToReadAllResponse, &bufferContent) != 0)
                                                                            {
                                                                                result = HTTPAPI_ERROR;
                                                                                LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                                goOnAndReadEverything = 0;
                                                                            }
                                                                            else if (BUFFER_size(useToReadAllResponse, &bufferSize) != 0)
                                                                            {
                                                                                result = HTTPAPI_ERROR;
                                                                                LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                                goOnAndReadEverything = 0;
                                                                            }
                                                                            else
                                                                            {
                                                                                DWORD bytesReceived;
                                                                                if (!WinHttpReadData(requestHandle, (LPVOID)(bufferContent + bufferSize - responseBytesAvailable), responseBytesAvailable, &bytesReceived))
                                                                                {
                                                                                    result = HTTPAPI_READ_DATA_FAILED;
                                                                                    LogErrorWinHTTPWithGetLastErrorAsString("WinHttpReadData failed (result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                                    goOnAndReadEverything = 0;
                                                                                }
                                                                                else
                                                                                {
                                                                                    /*if for some reason bytesReceived is zero If you are using WinHttpReadData synchronously, and the return value is TRUE and the number of bytes read is zero, the transfer has been completed and there are no more bytes to read on the handle.*/
                                                                                    if (bytesReceived == 0)
                                                                                    {
                                                                                        /*end of everything, but this looks like an error still, or a non-conformance between WinHttpQueryDataAvailable and WinHttpReadData*/
                                                                                        result = HTTPAPI_READ_DATA_FAILED;
                                                                                        LogError("bytesReceived was unexpectedly zero (result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                                        goOnAndReadEverything = 0;
                                                                                    }
                                                                                    else
                                                                                    {
                                                                                        /*all is fine, keep going*/
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }

                                                                } while (goOnAndReadEverything != 0);

                                                                if (responseContent != NULL)
                                                                {
                                                                    if (BUFFER_u_char(responseContent) != NULL)
                                                                    {
                                                                        LogInfo("Buffer Content:\r\n %.*s\r\n", BUFFER_length(responseContent), BUFFER_u_char(responseContent));
                                                                    }
                                                                }
                                                                else if (useToReadAllResponse != NULL)
                                                                {
                                                                    if (BUFFER_u_char(useToReadAllResponse) != NULL)
                                                                    {
                                                                        LogInfo("Buffer Content:\r\n %.*s\r\n", BUFFER_length(useToReadAllResponse), BUFFER_u_char(useToReadAllResponse));
                                                                    }
                                                                    BUFFER_delete(useToReadAllResponse);
                                                                }
                                                            }
                                                        }

                                                        if (result == HTTPAPI_OK && responseHeadersHandle != NULL)
                                                        {
                                                            wchar_t* responseHeadersTemp;
                                                            DWORD responseHeadersTempLength = sizeof(responseHeadersTemp);

                                                            (void)WinHttpQueryHeaders(
                                                                requestHandle,
                                                                WINHTTP_QUERY_RAW_HEADERS_CRLF,
                                                                WINHTTP_HEADER_NAME_BY_INDEX,
                                                                WINHTTP_NO_OUTPUT_BUFFER,
                                                                &responseHeadersTempLength,
                                                                WINHTTP_NO_HEADER_INDEX);

                                                            responseHeadersTemp = (wchar_t*)malloc(responseHeadersTempLength + 2);
                                                            if (responseHeadersTemp == NULL)
                                                            {
                                                                result = HTTPAPI_ALLOC_FAILED;
                                                                LogError("malloc failed: (result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                            }
                                                            else
                                                            {
                                                                if (WinHttpQueryHeaders(
                                                                    requestHandle,
                                                                    WINHTTP_QUERY_RAW_HEADERS_CRLF,
                                                                    WINHTTP_HEADER_NAME_BY_INDEX,
                                                                    responseHeadersTemp,
                                                                    &responseHeadersTempLength,
                                                                    WINHTTP_NO_HEADER_INDEX))
                                                                {
                                                                    wchar_t *next_token;
                                                                    wchar_t* token = wcstok_s(responseHeadersTemp, L"\r\n", &next_token);
                                                                    while ((token != NULL) &&
                                                                        (token[0] != L'\0'))
                                                                    {
                                                                        char* tokenTemp;
                                                                        size_t tokenTemp_size;

                                                                        tokenTemp_size = WideCharToMultiByte(CP_ACP, 0, token, -1, NULL, 0, NULL, NULL);
                                                                        if (tokenTemp_size == 0)
                                                                        {
                                                                            LogError("WideCharToMultiByte failed\r\n");
                                                                        }
                                                                        else
                                                                        {
                                                                            tokenTemp = malloc(sizeof(char)*tokenTemp_size);
                                                                            if (tokenTemp == NULL)
                                                                            {
                                                                                LogError("malloc failed\r\n");
                                                                            }
                                                                            else
                                                                            {
                                                                                if (WideCharToMultiByte(CP_ACP, 0, token, -1, tokenTemp, tokenTemp_size, NULL, NULL) > 0)
                                                                                {
                                                                                    /*breaking the token in 2 parts: everything before the first ":" and everything after the first ":"*/
                                                                                    /* if there is no such character, then skip it*/
                                                                                    /*if there is a : then replace is by a '\0' and so it breaks the original string in name and value*/

                                                                                    char* whereIsColon = strchr(tokenTemp, ':');
                                                                                    if (whereIsColon != NULL)
                                                                                    {
                                                                                        *whereIsColon = '\0';
                                                                                        if (HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, tokenTemp, whereIsColon + 1) != HTTP_HEADERS_OK)
                                                                                        {
                                                                                            LogError("HTTPHeaders_AddHeaderNameValuePair failed\r\n");
                                                                                            result = HTTPAPI_HTTP_HEADERS_FAILED;
                                                                                            break;
                                                                                        }
                                                                                    }
                                                                                }
                                                                                else
                                                                                {
                                                                                    LogError("WideCharToMultiByte failed\r\n");
                                                                                }
                                                                                free(tokenTemp);
                                                                            }
                                                                        }
                                                                        

                                                                        token = wcstok_s(NULL, L"\r\n", &next_token);
                                                                    }
                                                                }
                                                                else
                                                                {
                                                                    LogError("WinHttpQueryHeaders failed\r\n");
                                                                }

                                                                free(responseHeadersTemp);
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                        (void)WinHttpCloseHandle(requestHandle);
                                    }
                                }
                                free(headersTemp);
                            }
                        }
                        free(relativePathTemp);
                    }
                    free((void*)headers2);
                }
                else
                {
                    result = HTTPAPI_ALLOC_FAILED; /*likely*/
                    LogError("ConstructHeadersString failed\r\n");
                }
            }
        }
    }

    return result;
}