Skip to content

Commit c13ba93

Browse files
authored
checksums for upload path (#3625)
1 parent cb96480 commit c13ba93

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

src/aws-cpp-sdk-transfer/source/transfer/TransferManager.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
#include <aws/core/platform/FileSystem.h>
77
#include <aws/core/utils/HashingUtils.h>
88
#include <aws/core/utils/logging/LogMacros.h>
9+
#include <aws/core/utils/crypto/Hash.h>
10+
#include <aws/core/utils/crypto/CRC32.h>
11+
#include <aws/core/utils/crypto/CRC64.h>
12+
#include <aws/core/utils/crypto/Sha1.h>
13+
#include <aws/core/utils/crypto/Sha256.h>
914
#include <aws/core/utils/memory/AWSMemory.h>
1015
#include <aws/core/utils/memory/stl/AWSStreamFwd.h>
1116
#include <aws/core/utils/memory/stl/AWSStringStream.h>
@@ -399,6 +404,25 @@ namespace Aws
399404
bool isRetry = !handle->GetMultiPartId().empty();
400405
uint64_t sentBytes = 0;
401406

407+
const auto fullObjectHashCalculator = [](const std::shared_ptr<TransferHandle>& handle, bool isRetry, S3::Model::ChecksumAlgorithm algorithm) -> std::shared_ptr<Aws::Utils::Crypto::Hash> {
408+
if (handle->GetChecksum().empty() && !isRetry) {
409+
if (algorithm == S3::Model::ChecksumAlgorithm::CRC32) {
410+
return Aws::MakeShared<Aws::Utils::Crypto::CRC32>("TransferManager");
411+
}
412+
if (algorithm == S3::Model::ChecksumAlgorithm::CRC32C) {
413+
return Aws::MakeShared<Aws::Utils::Crypto::CRC32C>("TransferManager");
414+
}
415+
if (algorithm == S3::Model::ChecksumAlgorithm::SHA1) {
416+
return Aws::MakeShared<Aws::Utils::Crypto::Sha1>("TransferManager");
417+
}
418+
if (algorithm == S3::Model::ChecksumAlgorithm::SHA256) {
419+
return Aws::MakeShared<Aws::Utils::Crypto::Sha256>("TransferManager");
420+
}
421+
return Aws::MakeShared<Aws::Utils::Crypto::CRC64>("TransferManager");
422+
}
423+
return nullptr;
424+
}(handle, isRetry, m_transferConfig.checksumAlgorithm);
425+
402426
if (!isRetry) {
403427
Aws::S3::Model::CreateMultipartUploadRequest createMultipartRequest = m_transferConfig.createMultipartUploadTemplate;
404428
createMultipartRequest.SetChecksumAlgorithm(m_transferConfig.checksumAlgorithm);
@@ -466,6 +490,10 @@ namespace Aws
466490
streamToPut->seekg((partsIter->first - 1) * m_transferConfig.bufferSize);
467491
streamToPut->read(reinterpret_cast<char*>(buffer), lengthToWrite);
468492

493+
if (fullObjectHashCalculator) {
494+
fullObjectHashCalculator->Update(buffer, static_cast<size_t>(lengthToWrite));
495+
}
496+
469497
auto streamBuf = Aws::New<Aws::Utils::Stream::PreallocatedStreamBuf>(CLASS_TAG, buffer, static_cast<size_t>(lengthToWrite));
470498
auto preallocatedStreamReader = Aws::MakeShared<Aws::IOStream>(CLASS_TAG, streamBuf);
471499

@@ -525,6 +553,13 @@ namespace Aws
525553
handle->UpdateStatus(DetermineIfFailedOrCanceled(*handle));
526554
TriggerTransferStatusUpdatedCallback(handle);
527555
}
556+
else if (fullObjectHashCalculator && handle->GetChecksum().empty()) {
557+
// Finalize checksum calculation and set on handle
558+
auto hashResult = fullObjectHashCalculator->GetHash();
559+
if (hashResult.IsSuccess()) {
560+
handle->SetChecksum(Aws::Utils::HashingUtils::Base64Encode(hashResult.GetResult()));
561+
}
562+
}
528563
}
529564

530565
void TransferManager::DoSinglePartUpload(const std::shared_ptr<TransferHandle>& handle)
@@ -1560,4 +1595,4 @@ namespace Aws
15601595
}
15611596
}
15621597
}
1563-
}
1598+
}

tests/aws-cpp-sdk-transfer-tests/TransferTests.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <aws/s3/S3Client.h>
1010
#include <aws/s3/model/DeleteObjectsRequest.h>
1111
#include <aws/s3/model/AbortMultipartUploadRequest.h>
12+
#include <aws/s3/model/CompleteMultipartUploadRequest.h>
1213
#include <aws/s3/model/ListObjectsRequest.h>
1314
#include <aws/s3/model/ListMultipartUploadsRequest.h>
1415
#include <aws/s3/model/GetObjectRequest.h>
@@ -160,6 +161,21 @@ class MockS3Client : public S3Client
160161
return S3Client::ListObjectsV2(request);
161162
}
162163

164+
// Override to verify checksum is being sent
165+
Model::CompleteMultipartUploadOutcome CompleteMultipartUpload(const Model::CompleteMultipartUploadRequest& request) const override
166+
{
167+
AWS_LOGSTREAM_INFO("TransferTests", "=== CompleteMultipartUpload Request ===");
168+
AWS_LOGSTREAM_INFO("TransferTests", "Available ChecksumAlgorithm enum values:");
169+
AWS_LOGSTREAM_INFO("TransferTests", "ChecksumType: " << (int)request.GetChecksumType());
170+
AWS_LOGSTREAM_INFO("TransferTests", "ChecksumCRC32: " << request.GetChecksumCRC32());
171+
AWS_LOGSTREAM_INFO("TransferTests", "ChecksumCRC32C: " << request.GetChecksumCRC32C());
172+
AWS_LOGSTREAM_INFO("TransferTests", "ChecksumCRC64NVME: " << request.GetChecksumCRC64NVME());
173+
AWS_LOGSTREAM_INFO("TransferTests", "ChecksumSHA1: " << request.GetChecksumSHA1());
174+
AWS_LOGSTREAM_INFO("TransferTests", "ChecksumSHA256: " << request.GetChecksumSHA256());
175+
AWS_LOGSTREAM_INFO("TransferTests", "=======================================");
176+
return S3Client::CompleteMultipartUpload(request);
177+
}
178+
163179
// m_executor in Base class is private, we need our own one.
164180
std::shared_ptr<Aws::Utils::Threading::Executor> executor;
165181

0 commit comments

Comments
 (0)