diff --git a/src/aws-cpp-sdk-transfer/source/transfer/TransferManager.cpp b/src/aws-cpp-sdk-transfer/source/transfer/TransferManager.cpp index 556a77b683a..e73bf0951fd 100644 --- a/src/aws-cpp-sdk-transfer/source/transfer/TransferManager.cpp +++ b/src/aws-cpp-sdk-transfer/source/transfer/TransferManager.cpp @@ -6,6 +6,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include @@ -399,6 +404,25 @@ namespace Aws bool isRetry = !handle->GetMultiPartId().empty(); uint64_t sentBytes = 0; + const auto fullObjectHashCalculator = [](const std::shared_ptr& handle, bool isRetry, S3::Model::ChecksumAlgorithm algorithm) -> std::shared_ptr { + if (handle->GetChecksum().empty() && !isRetry) { + if (algorithm == S3::Model::ChecksumAlgorithm::CRC32) { + return Aws::MakeShared("TransferManager"); + } + if (algorithm == S3::Model::ChecksumAlgorithm::CRC32C) { + return Aws::MakeShared("TransferManager"); + } + if (algorithm == S3::Model::ChecksumAlgorithm::SHA1) { + return Aws::MakeShared("TransferManager"); + } + if (algorithm == S3::Model::ChecksumAlgorithm::SHA256) { + return Aws::MakeShared("TransferManager"); + } + return Aws::MakeShared("TransferManager"); + } + return nullptr; + }(handle, isRetry, m_transferConfig.checksumAlgorithm); + if (!isRetry) { Aws::S3::Model::CreateMultipartUploadRequest createMultipartRequest = m_transferConfig.createMultipartUploadTemplate; createMultipartRequest.SetChecksumAlgorithm(m_transferConfig.checksumAlgorithm); @@ -466,6 +490,10 @@ namespace Aws streamToPut->seekg((partsIter->first - 1) * m_transferConfig.bufferSize); streamToPut->read(reinterpret_cast(buffer), lengthToWrite); + if (fullObjectHashCalculator) { + fullObjectHashCalculator->Update(buffer, static_cast(lengthToWrite)); + } + auto streamBuf = Aws::New(CLASS_TAG, buffer, static_cast(lengthToWrite)); auto preallocatedStreamReader = Aws::MakeShared(CLASS_TAG, streamBuf); @@ -525,6 +553,13 @@ namespace Aws handle->UpdateStatus(DetermineIfFailedOrCanceled(*handle)); TriggerTransferStatusUpdatedCallback(handle); } + else if (fullObjectHashCalculator && handle->GetChecksum().empty()) { + // Finalize checksum calculation and set on handle + auto hashResult = fullObjectHashCalculator->GetHash(); + if (hashResult.IsSuccess()) { + handle->SetChecksum(Aws::Utils::HashingUtils::Base64Encode(hashResult.GetResult())); + } + } } void TransferManager::DoSinglePartUpload(const std::shared_ptr& handle) @@ -1508,4 +1543,4 @@ namespace Aws } } } -} +} \ No newline at end of file diff --git a/tests/aws-cpp-sdk-transfer-tests/TransferTests.cpp b/tests/aws-cpp-sdk-transfer-tests/TransferTests.cpp index ab061815ca4..590ca405818 100644 --- a/tests/aws-cpp-sdk-transfer-tests/TransferTests.cpp +++ b/tests/aws-cpp-sdk-transfer-tests/TransferTests.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -160,6 +161,21 @@ class MockS3Client : public S3Client return S3Client::ListObjectsV2(request); } + // Override to verify checksum is being sent + Model::CompleteMultipartUploadOutcome CompleteMultipartUpload(const Model::CompleteMultipartUploadRequest& request) const override + { + AWS_LOGSTREAM_INFO("TransferTests", "=== CompleteMultipartUpload Request ==="); + AWS_LOGSTREAM_INFO("TransferTests", "Available ChecksumAlgorithm enum values:"); + AWS_LOGSTREAM_INFO("TransferTests", "ChecksumType: " << (int)request.GetChecksumType()); + AWS_LOGSTREAM_INFO("TransferTests", "ChecksumCRC32: " << request.GetChecksumCRC32()); + AWS_LOGSTREAM_INFO("TransferTests", "ChecksumCRC32C: " << request.GetChecksumCRC32C()); + AWS_LOGSTREAM_INFO("TransferTests", "ChecksumCRC64NVME: " << request.GetChecksumCRC64NVME()); + AWS_LOGSTREAM_INFO("TransferTests", "ChecksumSHA1: " << request.GetChecksumSHA1()); + AWS_LOGSTREAM_INFO("TransferTests", "ChecksumSHA256: " << request.GetChecksumSHA256()); + AWS_LOGSTREAM_INFO("TransferTests", "======================================="); + return S3Client::CompleteMultipartUpload(request); + } + // m_executor in Base class is private, we need our own one. std::shared_ptr executor;