Skip to content

Commit aa688ff

Browse files
committed
replacing stream wrapper with file-based checksum validation for single-part downloads
1 parent 41af26d commit aa688ff

File tree

3 files changed

+44
-98
lines changed

3 files changed

+44
-98
lines changed

src/aws-cpp-sdk-transfer/include/aws/transfer/ChecksumValidatingStreamBuf.h

Lines changed: 0 additions & 55 deletions
This file was deleted.

src/aws-cpp-sdk-transfer/include/aws/transfer/TransferHandle.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#pragma once
77

88
#include <aws/transfer/Transfer_EXPORTS.h>
9-
#include <aws/transfer/ChecksumValidatingStreamBuf.h>
109
#include <aws/core/utils/memory/stl/AWSString.h>
1110
#include <aws/core/utils/memory/stl/AWSSet.h>
1211
#include <aws/core/utils/memory/stl/AWSMap.h>

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

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -930,28 +930,7 @@ namespace Aws
930930
request.SetVersionId(handle->GetVersionId());
931931
}
932932

933-
// Wrap user's stream with checksum validator if enabled
934-
std::shared_ptr<Utils::Crypto::Hash> singlePartHash;
935-
std::shared_ptr<ChecksumValidatingStreamBuf> checksumWrapper;
936-
937-
if (m_transferConfig.validateChecksums)
938-
{
939-
singlePartHash = CreateHashForAlgorithm(m_transferConfig.checksumAlgorithm);
940-
auto userStreamFactory = handle->GetCreateDownloadStreamFunction();
941-
942-
request.SetResponseStreamFactory([userStreamFactory, singlePartHash, &checksumWrapper]() -> Aws::IOStream* {
943-
auto userStream = userStreamFactory();
944-
if (userStream && singlePartHash) {
945-
checksumWrapper = Aws::MakeShared<ChecksumValidatingStreamBuf>(CLASS_TAG, userStream->rdbuf(), singlePartHash);
946-
userStream->rdbuf(checksumWrapper.get());
947-
}
948-
return userStream;
949-
});
950-
}
951-
else
952-
{
953-
request.SetResponseStreamFactory(handle->GetCreateDownloadStreamFunction());
954-
}
933+
request.SetResponseStreamFactory(handle->GetCreateDownloadStreamFunction());
955934

956935
request.SetDataReceivedEventHandler([this, handle, partState](const Aws::Http::HttpRequest*, Aws::Http::HttpResponse*, long long progress)
957936
{
@@ -977,32 +956,55 @@ namespace Aws
977956
handle->ChangePartToCompleted(partState, getObjectOutcome.GetResult().GetETag());
978957
getObjectOutcome.GetResult().GetBody().flush();
979958

980-
// Validate checksum for single-part download
981-
if (m_transferConfig.validateChecksums && singlePartHash)
959+
// Validate checksum for single-part download by reading file
960+
if (m_transferConfig.validateChecksums)
982961
{
983962
Aws::String expectedChecksum = GetChecksumFromResult(getObjectOutcome.GetResult(), m_transferConfig.checksumAlgorithm);
984963

985-
if (!expectedChecksum.empty())
964+
if (!expectedChecksum.empty() && !handle->GetTargetFilePath().empty())
986965
{
987-
auto calculatedResult = singlePartHash->GetHash();
988-
if (calculatedResult.IsSuccess())
966+
auto hash = CreateHashForAlgorithm(m_transferConfig.checksumAlgorithm);
967+
Aws::IFStream fileStream(handle->GetTargetFilePath().c_str(), std::ios::binary);
968+
969+
if (fileStream.good())
989970
{
990-
Aws::String calculatedChecksum = Utils::HashingUtils::Base64Encode(calculatedResult.GetResult());
991-
if (calculatedChecksum != expectedChecksum)
971+
const size_t bufferSize = 8192;
972+
char buffer[bufferSize];
973+
while (fileStream.good())
992974
{
993-
AWS_LOGSTREAM_ERROR(CLASS_TAG, "Transfer handle [" << handle->GetId()
994-
<< "] Checksum mismatch for single-part download. Expected: "
995-
<< expectedChecksum << ", Calculated: " << calculatedChecksum);
996-
handle->ChangePartToFailed(partState);
997-
handle->UpdateStatus(TransferStatus::FAILED);
998-
Aws::Client::AWSError<Aws::S3::S3Errors> error(Aws::S3::S3Errors::INTERNAL_FAILURE,
999-
"ChecksumMismatch",
1000-
"Single-part download checksum validation failed",
1001-
false);
1002-
handle->SetError(error);
1003-
TriggerErrorCallback(handle, error);
1004-
TriggerTransferStatusUpdatedCallback(handle);
1005-
return;
975+
fileStream.read(buffer, bufferSize);
976+
std::streamsize bytesRead = fileStream.gcount();
977+
if (bytesRead > 0)
978+
{
979+
hash->Update(reinterpret_cast<unsigned char*>(buffer), static_cast<size_t>(bytesRead));
980+
}
981+
}
982+
fileStream.close();
983+
984+
auto calculatedResult = hash->GetHash();
985+
if (calculatedResult.IsSuccess())
986+
{
987+
Aws::String calculatedChecksum = Utils::HashingUtils::Base64Encode(calculatedResult.GetResult());
988+
if (calculatedChecksum != expectedChecksum)
989+
{
990+
AWS_LOGSTREAM_ERROR(CLASS_TAG, "Transfer handle [" << handle->GetId()
991+
<< "] Checksum mismatch for single-part download. Expected: "
992+
<< expectedChecksum << ", Calculated: " << calculatedChecksum);
993+
994+
// Delete the corrupted file
995+
Aws::FileSystem::RemoveFileIfExists(handle->GetTargetFilePath().c_str());
996+
997+
handle->ChangePartToFailed(partState);
998+
handle->UpdateStatus(TransferStatus::FAILED);
999+
Aws::Client::AWSError<Aws::S3::S3Errors> error(Aws::S3::S3Errors::INTERNAL_FAILURE,
1000+
"ChecksumMismatch",
1001+
"Single-part download checksum validation failed",
1002+
false);
1003+
handle->SetError(error);
1004+
TriggerErrorCallback(handle, error);
1005+
TriggerTransferStatusUpdatedCallback(handle);
1006+
return;
1007+
}
10061008
}
10071009
}
10081010
}

0 commit comments

Comments
 (0)