Add more granular upload-to-blob functions, refactor u2b code (#2498)
* Add more granular upload-to-blob functions, refactor u2b code * [ACR] Expose upload-to-blob correlation ID and SAS URI in new API functions * Address code review comments (2) * Update unit tests for blob.c * Update iothub_client_ll_u2b_ut * Update iothub_client_ll_u2b_ut (continued) and other fixes * Update iothub_client_ll_u2b_ut (continued 2) * Update iothub_client_ll_u2b_ut (continued 3) * Update iothub_client_ll_u2b_ut (continued 4) * Updates to iothub_client_core_ll_ut * Updates to iothub_client_core_ll_ut (continued) * Additional unit test fixes * Fix return of blob result in iothubclient_ll_u2b_ut * Fix size_t to int conversion in iothub_client_ll_uploadtoblob.c * Add fixes for clang build * More fixes for clang and windows builds * Fix DONT_USE_UPLOADTOBLOB guards in code * More build and test fixes * More build fixes * More test fixes in iothub_client_ll_u2b_ut for OSX pipeline * Reduce number of iterations of IoTHub_MQTT_UploadCloseHandle_Before_WorkersComplete * Address CR comments from Eric * Add retry logic to iothub_client_sample_upload_to_blob_custom * Address code review comments (function renaming) * Verify and log http response status code in u2b functions * Update blob_ut * Address final CR comments
This commit is contained in:
Родитель
5ce08e60ea
Коммит
979d0718d2
|
@ -17,7 +17,7 @@
|
|||
#include "azure_c_shared_utility/buffer_.h"
|
||||
#include "azure_c_shared_utility/strings_types.h"
|
||||
#include "azure_c_shared_utility/httpapiex.h"
|
||||
#include "iothub_client_core_ll.h"
|
||||
#include "azure_c_shared_utility/singlylinkedlist.h"
|
||||
#include "azure_c_shared_utility/shared_util_options.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -46,36 +46,47 @@ extern "C"
|
|||
|
||||
MU_DEFINE_ENUM_WITHOUT_INVALID(BLOB_RESULT, BLOB_RESULT_VALUES)
|
||||
|
||||
/**
|
||||
* @brief Synchronously uploads a byte array to blob storage
|
||||
*
|
||||
* @param SASURI The URI to use to upload data
|
||||
* @param getDataCallbackEx A callback to be invoked to acquire the file chunks to be uploaded, as well as to indicate the status of the upload of the previous block.
|
||||
* @param context Any data provided by the user to serve as context on getDataCallback.
|
||||
* @param httpStatus A pointer to an out argument receiving the HTTP status (available only when the return value is BLOB_OK)
|
||||
* @param httpResponse A BUFFER_HANDLE that receives the HTTP response from the server (available only when the return value is BLOB_OK)
|
||||
* @param certificates A null terminated string containing CA certificates to be used
|
||||
* @param proxyOptions A structure that contains optional web proxy information
|
||||
* @param networkInterface An optional null terminated string containing the network interface
|
||||
* @param timeoutInMilliseconds The maximum time in ms allowed for a blob transfer. A value of 0 uses the default timeout for the underlying transport.
|
||||
*
|
||||
* @return A @c BLOB_RESULT. BLOB_OK means the blob has been uploaded successfully. Any other value indicates an error
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, 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, const char*, networkInterface, const size_t, timeoutInMilliseconds)
|
||||
MOCKABLE_FUNCTION(, HTTPAPIEX_HANDLE, Blob_CreateHttpConnection, const char*, blobStorageHostname, const char*, certificates, const HTTP_PROXY_OPTIONS*, proxyOptions, const char*, networkInterface, const size_t, timeoutInMilliseconds);
|
||||
|
||||
MOCKABLE_FUNCTION(, void, Blob_DestroyHttpConnection, HTTPAPIEX_HANDLE, httpApiExHandle);
|
||||
|
||||
MOCKABLE_FUNCTION(, void, Blob_ClearBlockIdList, SINGLYLINKEDLIST_HANDLE, blockIdList);
|
||||
|
||||
/**
|
||||
* @brief Synchronously uploads a byte array as a new block to blob storage
|
||||
* @brief Synchronously uploads a byte array as a new block to blob storage (put block operation)
|
||||
*
|
||||
* @param requestContent The data to upload
|
||||
* @param blockId The block id (from 00000 to 49999)
|
||||
* @param xml The XML file containing the blockId list
|
||||
* @param httpApiExHandle The HTTP connection handle
|
||||
* @param relativePath The destination path within the storage
|
||||
* @param httpApiExHandle The connection handle
|
||||
* @param blockID The block id (from 00000 to 49999)
|
||||
* @param blockData The data to upload
|
||||
* @param blockIDList The list where to store the block IDs
|
||||
* @param httpStatus A pointer to an out argument receiving the HTTP status (available only when the return value is BLOB_OK)
|
||||
* @param httpResponse A BUFFER_HANDLE that receives the HTTP response from the server (available only when the return value is BLOB_OK)
|
||||
*/
|
||||
//MOCKABLE_FUNCTION(, BLOB_RESULT, Blob_UploadNextBlock, BUFFER_HANDLE, requestContent, unsigned int, blockID, STRING_HANDLE, xml, const char*, relativePath, HTTPAPIEX_HANDLE, httpApiExHandle, unsigned int*, httpStatus, BUFFER_HANDLE, httpResponse)
|
||||
MOCKABLE_FUNCTION(, BLOB_RESULT, Blob_UploadBlock, HTTPAPIEX_HANDLE, httpApiExHandle, const char*, relativePath, BUFFER_HANDLE, requestContent, unsigned int, blockID, STRING_HANDLE, blockIDList, unsigned int*, httpStatus, BUFFER_HANDLE, httpResponse)
|
||||
MOCKABLE_FUNCTION(, BLOB_RESULT, Blob_PutBlock,
|
||||
HTTPAPIEX_HANDLE, httpApiExHandle,
|
||||
const char*, relativePath,
|
||||
unsigned int, blockID,
|
||||
BUFFER_HANDLE, blockData,
|
||||
SINGLYLINKEDLIST_HANDLE, blockIDList,
|
||||
unsigned int*, httpStatus,
|
||||
BUFFER_HANDLE, httpResponse)
|
||||
|
||||
/**
|
||||
* @brief Synchronously sends a put block list request to Azure Storage
|
||||
*
|
||||
* @param httpApiExHandle The HTTP connection handle
|
||||
* @param relativePath The destination path within the storage
|
||||
* @param blockIDList The list containing the block IDs to report
|
||||
* @param httpStatus A pointer to an out argument receiving the HTTP status (available only when the return value is BLOB_OK)
|
||||
* @param httpResponse A BUFFER_HANDLE that receives the HTTP response from the server (available only when the return value is BLOB_OK)
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, BLOB_RESULT, Blob_PutBlockList,
|
||||
HTTPAPIEX_HANDLE, httpApiExHandle,
|
||||
const char*, relativePath,
|
||||
SINGLYLINKEDLIST_HANDLE, blockIDList,
|
||||
unsigned int*, httpStatus,
|
||||
BUFFER_HANDLE, httpResponse)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
#ifndef IOTHUB_CLIENT_LL_UPLOADTOBLOB_H
|
||||
#define IOTHUB_CLIENT_LL_UPLOADTOBLOB_H
|
||||
|
||||
#include "iothub_client_core_ll.h"
|
||||
#include "iothub_client_core_common.h"
|
||||
#include "internal/iothub_client_authorization.h"
|
||||
|
||||
#include "umock_c/umock_c_prod.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cstddef>
|
||||
extern "C"
|
||||
|
@ -41,9 +41,33 @@ extern "C"
|
|||
|
||||
typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE;
|
||||
|
||||
/*
|
||||
* @remark `struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_STRUCT` contains information specifically
|
||||
* related to an individual upload request currently active in Azure IoT Hub, mainly
|
||||
* the correlation-id and Azure Blob SAS URI provided by the Azure IoT Hub when a new
|
||||
* upload is started. The `struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA` on the other hand
|
||||
* holds common information (independent from individual upload requests) that is used for
|
||||
* upload-to-blob Rest API calls to Azure IoT Hub.
|
||||
*/
|
||||
typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_STRUCT* IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE;
|
||||
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, IoTHubClient_LL_UploadToBlob_Create, const IOTHUB_CLIENT_CONFIG*, config, IOTHUB_AUTHORIZATION_HANDLE, auth_handle);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_Impl, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, destinationFileName, const unsigned char*, source, size_t, size);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
|
||||
|
||||
/*
|
||||
* @remark This is a legacy function that provides compatibility with the exposed public API for
|
||||
* upload to blob in iothub_(device|module)_client(_ll) that allowed passing a callback for obtaining the
|
||||
* blob blocks data. Since there was quite a lot of (specific) logic put into this function, it
|
||||
* better remain in this API module.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
|
||||
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_InitializeUpload, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClient_LL_UploadToBlob_CreateContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, azureBlobSasUri);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_PutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_PutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext);
|
||||
MOCKABLE_FUNCTION(, void, IoTHubClient_LL_UploadToBlob_DestroyContext, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, uploadContext);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_NotifyCompletion, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage);
|
||||
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob_SetOption, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle, const char*, optionName, const void*, value);
|
||||
MOCKABLE_FUNCTION(, void, IoTHubClient_LL_UploadToBlob_Destroy, IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, handle);
|
||||
|
||||
|
|
|
@ -52,6 +52,12 @@ extern "C"
|
|||
#ifndef DONT_USE_UPLOADTOBLOB
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_UploadToBlobAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK, iotHubClientFileUploadCallback, void*, context);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_UploadMultipleBlocksToBlobAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_InitializeUpload, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClientCore_AzureStorageCreateClient, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_AzureStoragePutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle);
|
||||
MOCKABLE_FUNCTION(, void, IoTHubClientCore_AzureStorageDestroyClient, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_NotifyUploadCompletion, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage);
|
||||
#endif /* DONT_USE_UPLOADTOBLOB */
|
||||
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_SendEventToOutputAsync, IOTHUB_CLIENT_CORE_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, const char*, outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback);
|
||||
|
|
|
@ -18,6 +18,9 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_CLIENT_CORE_LL_HAND
|
|||
#include "umock_c/umock_c_prod.h"
|
||||
#include "iothub_transport_ll.h"
|
||||
#include "iothub_client_core_common.h"
|
||||
#ifndef DONT_USE_UPLOADTOBLOB
|
||||
#include "internal/iothub_client_ll_uploadtoblob.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
@ -52,6 +55,12 @@ extern "C"
|
|||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadToBlob, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadMultipleBlocksToBlob, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, void*, context);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_InitializeUpload, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, IoTHubClientCore_LL_AzureStorageCreateClient, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_AzureStoragePutBlock, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle);
|
||||
MOCKABLE_FUNCTION(, void, IoTHubClientCore_LL_AzureStorageDestroyClient, IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, azureStorageClientHandle);
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClientCore_LL_NotifyUploadCompletion, IOTHUB_CLIENT_CORE_LL_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage);
|
||||
#endif /*DONT_USE_UPLOADTOBLOB*/
|
||||
|
||||
#ifdef USE_EDGE_MODULES
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "iothub_client_core.h"
|
||||
#include "iothub_device_client_ll.h"
|
||||
|
||||
|
||||
#ifndef IOTHUB_DEVICE_CLIENT_INSTANCE_TYPE
|
||||
/**
|
||||
* @brief Handle corresponding to a convenience layer device client instance.
|
||||
|
@ -35,6 +34,12 @@ typedef IOTHUB_CLIENT_CORE_HANDLE IOTHUB_DEVICE_CLIENT_HANDLE;
|
|||
#define IOTHUB_DEVICE_CLIENT_INSTANCE_TYPE
|
||||
#endif // IOTHUB_CLIENT_INSTANCE
|
||||
|
||||
#ifndef DONT_USE_UPLOADTOBLOB
|
||||
/**
|
||||
* @brief Handle for Upload-to-Blob API Functions.
|
||||
*/
|
||||
typedef IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IOTHUB_CLIENT_AZURE_STORAGE_CLIENT_HANDLE;
|
||||
#endif // DONT_USE_UPLOADTOBLOB
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
@ -349,6 +354,155 @@ extern "C"
|
|||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
|
||||
|
||||
/**
|
||||
* @brief This API creates a new upload within Azure IoT Hub, getting back a correlation-id and a
|
||||
* SAS URI for the Blob upload to the Azure Storage associated with the Azure IoT Hub.
|
||||
* @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads.
|
||||
* This function is expected to be used along with:
|
||||
* `IoTHubDeviceClient_AzureStorageCreateClient`
|
||||
* `IoTHubDeviceClient_AzureStoragePutBlock`
|
||||
* `IoTHubDeviceClient_AzureStoragePutBlockList`
|
||||
* `IoTHubDeviceClient_AzureStorageDestroyClient`
|
||||
* `IoTHubDeviceClient_AzureStorageInitializeBlobUpload`
|
||||
* `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion`
|
||||
* For simpler/less-granular control of uploads to Azure blob storage please use either
|
||||
* `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`.
|
||||
*
|
||||
* @param iotHubClientHandle The handle created by a call to the create function.
|
||||
* @param destinationFileName Name of the file in blob storage.
|
||||
* @param uploadCorrelationId Variable where to store the correlation-id of the new upload.
|
||||
* @param azureBlobSasUri Variable where to store the Azure Storage SAS URI for the new upload.
|
||||
*
|
||||
* @warning This is a synchronous/blocking function.
|
||||
* `uploadCorrelationId` and `azureBlobSasUri` must be freed by the calling application
|
||||
* after the blob upload process is done (e.g., after calling `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion`).
|
||||
*
|
||||
* @return An IOTHUB_CLIENT_RESULT value indicating the success or failure of the API call.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_AzureStorageInitializeBlobUpload, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri);
|
||||
|
||||
/**
|
||||
* @brief This API creates a client for a new blob upload to Azure Storage.
|
||||
* @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads.
|
||||
* This function is expected to be used along with:
|
||||
* `IoTHubDeviceClient_AzureStorageCreateClient`
|
||||
* `IoTHubDeviceClient_AzureStoragePutBlock`
|
||||
* `IoTHubDeviceClient_AzureStoragePutBlockList`
|
||||
* `IoTHubDeviceClient_AzureStorageDestroyClient`
|
||||
* `IoTHubDeviceClient_AzureStorageInitializeBlobUpload`
|
||||
* `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion`
|
||||
* For simpler/less-granular control of uploads to Azure blob storage please use either
|
||||
* `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`.
|
||||
*
|
||||
* @param iotHubClientHandle The handle created by a call to the create function.
|
||||
* @param azureBlobSasUri The Azure Storage Blob SAS uri obtained with `IoTHubDeviceClient_AzureStorageInitializeBlobUpload`.
|
||||
*
|
||||
* @warning This is a synchronous/blocking function.
|
||||
*
|
||||
* @return A `IOTHUB_CLIENT_AZURE_STORAGE_CLIENT_HANDLE` on success or NULL if the function fails.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_AZURE_STORAGE_CLIENT_HANDLE, IoTHubDeviceClient_AzureStorageCreateClient, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri);
|
||||
|
||||
/**
|
||||
* @brief This API uploads a single blob block to Azure Storage (performs a PUT BLOCK operation).
|
||||
* @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads.
|
||||
* This function is expected to be used along with:
|
||||
* `IoTHubDeviceClient_AzureStorageCreateClient`
|
||||
* `IoTHubDeviceClient_AzureStoragePutBlock`
|
||||
* `IoTHubDeviceClient_AzureStoragePutBlockList`
|
||||
* `IoTHubDeviceClient_AzureStorageDestroyClient`
|
||||
* `IoTHubDeviceClient_AzureStorageInitializeBlobUpload`
|
||||
* `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion`
|
||||
* For simpler/less-granular control of uploads to Azure blob storage please use either
|
||||
* `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`.
|
||||
* For more information about Azure Storage PUT BLOCK, its parameters and behavior, please refer to
|
||||
* https://learn.microsoft.com/en-us/rest/api/storageservices/put-block
|
||||
*
|
||||
* @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_AzureStorageCreateClient`.
|
||||
* @param blockNumber Number of the block being uploaded.
|
||||
* @param dataPtr Pointer to the block data to be uploaded to Azure Storage blob.
|
||||
* @param dataSize Size of the block data pointed by `dataPtr`.
|
||||
*
|
||||
* @warning This is a synchronous/blocking function.
|
||||
*
|
||||
* @return IOTHUB_CLIENT_OK upon success or an error code upon failure.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_AzureStoragePutBlock, IOTHUB_CLIENT_AZURE_STORAGE_CLIENT_HANDLE, azureStorageClientHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize);
|
||||
|
||||
/**
|
||||
* @brief This API performs an Azure Storage PUT BLOCK LIST operation.
|
||||
* @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads.
|
||||
* This function is expected to be used along with:
|
||||
* `IoTHubDeviceClient_AzureStorageCreateClient`
|
||||
* `IoTHubDeviceClient_AzureStoragePutBlock`
|
||||
* `IoTHubDeviceClient_AzureStoragePutBlockList`
|
||||
* `IoTHubDeviceClient_AzureStorageDestroyClient`
|
||||
* `IoTHubDeviceClient_AzureStorageInitializeBlobUpload`
|
||||
* `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion`
|
||||
* For simpler/less-granular control of uploads to Azure blob storage please use either
|
||||
* `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`.
|
||||
* If this function fails (due to any HTTP error to Azure Storage) it can
|
||||
* be run again for a discretionary number of times in an attempt to succeed after, for example,
|
||||
* an internet connectivity disruption is over.
|
||||
* For more information about Azure Storage PUT BLOCK LIST, please refer to
|
||||
* https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list
|
||||
*
|
||||
* @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_AzureStorageCreateClient`.
|
||||
*
|
||||
* @warning This is a synchronous/blocking function.
|
||||
*
|
||||
* @return IOTHUB_CLIENT_OK upon success or an error code upon failure.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_AzureStoragePutBlockList, IOTHUB_CLIENT_AZURE_STORAGE_CLIENT_HANDLE, azureStorageClientHandle);
|
||||
|
||||
/**
|
||||
* @brief This API destroys an instance previously created with `IoTHubDeviceClient_AzureStorageCreateClient`.
|
||||
* @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads.
|
||||
* This function is expected to be used along with:
|
||||
* `IoTHubDeviceClient_AzureStorageCreateClient`
|
||||
* `IoTHubDeviceClient_AzureStoragePutBlock`
|
||||
* `IoTHubDeviceClient_AzureStoragePutBlockList`
|
||||
* `IoTHubDeviceClient_AzureStorageDestroyClient`
|
||||
* `IoTHubDeviceClient_AzureStorageInitializeBlobUpload`
|
||||
* `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion`
|
||||
* For simpler/less-granular control of uploads to Azure blob storage please use either
|
||||
* `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`.
|
||||
*
|
||||
* @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_AzureStorageCreateClient`.
|
||||
*
|
||||
* @warning This is a synchronous/blocking function.
|
||||
*
|
||||
* @return Nothing.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, void, IoTHubDeviceClient_AzureStorageDestroyClient, IOTHUB_CLIENT_AZURE_STORAGE_CLIENT_HANDLE, azureStorageClientHandle);
|
||||
|
||||
/**
|
||||
* @brief This API notifies Azure IoT Hub of the upload completion.
|
||||
* @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads.
|
||||
* This function is expected to be used along with:
|
||||
* `IoTHubDeviceClient_AzureStorageCreateClient`
|
||||
* `IoTHubDeviceClient_AzureStoragePutBlock`
|
||||
* `IoTHubDeviceClient_AzureStoragePutBlockList`
|
||||
* `IoTHubDeviceClient_AzureStorageDestroyClient`
|
||||
* `IoTHubDeviceClient_AzureStorageInitializeBlobUpload`
|
||||
* `IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion`
|
||||
* For simpler/less-granular control of uploads to Azure blob storage please use either
|
||||
* `IoTHubDeviceClient_UploadToBlobAsync` or `IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync`.
|
||||
* If this function fails (due to any HTTP error to either Azure Storage or Azure IoT Hub) it can
|
||||
* be run again for a discretionary number of times in an attempt to succeed after, for example,
|
||||
* an internet connectivity disruption is over.
|
||||
*
|
||||
* @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_AzureStorageCreateClient`.
|
||||
* @param uploadCorrelationId Upload correlation-id obtained with `IoTHubDeviceClient_AzureStorageInitializeBlobUpload`.
|
||||
* @param isSuccess A boolean value indicating if the call(s) to `IoTHubDeviceClient_AzureStoragePutBlock` succeeded.
|
||||
* @param responseCode An user-defined code to signal the status of the upload (e.g., 200 for success, or -1 for abort).
|
||||
* @param responseMessage An user-defined status message to go along with `responseCode` on the notification to Azure IoT Hub.
|
||||
*
|
||||
* @warning This is a synchronous/blocking function.
|
||||
*
|
||||
* @return IOTHUB_CLIENT_OK upon success or an error code upon failure.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion, IOTHUB_DEVICE_CLIENT_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage);
|
||||
#endif /* DONT_USE_UPLOADTOBLOB */
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,6 +48,14 @@ extern "C"
|
|||
*/
|
||||
typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HANDLE;
|
||||
|
||||
#ifndef DONT_USE_UPLOADTOBLOB
|
||||
/**
|
||||
* @brief Handle for Upload-to-Blob API Functions.
|
||||
*/
|
||||
typedef IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE;
|
||||
#endif // DONT_USE_UPLOADTOBLOB
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a IoT Hub client for communication with an existing
|
||||
|
@ -378,6 +386,142 @@ typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_DEVICE_CLIENT_LL_HA
|
|||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
|
||||
|
||||
/**
|
||||
* @brief This API creates a new upload within Azure IoT Hub, getting back a correlation-id and a
|
||||
* SAS URI for the Blob access to the Azure Storage associated with the Azure IoT Hub.
|
||||
* @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads.
|
||||
* This function is expected to be used along with:
|
||||
* `IoTHubDeviceClient_LL_AzureStoragePutBlock`
|
||||
* `IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion`
|
||||
* `IoTHubDeviceClient_LL_AzureStorageDestroyClient`
|
||||
* For simpler/less-granular control of uploads to Azure blob storage please use either
|
||||
* `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`.
|
||||
*
|
||||
* @param iotHubClientHandle The handle created by a call to the create function.
|
||||
* @param destinationFileName Name of the file in blob storage.
|
||||
* @param uploadCorrelationId Variable where to store the correlation-id of the new upload.
|
||||
* @param azureBlobSasUri Variable where to store the Azure Storage SAS URI for the new upload.
|
||||
*
|
||||
* @warning This is a synchronous/blocking function.
|
||||
* This function only attempts to send HTTP requests once, it does not retry in case of failure.
|
||||
* Any retries must be explicitly implemented by the calling application.
|
||||
* `uploadCorrelationId` and `azureBlobSasUri` must be freed by the calling application
|
||||
* after the blob upload process is done (e.g., after calling `IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion`).
|
||||
*
|
||||
* @return An IOTHUB_CLIENT_RESULT value indicating the success or failure of the API call.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_AzureStorageInitializeBlobUpload, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, char**, uploadCorrelationId, char**, azureBlobSasUri);
|
||||
|
||||
/**
|
||||
* @brief This API creates a client for a new blob upload to Azure Storage.
|
||||
* @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads.
|
||||
* This function is expected to be used along with:
|
||||
* `IoTHubDeviceClient_LL_AzureStoragePutBlock`
|
||||
* `IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion`
|
||||
* `IoTHubDeviceClient_LL_AzureStorageDestroyClient`
|
||||
* For simpler/less-granular control of uploads to Azure blob storage please use either
|
||||
* `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`.
|
||||
*
|
||||
* @param iotHubClientHandle The handle created by a call to the create function.
|
||||
* @param azureBlobSasUri The Azure Storage Blob SAS uri obtained with `IoTHubDeviceClient_LL_AzureStorageInitializeBlobUpload`.
|
||||
*
|
||||
* @warning This is a synchronous/blocking function.
|
||||
*
|
||||
* @return A `IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE` on success or NULL if the function fails.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE, IoTHubDeviceClient_LL_AzureStorageCreateClient, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, azureBlobSasUri);
|
||||
|
||||
/**
|
||||
* @brief This API uploads a single blob block to Azure Storage (performs a PUT BLOCK operation).
|
||||
* @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads.
|
||||
* This function is expected to be used along with:
|
||||
* `IoTHubDeviceClient_LL_AzureStorageCreateClient`
|
||||
* `IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion`
|
||||
* `IoTHubDeviceClient_LL_AzureStorageDestroyClient`
|
||||
* For simpler/less-granular control of uploads to Azure blob storage please use either
|
||||
* `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`.
|
||||
* For more information about Azure Storage PUT BLOCK, its parameters and behavior, please refer to
|
||||
* https://learn.microsoft.com/en-us/rest/api/storageservices/put-block
|
||||
*
|
||||
* @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_LL_AzureStorageCreateClient`.
|
||||
* @param blockNumber Number of the block being uploaded.
|
||||
* @param dataPtr Pointer to the block data to be uploaded to Azure Storage blob.
|
||||
* @param dataSize Size of the block data pointed by `dataPtr`.
|
||||
*
|
||||
* @warning This is a synchronous/blocking function.
|
||||
* This function only attempts to send HTTP requests once, it does not retry in case of failure.
|
||||
* Any retries must be explicitly implemented by the calling application.
|
||||
*
|
||||
* @return IOTHUB_CLIENT_OK upon success or an error code upon failure.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_AzureStoragePutBlock, IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE, azureStorageClientHandle, uint32_t, blockNumber, const uint8_t*, dataPtr, size_t, dataSize);
|
||||
|
||||
/**
|
||||
* @brief This API performs an Azure Storage PUT BLOCK LIST operation.
|
||||
* @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads.
|
||||
* This function is expected to be used along with:
|
||||
* `IoTHubDeviceClient_LL_AzureStorageCreateClient`
|
||||
* `IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion`
|
||||
* `IoTHubDeviceClient_LL_AzureStorageDestroyClient`
|
||||
* For simpler/less-granular control of uploads to Azure blob storage please use either
|
||||
* `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`.
|
||||
* For more information about Azure Storage PUT BLOCK LIST, please refer to
|
||||
* https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list
|
||||
*
|
||||
* @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_LL_AzureStorageCreateClient`.
|
||||
*
|
||||
* @warning This is a synchronous/blocking function.
|
||||
* This function only attempts to send HTTP requests once, it does not retry in case of failure.
|
||||
* Any retries must be explicitly implemented by the calling application.
|
||||
*
|
||||
* @return IOTHUB_CLIENT_OK upon success or an error code upon failure.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_AzureStoragePutBlockList, IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE, azureStorageClientHandle);
|
||||
|
||||
/**
|
||||
* @brief This API destroys an instance previously created with `IoTHubDeviceClient_LL_AzureStorageCreateClient` .
|
||||
* @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads.
|
||||
* This function is expected to be used along with:
|
||||
* `IoTHubDeviceClient_LL_AzureStorageCreateClient`
|
||||
* `IoTHubDeviceClient_LL_AzureStoragePutBlock`
|
||||
* `IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion`
|
||||
* For simpler/less-granular control of uploads to Azure blob storage please use either
|
||||
* `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`.
|
||||
*
|
||||
* @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_LL_AzureStorageCreateClient`.
|
||||
*
|
||||
* @warning This is a synchronous/blocking function.
|
||||
*
|
||||
* @return Nothing.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, void, IoTHubDeviceClient_LL_AzureStorageDestroyClient, IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE, azureStorageClientHandle);
|
||||
|
||||
/**
|
||||
* @brief This API notifies Azure IoT Hub of the upload completion.
|
||||
* @remark It is part of a set of functions for more granular control over Azure IoT-based blob uploads.
|
||||
* This function is expected to be used along with:
|
||||
* `IoTHubDeviceClient_LL_AzureStorageCreateClient`
|
||||
* `IoTHubDeviceClient_LL_AzureStoragePutBlock`
|
||||
* `IoTHubDeviceClient_LL_AzureStorageDestroyClient`
|
||||
* For simpler/less-granular control of uploads to Azure blob storage please use either
|
||||
* `IoTHubDeviceClient_LL_UploadToBlob` or `IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob`.
|
||||
* If this function fails (due to any HTTP error to either Azure Storage or Azure IoT Hub) it can
|
||||
* be run again for a discretionary number of times in an attempt to succeed after, for example,
|
||||
* an internet connectivity disruption is over.
|
||||
*
|
||||
* @param azureStorageClientHandle The handle created with `IoTHubDeviceClient_LL_AzureStorageCreateClient`.
|
||||
* @param uploadCorrelationId Upload correlation-id obtained with `IoTHubDeviceClient_LL_AzureStorageInitializeBlobUpload`.
|
||||
* @param isSuccess A boolean value indicating if the call(s) to `IoTHubDeviceClient_LL_AzureStoragePutBlock` succeeded.
|
||||
* @param responseCode An user-defined code to signal the status of the upload (e.g., 200 for success, or -1 for abort).
|
||||
* @param responseMessage An user-defined status message to go along with `responseCode` on the notification to Azure IoT Hub.
|
||||
*
|
||||
* @warning This is a synchronous/blocking function.
|
||||
* This function only attempts to send HTTP requests once, it does not retry in case of failure.
|
||||
* Any retries must be explicitly implemented by the calling application.
|
||||
*
|
||||
* @return IOTHUB_CLIENT_OK upon success or an error code upon failure.
|
||||
*/
|
||||
MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion, IOTHUB_DEVICE_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, uploadCorrelationId, bool, isSuccess, int, responseCode, const char*, responseMessage);
|
||||
#endif /*DONT_USE_UPLOADTOBLOB*/
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,6 +24,7 @@ if(${use_http})
|
|||
if(NOT ${dont_use_uploadtoblob})
|
||||
add_sample_directory(iothub_client_sample_upload_to_blob)
|
||||
add_sample_directory(iothub_client_sample_upload_to_blob_mb)
|
||||
add_sample_directory(iothub_client_sample_upload_to_blob_with_retry)
|
||||
endif()
|
||||
if (${use_edge_modules})
|
||||
add_sample_directory(iothub_client_sample_module_method_invoke)
|
||||
|
|
|
@ -35,6 +35,7 @@ static const char* connectionString = "[device connection string]";
|
|||
static const char* proxyHost = NULL;
|
||||
static int proxyPort = 0;
|
||||
|
||||
static const char* azureStorageBlobPath = "subdir/hello_world.txt";
|
||||
#define HELLO_WORLD "Hello World from IoTHubDeviceClient_LL_UploadToBlob"
|
||||
|
||||
int main(void)
|
||||
|
@ -73,7 +74,7 @@ int main(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (IoTHubDeviceClient_LL_UploadToBlob(device_ll_handle, "subdir/hello_world.txt", (const unsigned char*)HELLO_WORLD, sizeof(HELLO_WORLD) - 1) != IOTHUB_CLIENT_OK)
|
||||
if (IoTHubDeviceClient_LL_UploadToBlob(device_ll_handle, azureStorageBlobPath, (const unsigned char*)HELLO_WORLD, sizeof(HELLO_WORLD) - 1) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
(void)printf("hello world failed to upload\n");
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ static const char* connectionString = "[device connection string]";
|
|||
/*Optional string with http proxy host and integer for http proxy port (Linux only) */
|
||||
static const char* proxyHost = NULL;
|
||||
static int proxyPort = 0;
|
||||
static const char* azureStorageBlobPath = "subdir/hello_world_mb.txt";
|
||||
static const char* data_to_upload_format = "Hello World from IoTHubDeviceClient_LL_UploadToBlob block: %d\n";
|
||||
static char data_to_upload[128];
|
||||
static int block_count = 0;
|
||||
|
@ -48,7 +49,7 @@ static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataCallback(IOTHUB_CLIENT_F
|
|||
// Note that the IoT SDK caller does NOT free(*data), as a typical use case the buffer returned
|
||||
// to the IoT layer may be part of a larger buffer that this callback is chunking up for network sends.
|
||||
|
||||
if (block_count < 100)
|
||||
if (block_count < 10)
|
||||
{
|
||||
int len = snprintf(data_to_upload, sizeof(data_to_upload), data_to_upload_format, block_count);
|
||||
if (len < 0 || len >= sizeof(data_to_upload))
|
||||
|
@ -103,6 +104,11 @@ int main(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
#ifndef WIN32
|
||||
size_t log = 1;
|
||||
(void)IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_CURL_VERBOSE, &log);
|
||||
#endif // !WIN32
|
||||
|
||||
#ifdef SET_TRUSTED_CERT_IN_SAMPLES
|
||||
// Setting the Trusted Certificate. This is only necessary on systems without
|
||||
// built in certificate stores.
|
||||
|
@ -119,7 +125,7 @@ int main(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob(device_ll_handle, "subdir/hello_world_mb.txt", getDataCallback, NULL) != IOTHUB_CLIENT_OK)
|
||||
if (IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob(device_ll_handle, azureStorageBlobPath, getDataCallback, NULL) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
(void)printf("hello world failed to upload\n");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
#Copyright (c) Microsoft. All rights reserved.
|
||||
#Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
#this is CMakeLists.txt for iothub_client_sample_upload_to_blob_with_retry
|
||||
|
||||
compileAsC99()
|
||||
|
||||
if(NOT ${use_http})
|
||||
message(FATAL_ERROR "iothub_client_sample_upload_to_blob_with_retry being generated without HTTP support")
|
||||
endif()
|
||||
|
||||
set(iothub_client_sample_upload_to_blob_with_retry_c_files
|
||||
iothub_client_sample_upload_to_blob_with_retry.c
|
||||
)
|
||||
|
||||
set(iothub_client_sample_upload_to_blob_with_retry_h_files
|
||||
)
|
||||
|
||||
#Conditionally use the SDK trusted certs in the samples
|
||||
if(${use_sample_trusted_cert})
|
||||
add_definitions(-DSET_TRUSTED_CERT_IN_SAMPLES)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/certs)
|
||||
set(iothub_client_sample_upload_to_blob_with_retry_c_files ${iothub_client_sample_upload_to_blob_with_retry_c_files} ${PROJECT_SOURCE_DIR}/certs/certs.c)
|
||||
endif()
|
||||
|
||||
IF(WIN32)
|
||||
#windows needs this define
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_definitions(-DGB_MEASURE_MEMORY_FOR_THIS -DGB_DEBUG_ALLOC)
|
||||
ENDIF(WIN32)
|
||||
|
||||
include_directories(.)
|
||||
|
||||
add_executable(
|
||||
iothub_client_sample_upload_to_blob_with_retry
|
||||
${iothub_client_sample_upload_to_blob_with_retry_c_files}
|
||||
${iothub_client_sample_upload_to_blob_with_retry_h_files}
|
||||
)
|
||||
|
||||
target_link_libraries(iothub_client_sample_upload_to_blob_with_retry
|
||||
iothub_client
|
||||
iothub_client_http_transport
|
||||
)
|
||||
|
||||
linkSharedUtil(iothub_client_sample_upload_to_blob_with_retry)
|
||||
linkHttp(iothub_client_sample_upload_to_blob_with_retry)
|
|
@ -0,0 +1,207 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// CAVEAT: This sample is to demonstrate azure IoT client concepts only and is not a guide design principles or style
|
||||
// Checking of return codes and error values shall be omitted for brevity. Please practice sound engineering practices
|
||||
// when writing production code.
|
||||
|
||||
// This sample is also uses a much more improved API for performing
|
||||
// Azure IoT Hub-backed Azure Storage Blob uploads by:
|
||||
// Explicitly getting a SAS token for the Blob storage (usable by external tools such as az_copy).
|
||||
// Using the the built-in Azure Storage Blob new upload client.
|
||||
// Showing how to retry blob upload per block (as opposed to the entire file).
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* This sample uses the _LL APIs of iothub_client for example purposes.
|
||||
That does not mean that HTTP only works with the _LL APIs.
|
||||
Simply changing the using the convenience layer (functions not having _LL)
|
||||
and removing calls to _DoWork will yield the same results. */
|
||||
|
||||
#include "iothub.h"
|
||||
#include "iothub_device_client.h"
|
||||
|
||||
#include "azure_c_shared_utility/shared_util_options.h"
|
||||
#include "azure_c_shared_utility/threadapi.h"
|
||||
#include "iothub_message.h"
|
||||
#include "iothubtransportmqtt.h"
|
||||
|
||||
#ifdef SET_TRUSTED_CERT_IN_SAMPLES
|
||||
#include "certs.h"
|
||||
#endif // SET_TRUSTED_CERT_IN_SAMPLES
|
||||
|
||||
/*String containing Hostname, Device Id & Device Key in the format: */
|
||||
/* "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>" */
|
||||
/* "HostName=<host_name>;DeviceId=<device_id>;SharedAccessSignature=<device_sas_token>" */
|
||||
static const char* connectionString = "[device connection string]";
|
||||
|
||||
/*Optional string with http proxy host and integer for http proxy port (Linux only) */
|
||||
static const char* proxyHost = NULL;
|
||||
static int proxyPort = 0;
|
||||
|
||||
static const char* azureStorageBlobPath = "subdir/hello_world_mb_with_retry.txt";
|
||||
static const char* data_to_upload_format = "Hello World from iothub_client_sample_upload_to_blob_with_retry: %d\n";
|
||||
static char data_to_upload[128];
|
||||
|
||||
#define SAMPLE_MAX_RETRY_COUNT 3
|
||||
#define SAMPLE_RETRY_DELAY_MILLISECS 2000
|
||||
|
||||
int main(void)
|
||||
{
|
||||
IOTHUB_DEVICE_CLIENT_LL_HANDLE device_ll_handle;
|
||||
|
||||
// Used to initialize IoTHub SDK subsystem
|
||||
(void)IoTHub_Init();
|
||||
(void)printf("Starting the IoTHub client sample upload to blob...\r\n");
|
||||
|
||||
device_ll_handle = IoTHubDeviceClient_LL_CreateFromConnectionString(connectionString, MQTT_Protocol);
|
||||
if (device_ll_handle == NULL)
|
||||
{
|
||||
(void)printf("Failure creating IotHub device. Hint: Check your connection string.\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef WIN32
|
||||
size_t log = 1;
|
||||
(void)IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_CURL_VERBOSE, &log);
|
||||
#endif // !WIN32
|
||||
|
||||
#ifdef SET_TRUSTED_CERT_IN_SAMPLES
|
||||
// Setting the Trusted Certificate. This is only necessary on systems without
|
||||
// built in certificate stores.
|
||||
IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_TRUSTED_CERT, certificates);
|
||||
#endif // SET_TRUSTED_CERT_IN_SAMPLES
|
||||
|
||||
HTTP_PROXY_OPTIONS http_proxy_options = { 0 };
|
||||
http_proxy_options.host_address = proxyHost;
|
||||
http_proxy_options.port = proxyPort;
|
||||
|
||||
if (proxyHost != NULL && IoTHubDeviceClient_LL_SetOption(device_ll_handle, OPTION_HTTP_PROXY, &http_proxy_options) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
(void)printf("failure to set proxy\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
char* uploadCorrelationId;
|
||||
char* azureBlobSasUri;
|
||||
|
||||
if (IoTHubDeviceClient_LL_AzureStorageInitializeBlobUpload(
|
||||
device_ll_handle, azureStorageBlobPath, &uploadCorrelationId, &azureBlobSasUri) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
printf("failed initializing upload in IoT Hub\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// The SAS URI obtained above (azureBlobSasUri) can be used with other tools
|
||||
// like az_copy or Azure Storage SDK instead of the API functions
|
||||
// built-in this SDK shown below.
|
||||
|
||||
IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle = IoTHubDeviceClient_LL_AzureStorageCreateClient(device_ll_handle, azureBlobSasUri);
|
||||
|
||||
if (azureStorageClientHandle == NULL)
|
||||
{
|
||||
(void)printf("failed to create upload context\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
bool uploadSuccessful = true;
|
||||
int uploadResultCode = 200;
|
||||
int attemptCount;
|
||||
|
||||
for (uint32_t block_number = 0; block_number < 10 && uploadSuccessful; block_number++)
|
||||
{
|
||||
int data_size = snprintf(data_to_upload, sizeof(data_to_upload), data_to_upload_format, block_number);
|
||||
|
||||
attemptCount = 1;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (IoTHubDeviceClient_LL_AzureStoragePutBlock(
|
||||
azureStorageClientHandle, block_number, (const uint8_t*)data_to_upload, data_size) == IOTHUB_CLIENT_OK)
|
||||
{
|
||||
// Block upload succeeded. Continuing with next block.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (attemptCount >= SAMPLE_MAX_RETRY_COUNT)
|
||||
{
|
||||
(void)printf("Failed uploading block number %u to blob (exhausted all retries).\n", block_number);
|
||||
uploadSuccessful = false;
|
||||
uploadResultCode = 300;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)printf("Failed uploading block number %u. Retrying in %u seconds...\n", block_number, SAMPLE_RETRY_DELAY_MILLISECS / 1000);
|
||||
ThreadAPI_Sleep(SAMPLE_RETRY_DELAY_MILLISECS);
|
||||
}
|
||||
}
|
||||
|
||||
attemptCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (uploadSuccessful)
|
||||
{
|
||||
// This function can also be retried if any errors occur.
|
||||
if (IoTHubDeviceClient_LL_AzureStoragePutBlockList(azureStorageClientHandle) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
(void)printf("Failed performing Azure Storage Put Blob List.\n");
|
||||
uploadSuccessful = false;
|
||||
uploadResultCode = 400;
|
||||
}
|
||||
}
|
||||
|
||||
IoTHubDeviceClient_LL_AzureStorageDestroyClient(azureStorageClientHandle);
|
||||
|
||||
attemptCount = 1;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion(
|
||||
device_ll_handle, uploadCorrelationId, uploadSuccessful, uploadResultCode, uploadSuccessful ? "OK" : "Aborted")
|
||||
== IOTHUB_CLIENT_OK)
|
||||
{
|
||||
// Notification succeeded.
|
||||
if (uploadSuccessful)
|
||||
{
|
||||
(void)printf("hello world blob has been created\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (attemptCount >= SAMPLE_MAX_RETRY_COUNT)
|
||||
{
|
||||
(void)printf("Failed notifying Azure IoT Hub of upload completion (exhausted all retries).\n");
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)printf("Failed notifying Azure IoT Hub of upload completion. Retrying in %u seconds...\n", SAMPLE_RETRY_DELAY_MILLISECS / 1000);
|
||||
ThreadAPI_Sleep(SAMPLE_RETRY_DELAY_MILLISECS);
|
||||
}
|
||||
}
|
||||
|
||||
attemptCount++;
|
||||
}
|
||||
}
|
||||
|
||||
free(uploadCorrelationId);
|
||||
free(azureBlobSasUri);
|
||||
}
|
||||
}
|
||||
// Clean up the iothub sdk handle
|
||||
IoTHubDeviceClient_LL_Destroy(device_ll_handle);
|
||||
}
|
||||
// Free all the sdk subsystem
|
||||
IoTHub_Deinit();
|
||||
|
||||
printf("Press any key to continue");
|
||||
(void)getchar();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#Copyright (c) Microsoft. All rights reserved.
|
||||
#Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
cmake_policy(SET CMP0074 NEW)
|
||||
cmake_policy(SET CMP0012 NEW)
|
||||
|
||||
project(iothub_client_sample_upload_to_blob_with_retry)
|
||||
|
||||
if(WIN32)
|
||||
message(FATAL_ERROR "This CMake file only supports Linux builds!")
|
||||
endif()
|
||||
|
||||
find_package(azure_iot_sdks REQUIRED)
|
||||
|
||||
add_definitions(-DSET_TRUSTED_CERT_IN_SAMPLES)
|
||||
include_directories("../../../../certs")
|
||||
|
||||
set(iothub_client_sample_upload_to_blob_with_retry_c_files
|
||||
../iothub_client_sample_upload_to_blob_with_retry.c
|
||||
../../../../certs/certs.c
|
||||
)
|
||||
|
||||
add_executable(iothub_client_sample_upload_to_blob_with_retry ${iothub_client_sample_upload_to_blob_with_retry_c_files})
|
||||
|
||||
target_link_libraries(iothub_client_sample_upload_to_blob_with_retry
|
||||
iothub_client
|
||||
)
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.23107.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iothub_client_sample_upload_to_blob", "iothub_client_sample_upload_to_blob.vcxproj", "{8BE6464E-75F3-4748-B33D-85598A74B18B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{8BE6464E-75F3-4748-B33D-85598A74B18B}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8BE6464E-75F3-4748-B33D-85598A74B18B}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8BE6464E-75F3-4748-B33D-85598A74B18B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8BE6464E-75F3-4748-B33D-85598A74B18B}.Debug|x64.Build.0 = Debug|x64
|
||||
{8BE6464E-75F3-4748-B33D-85598A74B18B}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{8BE6464E-75F3-4748-B33D-85598A74B18B}.Release|Win32.Build.0 = Release|Win32
|
||||
{8BE6464E-75F3-4748-B33D-85598A74B18B}.Release|x64.ActiveCfg = Release|x64
|
||||
{8BE6464E-75F3-4748-B33D-85598A74B18B}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,172 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{8BE6464E-75F3-4748-B33D-85598A74B18B}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>iothub_client_sample_upload_to_blob</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<IncludePath>..\..\..\..\certs;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>..\..\..\..\certs;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<IncludePath>..\..\..\..\certs;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<IncludePath>..\..\..\..\certs;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>GB_MEASURE_MEMORY_FOR_THIS;GB_DEBUG_ALLOC;WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\;$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\azureiot;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>rpcrt4.lib;ncrypt.lib;crypt32.lib;winhttp.lib;secur32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>GB_MEASURE_MEMORY_FOR_THIS;GB_DEBUG_ALLOC;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\;$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\azureiot;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>rpcrt4.lib;ncrypt.lib;crypt32.lib;winhttp.lib;secur32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\;$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\azureiot;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>rpcrt4.lib;ncrypt.lib;crypt32.lib;winhttp.lib;secur32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\;$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\azureiot;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>rpcrt4.lib;ncrypt.lib;crypt32.lib;winhttp.lib;secur32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\..\certs\certs.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\..\certs\certs.c" />
|
||||
<ClCompile Include="..\iothub_client_sample_upload_to_blob.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Target Name="EnsureVcPkgPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references Vcpkg package(s) that are missing on this computer. For more information, see https://github.com/Azure/azure-iot-sdk-c/tree/main/doc/setting_up_vcpkg.md. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\azureiot\iothub.h')" Text="$([System.String]::Format('$(ErrorText)', '$(VcpkgRoot)\installed\$(VcpkgTriplet)\include\azureiot\iothub.h'))" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -6,39 +6,149 @@
|
|||
|
||||
#include "azure_c_shared_utility/gballoc.h"
|
||||
#include "internal/blob.h"
|
||||
#include "internal/iothub_client_ll_uploadtoblob.h"
|
||||
|
||||
#include "azure_c_shared_utility/httpapiex.h"
|
||||
#include "azure_c_shared_utility/xlogging.h"
|
||||
#include "azure_c_shared_utility/azure_base64.h"
|
||||
#include "azure_c_shared_utility/shared_util_options.h"
|
||||
|
||||
#define HTTP_STATUS_CODE_OK 200
|
||||
#define IS_HTTP_STATUS_CODE_SUCCESS(x) ((x) >= 100 && (x) < 300)
|
||||
|
||||
static const char blockListXmlBegin[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<BlockList>";
|
||||
static const char blockListXmlEnd[] = "</BlockList>";
|
||||
static const char blockListUriMarker[] = "&comp=blocklist";
|
||||
static const char blockListLatestTagXmlBegin[] = "<Latest>";
|
||||
static const char blockListLatestTagXmlEnd[] = "</Latest>";
|
||||
|
||||
BLOB_RESULT Blob_UploadBlock(
|
||||
// Size of the string containing an Azure Blob Block ID.
|
||||
// For more details please see
|
||||
// https://learn.microsoft.com/en-us/rest/api/storageservices/put-block?tabs=azure-ad#uri-parameters
|
||||
#define AZURE_BLOB_BLOCK_ID_SIZE 7
|
||||
|
||||
// Length of the string representation of an Azure Blob Block ID (enough to represent "049999").
|
||||
#define AZURE_BLOB_BLOCK_ID_LENGTH 6
|
||||
|
||||
#define IS_HTTP_STATUS_CODE_SUCCESS(x) ((x) >= 100 && (x) < 300)
|
||||
|
||||
|
||||
static STRING_HANDLE createBlockIdListXml(SINGLYLINKEDLIST_HANDLE blockIDList)
|
||||
{
|
||||
STRING_HANDLE blockIdListXml;
|
||||
|
||||
if ((blockIdListXml = STRING_construct(blockListXmlBegin)) == NULL)
|
||||
{
|
||||
LogError("failed opening Block ID List XML");
|
||||
}
|
||||
else
|
||||
{
|
||||
LIST_ITEM_HANDLE listNode = singlylinkedlist_get_head_item(blockIDList);
|
||||
|
||||
while (listNode != NULL)
|
||||
{
|
||||
STRING_HANDLE blockIdEncodedString = (STRING_HANDLE)singlylinkedlist_item_get_value(listNode);
|
||||
|
||||
if (!(
|
||||
(STRING_concat(blockIdListXml, blockListLatestTagXmlBegin) == 0) &&
|
||||
(STRING_concat_with_STRING(blockIdListXml, blockIdEncodedString) == 0) &&
|
||||
(STRING_concat(blockIdListXml, blockListLatestTagXmlEnd) == 0)
|
||||
))
|
||||
{
|
||||
LogError("failed to concatenate Block ID to XML");
|
||||
STRING_delete(blockIdListXml);
|
||||
blockIdListXml = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
listNode = singlylinkedlist_get_next_item(listNode);
|
||||
}
|
||||
|
||||
if (blockIdListXml != NULL &&
|
||||
STRING_concat(blockIdListXml, blockListXmlEnd) != 0)
|
||||
{
|
||||
LogError("failed closing Block ID List XML");
|
||||
STRING_delete(blockIdListXml);
|
||||
blockIdListXml = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return blockIdListXml;
|
||||
}
|
||||
|
||||
static bool removeAndDestroyBlockIdInList(const void* item, const void* match_context, bool* continue_processing)
|
||||
{
|
||||
(void)match_context;
|
||||
STRING_HANDLE blockId = (STRING_HANDLE)item;
|
||||
STRING_delete(blockId);
|
||||
*continue_processing = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
HTTPAPIEX_HANDLE Blob_CreateHttpConnection(const char* blobStorageHostname, const char* certificates, const HTTP_PROXY_OPTIONS *proxyOptions, const char* networkInterface, const size_t timeoutInMilliseconds)
|
||||
{
|
||||
HTTPAPIEX_HANDLE httpApiExHandle;
|
||||
|
||||
if (blobStorageHostname == NULL)
|
||||
{
|
||||
LogError("Required storage hostname is NULL, blobStorageHostname=%p", blobStorageHostname);
|
||||
httpApiExHandle = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((httpApiExHandle = HTTPAPIEX_Create(blobStorageHostname)) == NULL)
|
||||
{
|
||||
LogError("unable to create a HTTPAPIEX_HANDLE");
|
||||
}
|
||||
else if ((timeoutInMilliseconds != 0) && (HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_TIMEOUT, &timeoutInMilliseconds) == HTTPAPIEX_ERROR))
|
||||
{
|
||||
LogError("unable to set blob transfer timeout");
|
||||
HTTPAPIEX_Destroy(httpApiExHandle);
|
||||
httpApiExHandle = NULL;
|
||||
}
|
||||
else if ((certificates != NULL) && (HTTPAPIEX_SetOption(httpApiExHandle, OPTION_TRUSTED_CERT, certificates) == HTTPAPIEX_ERROR))
|
||||
{
|
||||
LogError("failure in setting trusted certificates");
|
||||
HTTPAPIEX_Destroy(httpApiExHandle);
|
||||
httpApiExHandle = NULL;
|
||||
}
|
||||
else if ((proxyOptions != NULL && proxyOptions->host_address != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_PROXY, proxyOptions) == HTTPAPIEX_ERROR)
|
||||
{
|
||||
LogError("failure in setting proxy options");
|
||||
HTTPAPIEX_Destroy(httpApiExHandle);
|
||||
httpApiExHandle = NULL;
|
||||
}
|
||||
else if ((networkInterface != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_CURL_INTERFACE, networkInterface) == HTTPAPIEX_ERROR)
|
||||
{
|
||||
LogError("failure in setting network interface");
|
||||
HTTPAPIEX_Destroy(httpApiExHandle);
|
||||
httpApiExHandle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return httpApiExHandle;
|
||||
}
|
||||
|
||||
void Blob_DestroyHttpConnection(HTTPAPIEX_HANDLE httpApiExHandle)
|
||||
{
|
||||
if (httpApiExHandle != NULL)
|
||||
{
|
||||
HTTPAPIEX_Destroy(httpApiExHandle);
|
||||
}
|
||||
}
|
||||
|
||||
BLOB_RESULT Blob_PutBlock(
|
||||
HTTPAPIEX_HANDLE httpApiExHandle,
|
||||
const char* relativePath,
|
||||
BUFFER_HANDLE requestContent,
|
||||
unsigned int blockID,
|
||||
STRING_HANDLE blockIDList,
|
||||
BUFFER_HANDLE blockData,
|
||||
SINGLYLINKEDLIST_HANDLE blockIDList,
|
||||
unsigned int* httpStatus,
|
||||
BUFFER_HANDLE httpResponse)
|
||||
{
|
||||
BLOB_RESULT result;
|
||||
|
||||
if (requestContent == NULL ||
|
||||
blockIDList == NULL ||
|
||||
if (httpApiExHandle == NULL ||
|
||||
relativePath == NULL ||
|
||||
httpApiExHandle == NULL ||
|
||||
httpStatus == NULL ||
|
||||
httpResponse == NULL)
|
||||
blockData == NULL ||
|
||||
blockIDList == NULL)
|
||||
{
|
||||
LogError("invalid argument detected requestContent=%p blockIDList=%p relativePath=%p httpApiExHandle=%p httpStatus=%p httpResponse=%p", requestContent, blockIDList, relativePath, httpApiExHandle, httpStatus, httpResponse);
|
||||
LogError("invalid argument detected blockData=%p blockIDList=%p relativePath=%p httpApiExHandle=%p", blockData, blockIDList, relativePath, httpApiExHandle);
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else if (blockID > 49999) /*outside the expected range of 000000... 049999*/
|
||||
|
@ -47,329 +157,206 @@ BLOB_RESULT Blob_UploadBlock(
|
|||
result = BLOB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
char temp[7]; /*this will contain 000000... 049999*/
|
||||
if (sprintf(temp, "%6u", (unsigned int)blockID) != 6) /*produces 000000... 049999*/
|
||||
{
|
||||
char blockIdString[AZURE_BLOB_BLOCK_ID_SIZE]; /*this will contain 000000... 049999*/
|
||||
if (sprintf(blockIdString, "%6u", (unsigned int)blockID) != AZURE_BLOB_BLOCK_ID_LENGTH) /*produces 000000... 049999*/
|
||||
{
|
||||
LogError("failed to sprintf");
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
STRING_HANDLE blockIdString = Azure_Base64_Encode_Bytes((const unsigned char*)temp, 6);
|
||||
if (blockIdString == NULL)
|
||||
STRING_HANDLE blockIdEncodedString = Azure_Base64_Encode_Bytes((const unsigned char*)blockIdString, AZURE_BLOB_BLOCK_ID_LENGTH);
|
||||
|
||||
if (blockIdEncodedString == NULL)
|
||||
{
|
||||
LogError("unable to Azure_Base64_Encode_Bytes");
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
LIST_ITEM_HANDLE newListItem = singlylinkedlist_add(blockIDList, blockIdEncodedString);
|
||||
|
||||
/*add the blockId base64 encoded to the XML*/
|
||||
if (!(
|
||||
(STRING_concat(blockIDList, "<Latest>") == 0) &&
|
||||
(STRING_concat_with_STRING(blockIDList, blockIdString) == 0) &&
|
||||
(STRING_concat(blockIDList, "</Latest>") == 0)
|
||||
))
|
||||
if (newListItem == NULL)
|
||||
{
|
||||
LogError("unable to STRING_concat");
|
||||
LogError("unable to store block ID");
|
||||
STRING_delete(blockIdEncodedString);
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
STRING_HANDLE newRelativePath = STRING_construct(relativePath);
|
||||
|
||||
if (newRelativePath == NULL)
|
||||
{
|
||||
LogError("unable to STRING_construct");
|
||||
(void)singlylinkedlist_remove(blockIDList, newListItem);
|
||||
STRING_delete(blockIdEncodedString);
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(
|
||||
(STRING_concat(newRelativePath, "&comp=block&blockid=") == 0) &&
|
||||
(STRING_concat_with_STRING(newRelativePath, blockIdString) == 0)
|
||||
(STRING_concat_with_STRING(newRelativePath, blockIdEncodedString) == 0)
|
||||
))
|
||||
{
|
||||
LogError("unable to STRING concatenate");
|
||||
(void)singlylinkedlist_remove(blockIDList, newListItem);
|
||||
STRING_delete(blockIdEncodedString);
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int httpResponseStatusCode = 0;
|
||||
|
||||
if (HTTPAPIEX_ExecuteRequest(
|
||||
httpApiExHandle,
|
||||
HTTPAPI_REQUEST_PUT,
|
||||
STRING_c_str(newRelativePath),
|
||||
NULL,
|
||||
requestContent,
|
||||
httpStatus,
|
||||
NULL,
|
||||
httpResponse) != HTTPAPIEX_OK
|
||||
)
|
||||
httpApiExHandle,
|
||||
HTTPAPI_REQUEST_PUT,
|
||||
STRING_c_str(newRelativePath),
|
||||
NULL,
|
||||
blockData,
|
||||
&httpResponseStatusCode,
|
||||
NULL,
|
||||
httpResponse) != HTTPAPIEX_OK ||
|
||||
!IS_HTTP_STATUS_CODE_SUCCESS(httpResponseStatusCode))
|
||||
{
|
||||
LogError("unable to HTTPAPIEX_ExecuteRequest");
|
||||
LogError("unable to HTTPAPIEX_ExecuteRequest (HTTP response status %u)", httpResponseStatusCode);
|
||||
(void)singlylinkedlist_remove(blockIDList, newListItem);
|
||||
STRING_delete(blockIdEncodedString);
|
||||
result = BLOB_HTTP_ERROR;
|
||||
}
|
||||
else if (!IS_HTTP_STATUS_CODE_SUCCESS(*httpStatus))
|
||||
{
|
||||
LogError("HTTP status from storage does not indicate success (%d)", (int)*httpStatus);
|
||||
result = BLOB_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = BLOB_OK;
|
||||
}
|
||||
|
||||
if (httpStatus != NULL)
|
||||
{
|
||||
*httpStatus = httpResponseStatusCode;
|
||||
}
|
||||
}
|
||||
|
||||
STRING_delete(newRelativePath);
|
||||
}
|
||||
}
|
||||
STRING_delete(blockIdString);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// InvokeUserCallbackAndSendBlobs invokes the application's getDataCallbackEx as many time as callback requests and, for each call,
|
||||
// sends the blob contents to the server.
|
||||
static BLOB_RESULT InvokeUserCallbackAndSendBlobs(HTTPAPIEX_HANDLE httpApiExHandle, const char* relativePath, STRING_HANDLE blockIDList, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context, unsigned int* httpStatus, BUFFER_HANDLE httpResponse)
|
||||
void Blob_ClearBlockIdList(SINGLYLINKEDLIST_HANDLE blockIdList)
|
||||
{
|
||||
BLOB_RESULT result;
|
||||
|
||||
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 = NULL; /* data set by getDataCallbackEx */
|
||||
size_t size = 0; /* source size set by getDataCallbackEx */
|
||||
IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataReturnValue;
|
||||
|
||||
do
|
||||
if (blockIdList != NULL)
|
||||
{
|
||||
getDataReturnValue = getDataCallbackEx(FILE_UPLOAD_OK, &source, &size, context);
|
||||
if (getDataReturnValue == IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT)
|
||||
if (singlylinkedlist_remove_if(blockIdList, removeAndDestroyBlockIdInList, NULL) != 0)
|
||||
{
|
||||
LogInfo("Upload to blob has been aborted by the user");
|
||||
uploadOneMoreBlock = 0;
|
||||
result = BLOB_ABORTED;
|
||||
}
|
||||
else if (source == NULL || size == 0)
|
||||
{
|
||||
uploadOneMoreBlock = 0;
|
||||
result = BLOB_OK;
|
||||
*httpStatus = HTTP_STATUS_CODE_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size > BLOCK_SIZE)
|
||||
{
|
||||
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)
|
||||
{
|
||||
LogError("unable to upload more than %lu blocks in one blob", (unsigned long)MAX_BLOCK_COUNT);
|
||||
result = BLOB_INVALID_ARG;
|
||||
isError = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
BUFFER_HANDLE requestContent = BUFFER_create(source, size);
|
||||
if (requestContent == NULL)
|
||||
{
|
||||
LogError("unable to BUFFER_create");
|
||||
result = BLOB_ERROR;
|
||||
isError = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = Blob_UploadBlock(
|
||||
httpApiExHandle,
|
||||
relativePath,
|
||||
requestContent,
|
||||
blockID,
|
||||
blockIDList,
|
||||
httpStatus,
|
||||
httpResponse);
|
||||
|
||||
BUFFER_delete(requestContent);
|
||||
}
|
||||
|
||||
if (result != BLOB_OK)
|
||||
{
|
||||
LogError("unable to Blob_UploadBlock. Returned value=%d", result);
|
||||
isError = 1;
|
||||
}
|
||||
else if (!IS_HTTP_STATUS_CODE_SUCCESS(*httpStatus))
|
||||
{
|
||||
LogError("unable to Blob_UploadBlock. Returned httpStatus=%u", (unsigned int)*httpStatus);
|
||||
isError = 1;
|
||||
}
|
||||
}
|
||||
blockID++;
|
||||
LogError("Failed clearing block ID list");
|
||||
}
|
||||
}
|
||||
while(uploadOneMoreBlock && !isError);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// SendBlockIdList to send an XML of uploaded blockIds to the server after the application's payload block(s) have been transferred.
|
||||
static BLOB_RESULT SendBlockIdList(HTTPAPIEX_HANDLE httpApiExHandle, const char* relativePath, STRING_HANDLE blockIDList, unsigned int* httpStatus, BUFFER_HANDLE httpResponse)
|
||||
// Blob_PutBlockList to send an XML of uploaded blockIds to the server after the application's payload block(s) have been transferred.
|
||||
BLOB_RESULT Blob_PutBlockList(
|
||||
HTTPAPIEX_HANDLE httpApiExHandle,
|
||||
const char* relativePath,
|
||||
SINGLYLINKEDLIST_HANDLE blockIDList,
|
||||
unsigned int* httpStatus,
|
||||
BUFFER_HANDLE httpResponse)
|
||||
{
|
||||
BLOB_RESULT result;
|
||||
|
||||
/*complete the XML*/
|
||||
if (STRING_concat(blockIDList, blockListXmlEnd) != 0)
|
||||
|
||||
if (httpApiExHandle == NULL || relativePath == NULL || blockIDList == NULL || httpStatus == NULL)
|
||||
{
|
||||
LogError("failed to STRING_concat");
|
||||
LogError("Invalid argument (httpApiExHandle=%p, relativePath=%p, blockIDList=%p, httpStatus=%p)",
|
||||
httpApiExHandle, relativePath, blockIDList, httpStatus);
|
||||
result = BLOB_INVALID_ARG;
|
||||
}
|
||||
else if (singlylinkedlist_get_head_item(blockIDList) == NULL)
|
||||
{
|
||||
// Block ID List is empty, there is nothing to be be sent to Azure Blob Storage.
|
||||
// In this case we better return error, forcing the caller to call this function only
|
||||
// if at least one call to Blob_PutBlock() succeeds.
|
||||
LogError("Block ID list is empty");
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
STRING_HANDLE newRelativePath = STRING_construct(relativePath);
|
||||
if (newRelativePath == NULL)
|
||||
STRING_HANDLE blockIdListXml = createBlockIdListXml(blockIDList);
|
||||
|
||||
/*complete the XML*/
|
||||
if (blockIdListXml == NULL)
|
||||
{
|
||||
LogError("failed to STRING_construct");
|
||||
LogError("failed creating Block ID list XML");
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (STRING_concat(newRelativePath, blockListUriMarker) != 0)
|
||||
STRING_HANDLE newRelativePath = STRING_construct(relativePath);
|
||||
|
||||
if (newRelativePath == NULL)
|
||||
{
|
||||
LogError("failed to STRING_concat");
|
||||
LogError("failed to STRING_construct");
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* s = STRING_c_str(blockIDList);
|
||||
BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s));
|
||||
if (blockIDListAsBuffer == NULL)
|
||||
if (STRING_concat(newRelativePath, blockListUriMarker) != 0)
|
||||
{
|
||||
LogError("failed to BUFFER_create");
|
||||
LogError("failed to STRING_concat");
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HTTPAPIEX_ExecuteRequest(
|
||||
httpApiExHandle,
|
||||
HTTPAPI_REQUEST_PUT,
|
||||
STRING_c_str(newRelativePath),
|
||||
NULL,
|
||||
blockIDListAsBuffer,
|
||||
httpStatus,
|
||||
NULL,
|
||||
httpResponse
|
||||
) != HTTPAPIEX_OK)
|
||||
const char* blockIdListXmlCharPtr = STRING_c_str(blockIdListXml);
|
||||
size_t blockIdListXmlLength = STRING_length(blockIdListXml);
|
||||
BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)blockIdListXmlCharPtr, blockIdListXmlLength);
|
||||
|
||||
if (blockIDListAsBuffer == NULL)
|
||||
{
|
||||
LogError("unable to HTTPAPIEX_ExecuteRequest");
|
||||
result = BLOB_HTTP_ERROR;
|
||||
LogError("failed to BUFFER_create");
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = BLOB_OK;
|
||||
unsigned int httpResponseStatusCode = 0;
|
||||
|
||||
if (HTTPAPIEX_ExecuteRequest(
|
||||
httpApiExHandle,
|
||||
HTTPAPI_REQUEST_PUT,
|
||||
STRING_c_str(newRelativePath),
|
||||
NULL,
|
||||
blockIDListAsBuffer,
|
||||
&httpResponseStatusCode,
|
||||
NULL,
|
||||
httpResponse) != HTTPAPIEX_OK ||
|
||||
!IS_HTTP_STATUS_CODE_SUCCESS(httpResponseStatusCode))
|
||||
{
|
||||
LogError("unable to HTTPAPIEX_ExecuteRequest (HTTP response status %u)", httpResponseStatusCode);
|
||||
result = BLOB_HTTP_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)singlylinkedlist_remove_if(blockIDList, removeAndDestroyBlockIdInList, NULL);
|
||||
result = BLOB_OK;
|
||||
}
|
||||
|
||||
if (httpStatus != NULL)
|
||||
{
|
||||
*httpStatus = httpResponseStatusCode;
|
||||
}
|
||||
|
||||
BUFFER_delete(blockIDListAsBuffer);
|
||||
}
|
||||
BUFFER_delete(blockIDListAsBuffer);
|
||||
}
|
||||
STRING_delete(newRelativePath);
|
||||
}
|
||||
STRING_delete(newRelativePath);
|
||||
|
||||
STRING_delete(blockIdListXml);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
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, const char* networkInterface, const size_t timeoutInMilliseconds)
|
||||
{
|
||||
BLOB_RESULT result;
|
||||
const char* hostnameBegin;
|
||||
STRING_HANDLE blockIDList = NULL;
|
||||
HTTPAPIEX_HANDLE httpApiExHandle = NULL;
|
||||
char* hostname = NULL;
|
||||
|
||||
if ((SASURI == NULL) || (getDataCallbackEx == NULL))
|
||||
{
|
||||
LogError("One or more required values is NULL, SASURI=%p, getDataCallbackEx=%p", SASURI, getDataCallbackEx);
|
||||
result = BLOB_INVALID_ARG;
|
||||
}
|
||||
/*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 "://"*/
|
||||
else if ((hostnameBegin = strstr(SASURI, "://")) == NULL)
|
||||
{
|
||||
LogError("hostname cannot be determined");
|
||||
result = BLOB_INVALID_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
hostnameBegin += 3; /*have to skip 3 characters which are "://"*/
|
||||
const char* relativePath = strchr(hostnameBegin, '/');
|
||||
if (relativePath == NULL)
|
||||
{
|
||||
LogError("hostname cannot be determined");
|
||||
result = BLOB_INVALID_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t hostnameSize = relativePath - hostnameBegin;
|
||||
if ((hostname = (char*)malloc(hostnameSize + 1)) == NULL)
|
||||
{
|
||||
LogError("oom - out of memory");
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)memcpy(hostname, hostnameBegin, hostnameSize);
|
||||
hostname[hostnameSize] = '\0';
|
||||
|
||||
httpApiExHandle = HTTPAPIEX_Create(hostname);
|
||||
if (httpApiExHandle == NULL)
|
||||
{
|
||||
LogError("unable to create a HTTPAPIEX_HANDLE");
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else if ((timeoutInMilliseconds != 0) && (HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_TIMEOUT, &timeoutInMilliseconds) == HTTPAPIEX_ERROR))
|
||||
{
|
||||
LogError("unable to set blob transfer timeout");
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else if ((certificates != NULL) && (HTTPAPIEX_SetOption(httpApiExHandle, OPTION_TRUSTED_CERT, 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 if ((networkInterface != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_CURL_INTERFACE, networkInterface) == HTTPAPIEX_ERROR)
|
||||
{
|
||||
LogError("failure in setting network interface");
|
||||
result = BLOB_ERROR;
|
||||
}
|
||||
else if ((blockIDList = STRING_construct(blockListXmlBegin)) == NULL)
|
||||
{
|
||||
LogError("failed to STRING_construct");
|
||||
result = BLOB_HTTP_ERROR;
|
||||
}
|
||||
else if ((result = InvokeUserCallbackAndSendBlobs(httpApiExHandle, relativePath, blockIDList, getDataCallbackEx, context, httpStatus, httpResponse)) != BLOB_OK)
|
||||
{
|
||||
LogError("Failed in invoking callback/sending blob step");
|
||||
}
|
||||
else if (IS_HTTP_STATUS_CODE_SUCCESS(*httpStatus))
|
||||
{
|
||||
// Per SRS_BLOB_02_026, it possible for us to have a result=BLOB_OK AND a non-success HTTP status code.
|
||||
// In order to maintain back-compat with existing code, we will return the BLOB_OK to the caller but NOT invoke this final step.
|
||||
result = SendBlockIdList(httpApiExHandle, relativePath, blockIDList, httpStatus, httpResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HTTPAPIEX_Destroy(httpApiExHandle);
|
||||
STRING_delete(blockIDList);
|
||||
free(hostname);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -2486,6 +2486,59 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_UploadMultipleBlocksToBlobAsync(IOTHUB_CLI
|
|||
return result;
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubClientCore_InitializeUpload(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri)
|
||||
{
|
||||
IOTHUB_CLIENT_RESULT result;
|
||||
|
||||
if (iotHubClientHandle == NULL)
|
||||
{
|
||||
LogError("invalid parameter iotHubClientHandle = %p", iotHubClientHandle);
|
||||
result = IOTHUB_CLIENT_INVALID_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = IoTHubClientCore_LL_InitializeUpload(iotHubClientHandle->IoTHubClientLLHandle, destinationFileName, uploadCorrelationId, azureBlobSasUri);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_AzureStorageCreateClient(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* azureBlobSasUri)
|
||||
{
|
||||
IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE result;
|
||||
|
||||
if (iotHubClientHandle == NULL)
|
||||
{
|
||||
LogError("invalid parameter iotHubClientHandle = %p", iotHubClientHandle);
|
||||
result = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = IoTHubClientCore_LL_AzureStorageCreateClient(iotHubClientHandle->IoTHubClientLLHandle, azureBlobSasUri);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubClientCore_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize)
|
||||
{
|
||||
return IoTHubClientCore_LL_AzureStoragePutBlock(azureStorageClientHandle, blockNumber, dataPtr, dataSize);
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubClientCore_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle)
|
||||
{
|
||||
return IoTHubClientCore_LL_AzureStoragePutBlockList(azureStorageClientHandle);
|
||||
}
|
||||
|
||||
void IoTHubClientCore_AzureStorageDestroyClient(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle)
|
||||
{
|
||||
IoTHubClientCore_LL_AzureStorageDestroyClient(azureStorageClientHandle);
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubClientCore_NotifyUploadCompletion(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage)
|
||||
{
|
||||
return IoTHubClientCore_LL_NotifyUploadCompletion(iotHubClientHandle->IoTHubClientLLHandle, uploadCorrelationId, isSuccess, responseCode, responseMessage);
|
||||
}
|
||||
#endif /*DONT_USE_UPLOADTOBLOB*/
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubClientCore_SendEventToOutputAsync(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, const char* outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
|
||||
|
|
|
@ -2706,13 +2706,68 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadToBlob(IOTHUB_CLIENT_CORE_LL_HAND
|
|||
((source == NULL) && (size >0))
|
||||
)
|
||||
{
|
||||
LogError("invalid parameters IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle=%p, const char* destinationFileName=%s, const unsigned char* source=%p, size_t size=%lu", iotHubClientHandle, destinationFileName, source, (unsigned long)size);
|
||||
LogError("invalid parameters iotHubClientHandle=%p, const char* destinationFileName=%s, const unsigned char* source=%p, size_t size=%lu",
|
||||
iotHubClientHandle, destinationFileName, source, (unsigned long)size);
|
||||
result = IOTHUB_CLIENT_INVALID_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = IoTHubClient_LL_UploadToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, source, size);
|
||||
char* uploadCorrelationId;
|
||||
char* azureBlobSasUri;
|
||||
|
||||
if (IoTHubClient_LL_UploadToBlob_InitializeUpload(
|
||||
iotHubClientHandle->uploadToBlobHandle, destinationFileName, &uploadCorrelationId, &azureBlobSasUri) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed initializing upload in IoT Hub");
|
||||
result = IOTHUB_CLIENT_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool uploadSucceeded;
|
||||
IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, azureBlobSasUri);
|
||||
|
||||
if (uploadContext == NULL)
|
||||
{
|
||||
LogError("Failed creating upload to blob context");
|
||||
uploadSucceeded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IoTHubClient_LL_UploadToBlob_PutBlock(uploadContext, 0, source, size) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed uploading block to Azure Blob Storage");
|
||||
uploadSucceeded = false;
|
||||
}
|
||||
else if (IoTHubClient_LL_UploadToBlob_PutBlockList(uploadContext) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed completing upload to blob.");
|
||||
uploadSucceeded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadSucceeded = true;
|
||||
}
|
||||
|
||||
IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext);
|
||||
}
|
||||
|
||||
// TODO (ewertons): fix the http error status below.
|
||||
if (IoTHubClient_LL_UploadToBlob_NotifyCompletion(
|
||||
iotHubClientHandle->uploadToBlobHandle, uploadCorrelationId, uploadSucceeded, 400, NULL) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed completing upload to blob.");
|
||||
result = IOTHUB_CLIENT_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (uploadSucceeded ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR);
|
||||
}
|
||||
|
||||
free(uploadCorrelationId);
|
||||
free(azureBlobSasUri);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2744,12 +2799,62 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadMultipleBlocksToBlob(IOTHUB_CLIEN
|
|||
}
|
||||
else
|
||||
{
|
||||
UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT uploadMultipleBlocksWrapperContext;
|
||||
uploadMultipleBlocksWrapperContext.getDataCallback = getDataCallback;
|
||||
uploadMultipleBlocksWrapperContext.context = context;
|
||||
char* uploadCorrelationId;
|
||||
char* azureBlobSasUri;
|
||||
|
||||
result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, uploadMultipleBlocksCallbackWrapper, &uploadMultipleBlocksWrapperContext);
|
||||
if (IoTHubClient_LL_UploadToBlob_InitializeUpload(
|
||||
iotHubClientHandle->uploadToBlobHandle, destinationFileName, &uploadCorrelationId, &azureBlobSasUri) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed initializing upload in IoT Hub");
|
||||
result = IOTHUB_CLIENT_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool uploadSucceeded;
|
||||
IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, azureBlobSasUri);
|
||||
|
||||
if (uploadContext == NULL)
|
||||
{
|
||||
LogError("Failed creating upload to blob context");
|
||||
uploadSucceeded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
UPLOAD_MULTIPLE_BLOCKS_WRAPPER_CONTEXT uploadMultipleBlocksWrapperContext;
|
||||
uploadMultipleBlocksWrapperContext.getDataCallback = getDataCallback;
|
||||
uploadMultipleBlocksWrapperContext.context = context;
|
||||
|
||||
if (IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(
|
||||
uploadContext, uploadMultipleBlocksCallbackWrapper, &uploadMultipleBlocksWrapperContext) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed to upload multiple blocks to Azure blob");
|
||||
uploadSucceeded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadSucceeded = false;
|
||||
}
|
||||
|
||||
IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext);
|
||||
}
|
||||
|
||||
// TODO (ewertons): fix the http error status below.
|
||||
if (IoTHubClient_LL_UploadToBlob_NotifyCompletion(
|
||||
iotHubClientHandle->uploadToBlobHandle, uploadCorrelationId, uploadSucceeded, 400, NULL) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed completing upload to blob.");
|
||||
result = IOTHUB_CLIENT_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (uploadSucceeded ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR);
|
||||
}
|
||||
|
||||
free(uploadCorrelationId);
|
||||
free(azureBlobSasUri);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2767,10 +2872,167 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(IOTHUB_CLI
|
|||
}
|
||||
else
|
||||
{
|
||||
result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, getDataCallbackEx, context);
|
||||
char* uploadCorrelationId = NULL;
|
||||
char* azureBlobSasUri = NULL;
|
||||
|
||||
if (IoTHubClient_LL_UploadToBlob_InitializeUpload(
|
||||
iotHubClientHandle->uploadToBlobHandle, destinationFileName, &uploadCorrelationId, &azureBlobSasUri) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed initializing upload in IoT Hub");
|
||||
result = IOTHUB_CLIENT_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool uploadSucceeded;
|
||||
IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE uploadContext = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, azureBlobSasUri);
|
||||
|
||||
if (uploadContext == NULL)
|
||||
{
|
||||
LogError("Failed creating upload to blob context");
|
||||
uploadSucceeded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(uploadContext, getDataCallbackEx, context) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed to upload multiple blocks to Azure blob");
|
||||
uploadSucceeded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uploadSucceeded = true;
|
||||
}
|
||||
|
||||
IoTHubClient_LL_UploadToBlob_DestroyContext(uploadContext);
|
||||
}
|
||||
|
||||
if (IoTHubClient_LL_UploadToBlob_NotifyCompletion(
|
||||
iotHubClientHandle->uploadToBlobHandle, uploadCorrelationId, uploadSucceeded,
|
||||
uploadSucceeded ? 200 : 400, NULL) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed completing upload to blob.");
|
||||
result = IOTHUB_CLIENT_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (uploadSucceeded ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR);
|
||||
}
|
||||
|
||||
free(uploadCorrelationId);
|
||||
free(azureBlobSasUri);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_InitializeUpload(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri)
|
||||
{
|
||||
IOTHUB_CLIENT_RESULT result;
|
||||
|
||||
if (iotHubClientHandle == NULL)
|
||||
{
|
||||
LogError("invalid parameter iotHubClientHandle=%p", iotHubClientHandle);
|
||||
result = IOTHUB_CLIENT_INVALID_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IoTHubClient_LL_UploadToBlob_InitializeUpload(
|
||||
iotHubClientHandle->uploadToBlobHandle, destinationFileName, uploadCorrelationId, azureBlobSasUri) != IOTHUB_CLIENT_OK)
|
||||
{
|
||||
LogError("Failed initializing upload in IoT Hub");
|
||||
result = IOTHUB_CLIENT_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = IOTHUB_CLIENT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubClientCore_LL_AzureStorageCreateClient(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* azureBlobSasUri)
|
||||
{
|
||||
IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE result;
|
||||
if (
|
||||
(iotHubClientHandle == NULL) ||
|
||||
(azureBlobSasUri == NULL)
|
||||
)
|
||||
{
|
||||
LogError("invalid parameters iotHubClientHandle=%p, azureBlobSasUri=%p", iotHubClientHandle, azureBlobSasUri);
|
||||
result = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = IoTHubClient_LL_UploadToBlob_CreateContext(iotHubClientHandle->uploadToBlobHandle, azureBlobSasUri);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize)
|
||||
{
|
||||
IOTHUB_CLIENT_RESULT result;
|
||||
|
||||
if (
|
||||
(azureStorageClientHandle == NULL) ||
|
||||
(dataPtr == NULL) ||
|
||||
(dataSize == 0)
|
||||
)
|
||||
{
|
||||
LogError("invalid parameters azureStorageClientHandle=%p, dataPtr=%p, dataSize=%zu", azureStorageClientHandle, dataPtr, dataSize);
|
||||
result = IOTHUB_CLIENT_INVALID_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = IoTHubClient_LL_UploadToBlob_PutBlock(azureStorageClientHandle, blockNumber, dataPtr, dataSize);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle)
|
||||
{
|
||||
IOTHUB_CLIENT_RESULT result;
|
||||
|
||||
if (azureStorageClientHandle == NULL)
|
||||
{
|
||||
LogError("invalid parameter azureStorageClientHandle=%p", azureStorageClientHandle);
|
||||
result = IOTHUB_CLIENT_INVALID_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = IoTHubClient_LL_UploadToBlob_PutBlockList(azureStorageClientHandle);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_NotifyUploadCompletion(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage)
|
||||
{
|
||||
IOTHUB_CLIENT_RESULT result;
|
||||
|
||||
if (iotHubClientHandle == NULL)
|
||||
{
|
||||
LogError("invalid parameter iotHubClientHandle=%p", iotHubClientHandle);
|
||||
result = IOTHUB_CLIENT_INVALID_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = IoTHubClient_LL_UploadToBlob_NotifyCompletion(iotHubClientHandle->uploadToBlobHandle, uploadCorrelationId, isSuccess, responseCode, responseMessage);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void IoTHubClientCore_LL_AzureStorageDestroyClient(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle)
|
||||
{
|
||||
if (azureStorageClientHandle != NULL)
|
||||
{
|
||||
IoTHubClient_LL_UploadToBlob_DestroyContext(azureStorageClientHandle);
|
||||
}
|
||||
}
|
||||
#endif // DONT_USE_UPLOADTOBLOB
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SendEventToOutputAsync(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, const char* outputName, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback)
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#ifndef DONT_USE_UPLOADTOBLOB
|
||||
#include "internal/iothub_client_ll_uploadtoblob.h"
|
||||
#endif
|
||||
#endif // DONT_USE_UPLOADTOBLOB
|
||||
|
||||
IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
|
||||
{
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -114,6 +114,37 @@ IOTHUB_CLIENT_RESULT IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync(IOTHUB_D
|
|||
{
|
||||
return IoTHubClientCore_UploadMultipleBlocksToBlobAsync((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName, NULL, getDataCallbackEx, context);
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubDeviceClient_AzureStorageInitializeBlobUpload(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri)
|
||||
{
|
||||
return IoTHubClientCore_InitializeUpload((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, destinationFileName, uploadCorrelationId, azureBlobSasUri);
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE IoTHubDeviceClient_AzureStorageCreateClient(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* azureBlobSasUri)
|
||||
{
|
||||
return IoTHubClientCore_AzureStorageCreateClient((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, azureBlobSasUri);
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubDeviceClient_AzureStoragePutBlock(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize)
|
||||
{
|
||||
return IoTHubClientCore_AzureStoragePutBlock(azureStorageClientHandle, blockNumber, dataPtr, dataSize);
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubDeviceClient_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle)
|
||||
{
|
||||
return IoTHubClientCore_AzureStoragePutBlockList(azureStorageClientHandle);
|
||||
}
|
||||
|
||||
void IoTHubDeviceClient_AzureStorageDestroyClient(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE azureStorageClientHandle)
|
||||
{
|
||||
IoTHubClientCore_AzureStorageDestroyClient(azureStorageClientHandle);
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubDeviceClient_AzureStorageNotifyBlobUploadCompletion(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage)
|
||||
{
|
||||
return IoTHubClientCore_NotifyUploadCompletion((IOTHUB_CLIENT_CORE_HANDLE)iotHubClientHandle, uploadCorrelationId, isSuccess, responseCode, responseMessage);
|
||||
}
|
||||
|
||||
#endif /*DONT_USE_UPLOADTOBLOB*/
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubDeviceClient_SendTelemetryAsync(IOTHUB_DEVICE_CLIENT_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE telemetryMessageHandle, IOTHUB_CLIENT_TELEMETRY_CALLBACK telemetryConfirmationCallback, void* userContextCallback)
|
||||
|
|
|
@ -137,6 +137,35 @@ IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob(IOTHUB_DEV
|
|||
return IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, getDataCallbackEx, context);
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_AzureStorageInitializeBlobUpload(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName, char** uploadCorrelationId, char** azureBlobSasUri)
|
||||
{
|
||||
return IoTHubClientCore_LL_InitializeUpload((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, destinationFileName, uploadCorrelationId, azureBlobSasUri);
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE IoTHubDeviceClient_LL_AzureStorageCreateClient(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* azureBlobSasUri)
|
||||
{
|
||||
return IoTHubClientCore_LL_AzureStorageCreateClient((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, azureBlobSasUri);
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_AzureStoragePutBlock(IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE azureStorageClientHandle, uint32_t blockNumber, const uint8_t* dataPtr, size_t dataSize)
|
||||
{
|
||||
return IoTHubClientCore_LL_AzureStoragePutBlock(azureStorageClientHandle, blockNumber, dataPtr, dataSize);
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_AzureStoragePutBlockList(IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE azureStorageClientHandle)
|
||||
{
|
||||
return IoTHubClientCore_LL_AzureStoragePutBlockList(azureStorageClientHandle);
|
||||
}
|
||||
|
||||
void IoTHubDeviceClient_LL_AzureStorageDestroyClient(IOTHUB_CLIENT_LL_AZURE_STORAGE_CLIENT_HANDLE azureStorageClientHandle)
|
||||
{
|
||||
IoTHubClientCore_LL_AzureStorageDestroyClient(azureStorageClientHandle);
|
||||
}
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_AzureStorageNotifyBlobUploadCompletion(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, const char* uploadCorrelationId, bool isSuccess, int responseCode, const char* responseMessage)
|
||||
{
|
||||
return IoTHubClientCore_LL_NotifyUploadCompletion((IOTHUB_CLIENT_CORE_LL_HANDLE)iotHubClientHandle, uploadCorrelationId, isSuccess, responseCode, responseMessage);
|
||||
}
|
||||
#endif
|
||||
|
||||
IOTHUB_CLIENT_RESULT IoTHubDeviceClient_LL_SendTelemetryAsync(IOTHUB_DEVICE_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE telemetryMessageHandle, IOTHUB_CLIENT_TELEMETRY_CALLBACK telemetryConfirmationCallback, void* userContextCallback)
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -501,6 +501,7 @@ TEST_FUNCTION_INITIALIZE(TestMethodInitialize)
|
|||
}
|
||||
|
||||
#ifdef TEST_MQTT
|
||||
|
||||
TEST_FUNCTION(IoTHub_MQTT_UploadMultipleBlocksToBlobEx)
|
||||
{
|
||||
e2e_uploadtoblob_multiblock_test(MQTT_Protocol, true, false, false);
|
||||
|
@ -530,4 +531,3 @@ TEST_FUNCTION(IoTHub_MQTT_UploadCloseHandle_Before_WorkersComplete)
|
|||
#endif // TEST_MQTT
|
||||
|
||||
END_TEST_SUITE(iothubclient_uploadtoblob_e2e)
|
||||
|
||||
|
|
|
@ -51,6 +51,10 @@ void* my_gballoc_realloc(void* ptr, size_t size)
|
|||
#include "internal/iothub_client_authorization.h"
|
||||
#include "internal/iothub_client_diagnostic.h"
|
||||
|
||||
#ifndef DONT_USE_UPLOADTOBLOB
|
||||
#include "internal/iothub_client_ll_uploadtoblob.h"
|
||||
#endif // DONT_USE_UPLOADTOBLOB
|
||||
|
||||
#ifdef USE_EDGE_MODULES
|
||||
#include "internal/iothub_client_edge.h"
|
||||
#include "azure_prov_client/iothub_security_factory.h"
|
||||
|
@ -226,7 +230,7 @@ static const char* TEST_STRING_VALUE = "Test string value";
|
|||
#define TEST_RETRY_TIMEOUT_SECS 60
|
||||
|
||||
#define TEST_METHOD_ID (METHOD_HANDLE)0x61
|
||||
#define TEST_IOTHUB_AUTH_HANDLE (IOTHUB_AUTHORIZATION_HANDLE)0x62
|
||||
#define TEST_IOTHUB_AUTH_HANDLE (IOTHUB_AUTHORIZATION_HANDLE)0x62
|
||||
|
||||
static const char* TEST_PROV_URI = "global.azure-devices-provisioning.net";
|
||||
|
||||
|
@ -256,6 +260,13 @@ static const char* TEST_VAR_EDGEHOSTNAME = "testEdgeHost.host";
|
|||
static const char* TEST_VAR_EDGEGATEWAYHOST = "testEdgeGatewayHost";
|
||||
static const char* TEST_VAR_MODULEID = "testModuleId";
|
||||
|
||||
#ifndef DONT_USE_UPLOADTOBLOB
|
||||
#define TEST_U2B_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)0x4243
|
||||
#define TEST_U2B_CONTEXT_HANDLE (IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE)0x4244
|
||||
static const char* const TEST_BLOB_SAS_URI = "https://mystorageaccount.blob.core.windows.net/uploadcontainer01/myDeviceId%2fsubdir%text.txt?sv=2018-03-28&sr=b&sig=BuvkhxiMqrFJDYoS4UCZq%2FMkS4rb47doCPvfdgx1iwM%3D&se=2023-07-16T05%3A31%3A08Z&sp=rw";
|
||||
static const char* const TEST_UPLOAD_CORRELATION_ID = "MjAyMzA3MTYwNTQxXzVjMzg5NzMzLTlhZTgtNDVmZC1iNjQ0LTIzZDUzMDc5YzgyMF9zdWJkaXIvaGVsbG9fd29ybGRfY3VzdG9tX21iLnR4dF92ZXIyLjA=";
|
||||
#endif // DONT_USE_UPLOADTOBLOB
|
||||
|
||||
static SINGLYLINKEDLIST_HANDLE test_singlylinkedlist_handle = (SINGLYLINKEDLIST_HANDLE)0x4243;
|
||||
static LIST_ITEM_HANDLE find_item_handle = (LIST_ITEM_HANDLE)0x4244;
|
||||
static LIST_ITEM_HANDLE add_item_handle = (LIST_ITEM_HANDLE)0x4245;
|
||||
|
@ -477,20 +488,6 @@ static void my_CONSTBUFFER_DecRef(CONSTBUFFER_HANDLE constbufferHandle)
|
|||
my_gballoc_free(constbufferHandle);
|
||||
}
|
||||
|
||||
#ifndef DONT_USE_UPLOADTOBLOB
|
||||
static IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE my_IoTHubClient_LL_UploadToBlob_Create(const IOTHUB_CLIENT_CONFIG* config, IOTHUB_AUTHORIZATION_HANDLE auth_handle)
|
||||
{
|
||||
(void)config;
|
||||
(void)auth_handle;
|
||||
return (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)my_gballoc_malloc(1);
|
||||
}
|
||||
|
||||
static void my_IoTHubClient_LL_UploadToBlob_Destroy(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle)
|
||||
{
|
||||
my_gballoc_free(handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_EDGE_MODULES
|
||||
static IOTHUB_CLIENT_EDGE_HANDLE my_IoTHubModuleClient_LL_MethodHandle_Create(const IOTHUB_CLIENT_CONFIG* config, IOTHUB_AUTHORIZATION_HANDLE authorizationHandle, const char* moduleId)
|
||||
{
|
||||
|
@ -805,6 +802,7 @@ TEST_SUITE_INITIALIZE(suite_init)
|
|||
|
||||
#ifndef DONT_USE_UPLOADTOBLOB
|
||||
REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE, void*);
|
||||
REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_LL_UPLOADTOBLOB_CONTEXT_HANDLE, void*);
|
||||
REGISTER_UMOCK_ALIAS_TYPE(IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, void*);
|
||||
#endif // DONT_USE_UPLOADTOBLOB
|
||||
|
||||
|
@ -858,10 +856,15 @@ TEST_SUITE_INITIALIZE(suite_init)
|
|||
REGISTER_GLOBAL_MOCK_FAIL_RETURN(FAKE_IoTHubTransport_DeviceMethod_Response, MU_FAILURE);
|
||||
|
||||
#ifndef DONT_USE_UPLOADTOBLOB
|
||||
REGISTER_GLOBAL_MOCK_HOOK(IoTHubClient_LL_UploadToBlob_Create, my_IoTHubClient_LL_UploadToBlob_Create);
|
||||
REGISTER_GLOBAL_MOCK_FAIL_RETURN(IoTHubClient_LL_UploadToBlob_Create, NULL);
|
||||
REGISTER_GLOBAL_MOCK_HOOK(IoTHubClient_LL_UploadToBlob_Destroy, my_IoTHubClient_LL_UploadToBlob_Destroy);
|
||||
REGISTER_GLOBAL_MOCK_RETURN(IoTHubClient_LL_UploadToBlob_SetOption, IOTHUB_CLIENT_OK);
|
||||
REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_Create, TEST_U2B_HANDLE, NULL);
|
||||
REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_SetOption, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR);
|
||||
REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_InitializeUpload, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR);
|
||||
REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_NotifyCompletion, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR);
|
||||
REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_CreateContext, TEST_U2B_CONTEXT_HANDLE, NULL);
|
||||
REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_PutBlock, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR);
|
||||
REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_PutBlockList, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR);
|
||||
REGISTER_GLOBAL_MOCK_RETURNS(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks, IOTHUB_CLIENT_OK, IOTHUB_CLIENT_ERROR);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_EDGE_MODULES
|
||||
|
@ -971,9 +974,6 @@ TEST_SUITE_INITIALIZE(suite_init)
|
|||
REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_find, real_singlylinkedlist_find);
|
||||
REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_foreach, real_singlylinkedlist_foreach);
|
||||
REGISTER_GLOBAL_MOCK_HOOK(singlylinkedlist_remove_if, real_singlylinkedlist_remove_if);
|
||||
|
||||
REGISTER_GLOBAL_MOCK_RETURN(IoTHubClient_LL_UploadToBlob_Impl, IOTHUB_CLIENT_OK);
|
||||
REGISTER_GLOBAL_MOCK_RETURN(IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl, IOTHUB_CLIENT_OK);
|
||||
}
|
||||
|
||||
TEST_SUITE_CLEANUP(suite_cleanup)
|
||||
|
@ -4051,17 +4051,30 @@ TEST_FUNCTION(IoTHubClientCore_LL_SetOption_messageTimeout_when_tickcounter_fail
|
|||
TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_OK)
|
||||
{
|
||||
//arrange
|
||||
char* uploadCorrelationId;
|
||||
char* azureBlobSasUri;
|
||||
(void)my_mallocAndStrcpy_s(&uploadCorrelationId, TEST_UPLOAD_CORRELATION_ID);
|
||||
(void)my_mallocAndStrcpy_s(&azureBlobSasUri, TEST_BLOB_SAS_URI);
|
||||
IOTHUB_CLIENT_CORE_LL_HANDLE h = IoTHubClientCore_LL_Create(&TEST_CONFIG);
|
||||
umock_c_reset_all_calls();
|
||||
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_Impl(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG))
|
||||
.CopyOutArgumentBuffer_uploadCorrelationId(&uploadCorrelationId, sizeof(char*))
|
||||
.CopyOutArgumentBuffer_azureBlobSasUri(&azureBlobSasUri, sizeof(char*));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlock(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlockList(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
|
||||
//act
|
||||
IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadToBlob(h, "irrelevantFileName", (const unsigned char*)"a", 1);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result);
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result);
|
||||
|
||||
///cleanup
|
||||
IoTHubClientCore_LL_Destroy(h);
|
||||
|
@ -4070,17 +4083,30 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_OK)
|
|||
TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_fails)
|
||||
{
|
||||
//arrange
|
||||
char* uploadCorrelationId;
|
||||
char* azureBlobSasUri;
|
||||
(void)my_mallocAndStrcpy_s(&uploadCorrelationId, TEST_UPLOAD_CORRELATION_ID);
|
||||
(void)my_mallocAndStrcpy_s(&azureBlobSasUri, TEST_BLOB_SAS_URI);
|
||||
IOTHUB_CLIENT_CORE_LL_HANDLE h = IoTHubClientCore_LL_Create(&TEST_CONFIG);
|
||||
umock_c_reset_all_calls();
|
||||
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_Impl(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG)).SetReturn(IOTHUB_CLIENT_ERROR);
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG))
|
||||
.CopyOutArgumentBuffer_uploadCorrelationId(&uploadCorrelationId, sizeof(char*))
|
||||
.CopyOutArgumentBuffer_azureBlobSasUri(&azureBlobSasUri, sizeof(char*));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_PutBlock(IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG))
|
||||
.SetReturn(IOTHUB_CLIENT_ERROR);
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
|
||||
//act
|
||||
IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadToBlob(h, "irrelevantFileName", (const unsigned char*)"a", 1);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_ERROR, result);
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_ERROR, result);
|
||||
|
||||
///cleanup
|
||||
IoTHubClientCore_LL_Destroy(h);
|
||||
|
@ -4090,11 +4116,13 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_fails)
|
|||
TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_with_NULL_handle_fails)
|
||||
{
|
||||
//arrange
|
||||
umock_c_reset_all_calls();
|
||||
|
||||
//act
|
||||
IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadToBlob(NULL, "irrelevantFileName", (const unsigned char*)"a", 1);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result);
|
||||
|
||||
///cleanup
|
||||
|
@ -4110,8 +4138,8 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_with_NULL_fileName_fails)
|
|||
IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadToBlob(h, NULL, (const unsigned char*)"a", 1);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result);
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result);
|
||||
|
||||
///cleanup
|
||||
IoTHubClientCore_LL_Destroy(h);
|
||||
|
@ -4127,8 +4155,8 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadToBlob_with_NULL_source_and_size_greater
|
|||
IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadToBlob(h, "someFileName.txt", NULL, 1);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result);
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result);
|
||||
|
||||
///cleanup
|
||||
IoTHubClientCore_LL_Destroy(h);
|
||||
|
@ -4143,6 +4171,7 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlob_with_NULL_handle_fa
|
|||
IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadMultipleBlocksToBlob(NULL, "irrelevantFileName", my_FileUpload_GetData_Callback, &context);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result);
|
||||
|
||||
///cleanup
|
||||
|
@ -4159,6 +4188,7 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlob_with_NULL_filename_
|
|||
IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadMultipleBlocksToBlob(h, NULL, my_FileUpload_GetData_Callback, &context);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result);
|
||||
|
||||
///cleanup
|
||||
|
@ -4176,6 +4206,7 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlob_with_NULL_callback_
|
|||
IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadMultipleBlocksToBlob(h, "irrelevantFileName", NULL, &context);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_INVALID_ARG, result);
|
||||
|
||||
///cleanup
|
||||
|
@ -4186,15 +4217,28 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx_succeeds)
|
|||
{
|
||||
//arrange
|
||||
unsigned int context = 1;
|
||||
char* uploadCorrelationId;
|
||||
char* azureBlobSasUri;
|
||||
(void)my_mallocAndStrcpy_s(&uploadCorrelationId, TEST_UPLOAD_CORRELATION_ID);
|
||||
(void)my_mallocAndStrcpy_s(&azureBlobSasUri, TEST_BLOB_SAS_URI);
|
||||
IOTHUB_CLIENT_CORE_LL_HANDLE h = IoTHubClientCore_LL_Create(&TEST_CONFIG);
|
||||
umock_c_reset_all_calls();
|
||||
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG))
|
||||
.CopyOutArgumentBuffer_uploadCorrelationId(&uploadCorrelationId, sizeof(char*))
|
||||
.CopyOutArgumentBuffer_azureBlobSasUri(&azureBlobSasUri, sizeof(char*));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
|
||||
//act
|
||||
IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(h, "irrelevantFileName", my_FileUpload_GetData_CallbackEx, &context);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_OK, result);
|
||||
|
||||
///cleanup
|
||||
|
@ -4205,15 +4249,30 @@ TEST_FUNCTION(IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx_fails)
|
|||
{
|
||||
//arrange
|
||||
unsigned int context = 1;
|
||||
char* uploadCorrelationId;
|
||||
char* azureBlobSasUri;
|
||||
(void)my_mallocAndStrcpy_s(&uploadCorrelationId, TEST_UPLOAD_CORRELATION_ID);
|
||||
(void)my_mallocAndStrcpy_s(&azureBlobSasUri, TEST_BLOB_SAS_URI);
|
||||
|
||||
IOTHUB_CLIENT_CORE_LL_HANDLE h = IoTHubClientCore_LL_Create(&TEST_CONFIG);
|
||||
umock_c_reset_all_calls();
|
||||
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG)).SetReturn(IOTHUB_CLIENT_ERROR);
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_InitializeUpload(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG))
|
||||
.CopyOutArgumentBuffer_uploadCorrelationId(&uploadCorrelationId, sizeof(char*))
|
||||
.CopyOutArgumentBuffer_azureBlobSasUri(&azureBlobSasUri, sizeof(char*));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_CreateContext(IGNORED_PTR_ARG, IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_UploadMultipleBlocks(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG))
|
||||
.SetReturn(IOTHUB_CLIENT_ERROR);
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_DestroyContext(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(IoTHubClient_LL_UploadToBlob_NotifyCompletion(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG, IGNORED_NUM_ARG, IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
STRICT_EXPECTED_CALL(gballoc_free(IGNORED_PTR_ARG));
|
||||
|
||||
//act
|
||||
IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_UploadMultipleBlocksToBlobEx(h, "irrelevantFileName", my_FileUpload_GetData_CallbackEx, &context);
|
||||
|
||||
///assert
|
||||
ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls());
|
||||
ASSERT_ARE_EQUAL(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_ERROR, result);
|
||||
|
||||
///cleanup
|
||||
|
|
Загрузка…
Ссылка в новой задаче