diff options
Diffstat (limited to 'src')
44 files changed, 540 insertions, 495 deletions
diff --git a/src/AbstractDiskWriter.cc b/src/AbstractDiskWriter.cc index d6fec83d..943e0e76 100644 --- a/src/AbstractDiskWriter.cc +++ b/src/AbstractDiskWriter.cc @@ -113,36 +113,6 @@ int32_t AbstractDiskWriter::readDataInternal(char* data, int32_t len) { return read(fd, data, len); } -#ifdef ENABLE_MESSAGE_DIGEST -string AbstractDiskWriter::messageDigest(int64_t offset, int64_t length, - const MessageDigestContext::DigestAlgo& algo) -{ - MessageDigestContext ctx(algo); - ctx.digestInit(); - - int32_t BUFSIZE = 16*1024; - char buf[BUFSIZE]; - for(int64_t i = 0; i < length/BUFSIZE; i++) { - if(BUFSIZE != readData(buf, BUFSIZE, offset)) { - throw new DlAbortEx(EX_FILE_SHA1SUM, filename.c_str(), strerror(errno)); - } - ctx.digestUpdate(buf, BUFSIZE); - offset += BUFSIZE; - } - int32_t r = length%BUFSIZE; - if(r > 0) { - if(r != readData(buf, r, offset)) { - throw new DlAbortEx(EX_FILE_SHA1SUM, filename.c_str(), strerror(errno)); - } - ctx.digestUpdate(buf, r); - } - unsigned char hashValue[20]; - ctx.digestFinal(hashValue); - - return Util::toHex(hashValue, 20); -} -#endif // ENABLE_MESSAGE_DIGEST - void AbstractDiskWriter::seek(int64_t offset) { if(offset != lseek(fd, offset, SEEK_SET)) { throw new DlAbortEx(EX_FILE_SEEK, filename.c_str(), strerror(errno)); @@ -170,6 +140,7 @@ void AbstractDiskWriter::truncate(int64_t length) ftruncate(fd, length); } +// TODO the file descriptor fd must be opened before calling this function. int64_t AbstractDiskWriter::size() const { struct stat fileStat; diff --git a/src/AbstractDiskWriter.h b/src/AbstractDiskWriter.h index 316ab3fc..f6b2d426 100644 --- a/src/AbstractDiskWriter.h +++ b/src/AbstractDiskWriter.h @@ -65,11 +65,6 @@ public: virtual void openExistingFile(const string& filename, int64_t totalLength = 0); -#ifdef ENABLE_MESSAGE_DIGEST - virtual string messageDigest(int64_t offset, int64_t length, - const MessageDigestContext::DigestAlgo& algo); -#endif // ENABLE_MESSAGE_DIGEST - virtual void writeData(const char* data, int32_t len, int64_t offset); virtual int32_t readData(char* data, int32_t len, int64_t offset); diff --git a/src/AbstractSingleDiskAdaptor.cc b/src/AbstractSingleDiskAdaptor.cc index d1e5c4f0..e0bec6ee 100644 --- a/src/AbstractSingleDiskAdaptor.cc +++ b/src/AbstractSingleDiskAdaptor.cc @@ -59,10 +59,6 @@ int32_t AbstractSingleDiskAdaptor::readData(unsigned char* data, int32_t len, in return diskWriter->readData(data, len, offset); } -string AbstractSingleDiskAdaptor::messageDigest(int64_t offset, int64_t length, const MessageDigestContext::DigestAlgo& algo) { - return diskWriter->messageDigest(offset, length, algo); -} - bool AbstractSingleDiskAdaptor::fileExists() { return File(getFilePath()).exists(); diff --git a/src/AbstractSingleDiskAdaptor.h b/src/AbstractSingleDiskAdaptor.h index 57298d02..c4dc7e80 100644 --- a/src/AbstractSingleDiskAdaptor.h +++ b/src/AbstractSingleDiskAdaptor.h @@ -60,11 +60,13 @@ public: virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset); - virtual string messageDigest(int64_t offset, int64_t length, - const MessageDigestContext::DigestAlgo& algo); - virtual bool fileExists(); + virtual int64_t size() const + { + return getTotalLength(); + } + void setDiskWriter(const DiskWriterHandle diskWriter) { this->diskWriter = diskWriter; } diff --git a/src/BtContext.h b/src/BtContext.h index 5b4e832e..69d52029 100644 --- a/src/BtContext.h +++ b/src/BtContext.h @@ -84,6 +84,9 @@ public: * Returns the peer id of localhost, 20 byte length */ virtual const unsigned char* getPeerId() = 0; + + virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize) = 0; + }; typedef SharedHandle<BtContext> BtContextHandle; diff --git a/src/BtPieceMessage.cc b/src/BtPieceMessage.cc index dc6c8b8d..d3587583 100644 --- a/src/BtPieceMessage.cc +++ b/src/BtPieceMessage.cc @@ -39,6 +39,8 @@ #include "DlAbortEx.h" #include "BtChokingEvent.h" #include "BtCancelSendingPieceEvent.h" +#include "DiskAdaptorWriter.h" +#include "MessageDigestHelper.h" void BtPieceMessage::setBlock(const unsigned char* block, int32_t blockLength) { delete [] this->block; @@ -190,8 +192,9 @@ string BtPieceMessage::toString() const { bool BtPieceMessage::checkPieceHash(const PieceHandle& piece) { int64_t offset = ((int64_t)piece->getIndex())*btContext->getPieceLength(); - return pieceStorage->getDiskAdaptor()->messageDigest(offset, piece->getLength(), DIGEST_ALGO_SHA1) == - btContext->getPieceHash(piece->getIndex()); + + return MessageDigestHelper::digest("sha1", new DiskAdaptorWriter(pieceStorage->getDiskAdaptor()), offset, piece->getLength()) + == btContext->getPieceHash(piece->getIndex()); } void BtPieceMessage::onNewPiece(const PieceHandle& piece) { diff --git a/src/ByteArrayDiskWriter.h b/src/ByteArrayDiskWriter.h index 227cac74..a3583552 100644 --- a/src/ByteArrayDiskWriter.h +++ b/src/ByteArrayDiskWriter.h @@ -66,14 +66,6 @@ public: { return buf.str().size(); } - - // not implemented yet -#ifdef ENABLE_MESSAGE_DIGEST - virtual string messageDigest(int64_t offset, int64_t length, - const MessageDigestContext::DigestAlgo& algo) { - return ""; - } -#endif // ENABLE_MESSAGE_DIGEST }; #endif // _D_BYTE_ARRAY_DISK_WRITER_H_ diff --git a/src/Checksum.h b/src/Checksum.h index eb1d5c34..54eea063 100644 --- a/src/Checksum.h +++ b/src/Checksum.h @@ -36,43 +36,39 @@ #define _D_CHECKSUM_H_ #include "common.h" -#ifdef ENABLE_MESSAGE_DIGEST -#include "messageDigest.h" class Checksum { private: - string md; - MessageDigestContext::DigestAlgo algo; + string _algo; + string _messageDigest; public: - Checksum(const string& md, MessageDigestContext::DigestAlgo algo): - md(md), - algo(algo) {} + // _messageDigest is ascii hexadecimal notation. + Checksum(const string& algo, const string& messageDigest): + _algo(algo), _messageDigest(messageDigest) {} Checksum(): - algo(DIGEST_ALGO_SHA1) {} + _algo("sha1") {} + ~Checksum() {} bool isEmpty() const { - return md.size() == 0; + return _messageDigest.size() == 0; } void setMessageDigest(const string& md) { - this->md = md; + this->_messageDigest = md; } const string& getMessageDigest() const { - return md; + return _messageDigest; } - void setDigestAlgo(MessageDigestContext::DigestAlgo algo) { - this->algo = algo; + void setAlgo(const string& algo) { + this->_algo = algo; } - const MessageDigestContext::DigestAlgo& getDigestAlgo() const { - return algo; + + const string& getAlgo() const { + return _algo; } }; -#else -class Checksum { -}; -#endif // ENABLE_MESSAGE_DIGEST typedef SharedHandle<Checksum> ChecksumHandle; diff --git a/src/ChunkChecksum.h b/src/ChunkChecksum.h index 0df27efa..9b91b351 100644 --- a/src/ChunkChecksum.h +++ b/src/ChunkChecksum.h @@ -40,11 +40,11 @@ class ChunkChecksum { private: - MessageDigestContext::DigestAlgo _algo; + string _algo; Strings _checksums; int32_t _checksumLength; public: - ChunkChecksum(const MessageDigestContext::DigestAlgo& algo, + ChunkChecksum(const string& algo, const Strings& checksums, int32_t checksumLength): _algo(algo), @@ -85,7 +85,7 @@ public: return _checksumLength; } - MessageDigestContext::DigestAlgo getAlgo() const + const string& getAlgo() const { return _algo; } diff --git a/src/ChunkChecksumValidator.cc b/src/ChunkChecksumValidator.cc index ce62c24d..9e9b65ff 100644 --- a/src/ChunkChecksumValidator.cc +++ b/src/ChunkChecksumValidator.cc @@ -33,90 +33,34 @@ */ /* copyright --> */ #include "ChunkChecksumValidator.h" -#include "Util.h" -#include "Exception.h" #include "TimeA2.h" #include "message.h" -#ifdef ENABLE_MESSAGE_DIGEST -void ChunkChecksumValidator::validateSameLengthChecksum(BitfieldMan* bitfieldMan, - int32_t index, - const string& expectedChecksum, - int32_t dataLength, - int32_t checksumLength) +void ChunkChecksumValidator::validate() { - int64_t offset = ((int64_t)index)*checksumLength; - string actualChecksum = diskWriter->messageDigest(offset, dataLength, algo); - if(actualChecksum != expectedChecksum) { - logger->info(EX_INVALID_CHUNK_CHECKSUM, - index, Util::llitos(offset, true).c_str(), - expectedChecksum.c_str(), actualChecksum.c_str()); - bitfieldMan->unsetBit(index); - } -} - -void ChunkChecksumValidator::validateDifferentLengthChecksum(BitfieldMan* bitfieldMan, - int32_t index, - const string& expectedChecksum, - int32_t dataLength, - int32_t checksumLength) -{ - int64_t offset = ((int64_t)index)*checksumLength; - int32_t startIndex; - int32_t endIndex; - Util::indexRange(startIndex, endIndex, offset, - checksumLength, bitfieldMan->getBlockLength()); - if(bitfieldMan->isBitRangeSet(startIndex, endIndex)) { - string actualChecksum = diskWriter->messageDigest(offset, dataLength, algo); - if(expectedChecksum != actualChecksum) { - // wrong checksum - logger->info(EX_INVALID_CHUNK_CHECKSUM, - index, Util::llitos(offset, true).c_str(), - expectedChecksum.c_str(), actualChecksum.c_str()); - bitfieldMan->unsetBitRange(startIndex, endIndex); - } - } -} - -void ChunkChecksumValidator::validate(BitfieldMan* bitfieldMan, - const Strings& checksums, - int32_t checksumLength) -{ - // We assume file is already opened using DiskWriter::open or openExistingFile. - if(((int64_t)checksumLength*checksums.size()) < bitfieldMan->getTotalLength()) { + if(!_validator->canValidate()) { // insufficient checksums. logger->error(MSG_INSUFFICIENT_CHECKSUM, - checksumLength, checksums.size()); + _validator->getChunkChecksum()->getChecksumLength(), + _validator->getChunkChecksum()->countChecksum()); return; } - assert(bitfieldMan->getTotalLength()/checksumLength <= INT32_MAX); - int32_t x = bitfieldMan->getTotalLength()/checksumLength; - int32_t r = bitfieldMan->getTotalLength()%checksumLength; - void (ChunkChecksumValidator::*f)(BitfieldMan*, int32_t, const string&, int32_t, int32_t); - - if(checksumLength == bitfieldMan->getBlockLength()) { - f = &ChunkChecksumValidator::validateSameLengthChecksum; - } else { - f = &ChunkChecksumValidator::validateDifferentLengthChecksum; - } + _validator->init(); + int32_t numChecksum = _validator->getChunkChecksum()->countChecksum(); fileAllocationMonitor->setMinValue(0); - fileAllocationMonitor->setMaxValue(bitfieldMan->getTotalLength()); + fileAllocationMonitor->setMaxValue(numChecksum); fileAllocationMonitor->setCurrentValue(0); fileAllocationMonitor->showProgress(); Time cp; - for(int32_t i = 0; i < x; ++i) { - (this->*f)(bitfieldMan, i, checksums[i], checksumLength, checksumLength); + for(int32_t i = 0; i < numChecksum; ++i) { + _validator->validateChunk(); if(cp.elapsedInMillis(500)) { - fileAllocationMonitor->setCurrentValue(i*checksumLength); + fileAllocationMonitor->setCurrentValue(i+1); fileAllocationMonitor->showProgress(); cp.reset(); } } - if(r) { - (this->*f)(bitfieldMan, x, checksums[x], r, checksumLength); - } - fileAllocationMonitor->setCurrentValue(bitfieldMan->getTotalLength()); + fileAllocationMonitor->setCurrentValue(numChecksum); fileAllocationMonitor->showProgress(); } -#endif // ENABLE_MESSAGE_DIGEST diff --git a/src/ChunkChecksumValidator.h b/src/ChunkChecksumValidator.h index 717151a8..097b439b 100644 --- a/src/ChunkChecksumValidator.h +++ b/src/ChunkChecksumValidator.h @@ -36,63 +36,33 @@ #define _D_CHUNK_CHECKSUM_VALIDATOR_H_ #include "common.h" -#include "DiskWriter.h" -#include "BitfieldMan.h" -#ifdef ENABLE_MESSAGE_DIGEST -#include "messageDigest.h" -#endif // ENABLE_MESSAGE_DIGEST #include "LogFactory.h" #include "FileAllocationMonitor.h" #include "NullFileAllocationMonitor.h" +#include "IteratableChunkChecksumValidator.h" class ChunkChecksumValidator { -#ifdef ENABLE_MESSAGE_DIGEST -protected: - DiskWriterHandle diskWriter; - - MessageDigestContext::DigestAlgo algo; +private: + IteratableChunkChecksumValidatorHandle _validator; FileAllocationMonitorHandle fileAllocationMonitor; const Logger* logger; - - void validateSameLengthChecksum(BitfieldMan* bitfieldMan, - int32_t index, - const string& expectedChecksum, - int32_t thisLength, - int32_t checksumLength); - - void validateDifferentLengthChecksum(BitfieldMan* bitfieldMan, - int32_t index, - const string& expectedChecksum, - int32_t thisLength, - int32_t checksumLength); public: - ChunkChecksumValidator(): - diskWriter(0), - algo(DIGEST_ALGO_SHA1), + ChunkChecksumValidator(const IteratableChunkChecksumValidatorHandle v): + _validator(v), fileAllocationMonitor(new NullFileAllocationMonitor()), logger(LogFactory::getInstance()) {} ~ChunkChecksumValidator() {} - void validate(BitfieldMan* bitfieldMan, - const Strings& checksums, - int32_t checksumLength); - - void setDiskWriter(const DiskWriterHandle& diskWriter) { - this->diskWriter = diskWriter; - } - - void setDigestAlgo(const MessageDigestContext::DigestAlgo& algo) { - this->algo = algo; - } + void validate(); void setFileAllocationMonitor(const FileAllocationMonitorHandle& monitor) { this->fileAllocationMonitor = monitor; } -#endif // ENABLE_MESSAGE_DIGEST }; +typedef SharedHandle<ChunkChecksumValidator> ChunkChecksumValidatorHandle; #endif // _D_CHUNK_CHECKSUM_VALIDATOR_H_ diff --git a/src/DefaultBtContext.cc b/src/DefaultBtContext.cc index b5f3ad28..29c748ce 100644 --- a/src/DefaultBtContext.cc +++ b/src/DefaultBtContext.cc @@ -40,6 +40,8 @@ #include "DlAbortEx.h" #include "ShaVisitor.h" #include "Util.h" +#include "MessageDigestHelper.h" +#include "a2netcompat.h" #include <libgen.h> DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-") {} @@ -245,3 +247,39 @@ int32_t DefaultBtContext::getPieceLength() const { int32_t DefaultBtContext::getNumPieces() const { return numPieces; } + +Integers DefaultBtContext::computeFastSet(const string& ipaddr, int32_t fastSetSize) +{ + Integers fastSet; + struct in_addr saddr; + if(inet_aton(ipaddr.c_str(), &saddr) == 0) { + abort(); + } + unsigned char tx[24]; + memcpy(tx, (void*)&saddr.s_addr, 4); + if((tx[0] & 0x80) == 0 || (tx[0] & 0x40) == 0) { + tx[2] = 0x00; + tx[3] = 0x00; + } else { + tx[3] = 0x00; + } + memcpy(tx+4, infoHash, 20); + unsigned char x[20]; + MessageDigestHelper::digest(x, sizeof(x), "sha1", tx, 24); + while((int32_t)fastSet.size() < fastSetSize) { + for(int32_t i = 0; i < 5 && (int32_t)fastSet.size() < fastSetSize; i++) { + int32_t j = i*4; + uint32_t ny; + memcpy(&ny, x+j, 4); + uint32_t y = ntohl(ny); + int32_t index = y%numPieces; + if(find(fastSet.begin(), fastSet.end(), index) == fastSet.end()) { + fastSet.push_back(index); + } + } + unsigned char temp[20]; + MessageDigestHelper::digest(temp, sizeof(temp), "sha1", x, sizeof(x)); + memcpy(x, temp, sizeof(x)); + } + return fastSet; +} diff --git a/src/DefaultBtContext.h b/src/DefaultBtContext.h index 7a2c6811..36c9a543 100644 --- a/src/DefaultBtContext.h +++ b/src/DefaultBtContext.h @@ -107,12 +107,26 @@ private: return (const unsigned char*)peerId.c_str(); } + virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize); + string generatePeerId() const; void setPeerIdPrefix(const string& peerIdPrefix) { _peerIdPrefix = peerIdPrefix; } + + // for unit test + void setInfoHash(const unsigned char* infoHash) + { + memcpy(this->infoHash, infoHash, sizeof(this->infoHash)); + } + + void setNumPieces(int32_t numPieces) + { + this->numPieces = numPieces; + } + }; typedef SharedHandle<DefaultBtContext> DefaultBtContextHandle; diff --git a/src/DefaultBtInteractive.cc b/src/DefaultBtInteractive.cc index 4b0246ee..0263bc43 100644 --- a/src/DefaultBtInteractive.cc +++ b/src/DefaultBtInteractive.cc @@ -96,10 +96,8 @@ void DefaultBtInteractive::addBitfieldMessageToQueue() { void DefaultBtInteractive::addAllowedFastMessageToQueue() { if(peer->isFastExtensionEnabled()) { - Integers fastSet = Util::computeFastSet(peer->ipaddr, - btContext->getInfoHash(), - btContext->getNumPieces(), - allowedFastSetSize); + Integers fastSet = btContext->computeFastSet(peer->ipaddr, + allowedFastSetSize); for(Integers::const_iterator itr = fastSet.begin(); itr != fastSet.end(); itr++) { dispatcher->addMessageToQueue(messageFactory->createAllowedFastMessage(*itr)); diff --git a/src/DefaultPieceStorage.cc b/src/DefaultPieceStorage.cc index 00c8c65d..5afb64e7 100644 --- a/src/DefaultPieceStorage.cc +++ b/src/DefaultPieceStorage.cc @@ -448,10 +448,15 @@ void DefaultPieceStorage::checkIntegrity() { logger->notice(MSG_VALIDATING_FILE, diskAdaptor->getFilePath().c_str()); - ChunkChecksumValidator v; - v.setDigestAlgo(DIGEST_ALGO_SHA1); - v.setDiskWriter(new DiskAdaptorWriter(diskAdaptor)); + ChunkChecksumHandle chunkChecksum = new ChunkChecksum("sha1", + btContext->getPieceHashes(), + btContext->getPieceLength()); + IteratableChunkChecksumValidatorHandle iv = new IteratableChunkChecksumValidator(); + iv->setDiskWriter(new DiskAdaptorWriter(diskAdaptor)); + iv->setBitfield(bitfieldMan); + iv->setChunkChecksum(chunkChecksum); + + ChunkChecksumValidator v(iv); v.setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor()); - v.validate(bitfieldMan, btContext->getPieceHashes(), - btContext->getPieceLength()); + v.validate(); } diff --git a/src/DiskAdaptor.h b/src/DiskAdaptor.h index 32f93022..5a1c6df1 100644 --- a/src/DiskAdaptor.h +++ b/src/DiskAdaptor.h @@ -38,9 +38,6 @@ #include "common.h" #include "FileEntry.h" #include "Logger.h" -#ifdef ENABLE_MESSAGE_DIGEST -#include "messageDigest.h" -#endif // ENABLE_MESSAGE_DIGEST class DiskAdaptor { protected: @@ -63,17 +60,14 @@ public: virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset) = 0; -#ifdef ENABLE_MESSAGE_DIGEST - virtual string messageDigest(int64_t offset, int64_t length, - const MessageDigestContext::DigestAlgo& algo) = 0; -#endif // ENABLE_MESSAGE_DIGEST - virtual void onDownloadComplete() = 0; virtual bool fileExists() = 0; virtual string getFilePath() = 0; + virtual int64_t size() const = 0; + void setFileEntries(const FileEntries& fileEntries) { this->fileEntries = fileEntries; } diff --git a/src/DiskAdaptorWriter.h b/src/DiskAdaptorWriter.h index 3c400ddc..5a5fc5e3 100644 --- a/src/DiskAdaptorWriter.h +++ b/src/DiskAdaptorWriter.h @@ -78,12 +78,6 @@ public: return diskAdaptor->readData((unsigned char*)data, len, position); } - virtual string messageDigest(int64_t offset, int64_t length, - const MessageDigestContext::DigestAlgo& algo) - { - return diskAdaptor->messageDigest(offset, length, algo); - } - virtual void truncate(int64_t length) { throw new FatalException("DiskAdaptorWriter::truncate() is not implemented yet."); @@ -91,7 +85,7 @@ public: virtual int64_t size() const { - throw new FatalException("DiskAdaptorWriter::size() is not implemented yet."); + return diskAdaptor->size(); } }; diff --git a/src/DiskWriter.h b/src/DiskWriter.h index 9ff7602f..5f0a93b5 100644 --- a/src/DiskWriter.h +++ b/src/DiskWriter.h @@ -36,9 +36,6 @@ #define _D_DISK_WRITER_H_ #include "common.h" -#ifdef ENABLE_MESSAGE_DIGEST -#include "messageDigest.h" -#endif // ENABLE_MESSAGE_DIGEST using namespace std; @@ -90,10 +87,6 @@ public: virtual int32_t readData(unsigned char* data, int32_t len, int64_t position) { return readData((char*)data, len, position); } -#ifdef ENABLE_MESSAGE_DIGEST - virtual string messageDigest(int64_t offset, int64_t length, - const MessageDigestContext::DigestAlgo& algo) = 0; -#endif // ENABLE_MESSAGE_DIGEST virtual void truncate(int64_t length) = 0; diff --git a/src/DownloadCommand.cc b/src/DownloadCommand.cc index 243c048c..9a19b0fa 100644 --- a/src/DownloadCommand.cc +++ b/src/DownloadCommand.cc @@ -118,7 +118,7 @@ bool DownloadCommand::executeInternal() { _requestGroup->getSegmentMan()->completeSegment(cuid, segment); #ifdef ENABLE_MESSAGE_DIGEST if(e->option->get(PREF_REALTIME_CHUNK_CHECKSUM) == V_TRUE) { - _requestGroup->getSegmentMan()->tryChunkChecksumValidation(segment); + _requestGroup->getSegmentMan()->tryChunkChecksumValidation(segment, _requestGroup->getChunkChecksum()); } #endif // ENABLE_MESSAGE_DIGEST // this unit is going to download another segment. diff --git a/src/IteratableChecksumValidator.cc b/src/IteratableChecksumValidator.cc index e094a632..545d4328 100644 --- a/src/IteratableChecksumValidator.cc +++ b/src/IteratableChecksumValidator.cc @@ -76,6 +76,7 @@ void IteratableChecksumValidator::init() _bitfield->setAllBit(); _currentOffset = 0; - _ctx = new MessageDigestContext(_checksum->getDigestAlgo()); + _ctx = new MessageDigestContext(); + _ctx->trySetAlgo(_checksum->getAlgo()); _ctx->digestInit(); } diff --git a/src/IteratableChunkChecksumValidator.cc b/src/IteratableChunkChecksumValidator.cc index 9ad30c46..0e43acc3 100644 --- a/src/IteratableChunkChecksumValidator.cc +++ b/src/IteratableChunkChecksumValidator.cc @@ -35,6 +35,7 @@ #include "IteratableChunkChecksumValidator.h" #include "Util.h" #include "message.h" +#include "MessageDigestHelper.h" void IteratableChunkChecksumValidator::validateChunk() { @@ -65,7 +66,7 @@ string IteratableChunkChecksumValidator::calculateActualChecksum() { int64_t offset = ((int64_t)_currentIndex)*_chunkChecksum->getChecksumLength(); int32_t length = _diskWriter->size() < offset+_chunkChecksum->getChecksumLength() ? _diskWriter->size()-offset : _chunkChecksum->getChecksumLength(); - return _diskWriter->messageDigest(offset, length, _chunkChecksum->getAlgo()); + return MessageDigestHelper::digest(_chunkChecksum->getAlgo(), _diskWriter, offset, length); } bool IteratableChunkChecksumValidator::canValidate() const diff --git a/src/IteratableChunkChecksumValidator.h b/src/IteratableChunkChecksumValidator.h index 908a3540..6e4bb4bc 100644 --- a/src/IteratableChunkChecksumValidator.h +++ b/src/IteratableChunkChecksumValidator.h @@ -89,6 +89,11 @@ public: { return _bitfield->getTotalLength(); } + + ChunkChecksumHandle getChunkChecksum() + { + return _chunkChecksum; + } }; typedef SharedHandle<IteratableChunkChecksumValidator> IteratableChunkChecksumValidatorHandle; diff --git a/src/Makefile.am b/src/Makefile.am index 4a8b3ed6..66d369a3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -45,7 +45,6 @@ SRCS = Socket.h\ Option.cc Option.h\ Base64.cc Base64.h\ CookieBox.cc CookieBox.h\ - messageDigest.h\ LogFactory.cc LogFactory.h\ NullLogger.h\ TimeA2.cc TimeA2.h\ @@ -109,7 +108,9 @@ SRCS += ChunkChecksumValidator.cc ChunkChecksumValidator.h\ ChecksumCommand.cc ChecksumCommand.h\ CheckIntegrityCommand.cc CheckIntegrityCommand.h\ CheckIntegrityEntry.cc CheckIntegrityEntry.h\ - CheckIntegrityMan.h + CheckIntegrityMan.h\ + messageDigest.cc messageDigest.h\ + MessageDigestHelper.cc MessageDigestHelper.h endif # ENABLE_MESSAGE_DIGEST if ENABLE_BITTORRENT diff --git a/src/Makefile.in b/src/Makefile.in index deb01f1c..9c38b3a2 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -46,7 +46,9 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCommand.cc ChecksumCommand.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.cc CheckIntegrityCommand.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityEntry.cc CheckIntegrityEntry.h\ -@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityMan.h +@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityMan.h\ +@ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.cc messageDigest.h\ +@ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelper.cc MessageDigestHelper.h @ENABLE_BITTORRENT_TRUE@am__append_2 = MetaEntry.h\ @ENABLE_BITTORRENT_TRUE@ Data.cc Data.h\ @@ -219,8 +221,8 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ ChunkedEncoding.h DiskWriter.h AbstractDiskWriter.cc \ AbstractDiskWriter.h DefaultDiskWriter.cc DefaultDiskWriter.h \ File.cc File.h Option.cc Option.h Base64.cc Base64.h \ - CookieBox.cc CookieBox.h messageDigest.h LogFactory.cc \ - LogFactory.h NullLogger.h TimeA2.cc TimeA2.h SharedHandle.h \ + CookieBox.cc CookieBox.h LogFactory.cc LogFactory.h \ + NullLogger.h TimeA2.cc TimeA2.h SharedHandle.h \ HandleRegistry.h FeatureConfig.cc FeatureConfig.h \ DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \ SpeedCalc.cc SpeedCalc.h PeerStat.h BitfieldMan.cc \ @@ -259,9 +261,10 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ IteratableChecksumValidator.cc IteratableChecksumValidator.h \ ChecksumCommand.cc ChecksumCommand.h CheckIntegrityCommand.cc \ CheckIntegrityCommand.h CheckIntegrityEntry.cc \ - CheckIntegrityEntry.h CheckIntegrityMan.h MetaEntry.h Data.cc \ - Data.h Dictionary.cc Dictionary.h List.cc List.h \ - MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \ + CheckIntegrityEntry.h CheckIntegrityMan.h messageDigest.cc \ + messageDigest.h MessageDigestHelper.cc MessageDigestHelper.h \ + MetaEntry.h Data.cc Data.h Dictionary.cc Dictionary.h List.cc \ + List.h MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \ ShaVisitor.cc ShaVisitor.h PeerConnection.cc PeerConnection.h \ PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \ PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \ @@ -338,7 +341,9 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidator.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCommand.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.$(OBJEXT) \ -@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityEntry.$(OBJEXT) +@ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityEntry.$(OBJEXT) \ +@ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.$(OBJEXT) \ +@ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelper.$(OBJEXT) @ENABLE_BITTORRENT_TRUE@am__objects_2 = Data.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ Dictionary.$(OBJEXT) List.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ MetaFileUtil.$(OBJEXT) \ @@ -676,8 +681,8 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \ ChunkedEncoding.h DiskWriter.h AbstractDiskWriter.cc \ AbstractDiskWriter.h DefaultDiskWriter.cc DefaultDiskWriter.h \ File.cc File.h Option.cc Option.h Base64.cc Base64.h \ - CookieBox.cc CookieBox.h messageDigest.h LogFactory.cc \ - LogFactory.h NullLogger.h TimeA2.cc TimeA2.h SharedHandle.h \ + CookieBox.cc CookieBox.h LogFactory.cc LogFactory.h \ + NullLogger.h TimeA2.cc TimeA2.h SharedHandle.h \ HandleRegistry.h FeatureConfig.cc FeatureConfig.h \ DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \ SpeedCalc.cc SpeedCalc.h PeerStat.h BitfieldMan.cc \ @@ -902,6 +907,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChunkChecksumValidator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/List.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LogFactory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MessageDigestHelper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetaFileUtil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkEntry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkRequestInfo.Po@am__quote@ @@ -960,6 +966,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgen.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localtime_r.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messageDigest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strptime.Po@am__quote@ .c.o: diff --git a/src/MessageDigestHelper.cc b/src/MessageDigestHelper.cc new file mode 100644 index 00000000..8819dcdc --- /dev/null +++ b/src/MessageDigestHelper.cc @@ -0,0 +1,101 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#include "MessageDigestHelper.h" +#include "messageDigest.h" +#include "DlAbortEx.h" +#include "message.h" +#include "DefaultDiskWriter.h" +#include "Util.h" +#include <errno.h> + +string MessageDigestHelper::digest(const string& algo, DiskWriterHandle diskWriter, int64_t offset, int64_t length) +{ + MessageDigestContext ctx; + ctx.trySetAlgo(algo); + ctx.digestInit(); + + int32_t BUFSIZE = 4096; + char BUF[BUFSIZE]; + int64_t iteration = length/BUFSIZE; + int32_t tail = length%BUFSIZE; + for(int64_t i = 0; i < iteration; ++i) { + int32_t readLength = diskWriter->readData(BUF, BUFSIZE, offset); + if(readLength != BUFSIZE) { + throw new DlAbortEx(EX_FILE_READ, "n/a", strerror(errno)); + } + ctx.digestUpdate(BUF, readLength); + offset += readLength; + } + if(tail) { + int32_t readLength = diskWriter->readData(BUF, tail, offset); + if(readLength != tail) { + throw new DlAbortEx(EX_FILE_READ, "n/a", strerror(errno)); + } + ctx.digestUpdate(BUF, readLength); + } + string rawMD = ctx.digestFinal(); + return Util::toHex((const unsigned char*)rawMD.c_str(), rawMD.size()); +} + +string MessageDigestHelper::digest(const string& algo, const string& filename) +{ + DiskWriterHandle writer = new DefaultDiskWriter(); + writer->openExistingFile(filename); + return digest(algo, writer); +} + +string MessageDigestHelper::digest(const string& algo, const void* data, int32_t length) +{ + MessageDigestContext ctx; + ctx.trySetAlgo(algo); + ctx.digestInit(); + ctx.digestUpdate(data, length); + string rawMD = ctx.digestFinal(); + return Util::toHex((const unsigned char*)rawMD.c_str(), rawMD.size()); +} + +void MessageDigestHelper::digest(unsigned char* md, int32_t mdLength, + const string& algo, const void* data, int32_t length) +{ + if(mdLength < MessageDigestContext::digestLength(algo)) { + throw new DlAbortEx("Insufficient space for storing message digest: %d required, but only %d is allocated", MessageDigestContext::digestLength(algo), mdLength); + } + MessageDigestContext ctx; + ctx.trySetAlgo(algo); + ctx.digestInit(); + ctx.digestUpdate(data, length); + ctx.digestFinal(md); +} + diff --git a/src/MessageDigestHelper.h b/src/MessageDigestHelper.h new file mode 100644 index 00000000..21e4a215 --- /dev/null +++ b/src/MessageDigestHelper.h @@ -0,0 +1,77 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#ifndef _D_MESSAGE_DIGEST_HELPER_H_ +#define _D_MESSAGE_DIGEST_HELPER_H_ + +#include "common.h" +#include "DiskWriter.h" + +class MessageDigestHelper { +public: + /** + * Returns message digest in hexadecimal notation. + * Digest algorithm is specified by algo. + */ + static string digest(const string& algo, DiskWriterHandle diskWriter, int64_t offset, int64_t length); + + /** + * Calculates message digest of file opened by diskWriter. + */ + static string digest(const string& algo, DiskWriterHandle diskWriter) + { + return digest(algo, diskWriter, 0, diskWriter->size()); + } + + /** + * Calculates message digest of file denoted by filename. + */ + static string digest(const string& algo, const string& filename); + + static string digest(const string& algo, const void* data, int32_t length); + + static string digestString(const string& algo, const string& data) + { + return digest(algo, data.c_str(), data.size()); + } + + /** + * Stores *raw* message digest into md. + * Throws exception when mdLength is less than the size of message digest. + */ + static void digest(unsigned char* md, int32_t mdLength, + const string& algo, const void* data, int32_t length); +}; + +#endif // _D_MESSAGE_DIGEST_HELPER_H_ diff --git a/src/MetalinkEntry.cc b/src/MetalinkEntry.cc index b82129fa..80e2def8 100644 --- a/src/MetalinkEntry.cc +++ b/src/MetalinkEntry.cc @@ -39,7 +39,7 @@ MetalinkEntry::MetalinkEntry() #ifdef ENABLE_MESSAGE_DIGEST :checksum(0), - chunkChecksum(0) + chunkChecksum(0) #endif // ENABLE_MESSAGE_DIGEST {} @@ -84,7 +84,9 @@ public: switch(res->type) { case MetalinkResource::TYPE_FTP: case MetalinkResource::TYPE_HTTP: +#ifdef ENABLE_SSL case MetalinkResource::TYPE_HTTPS: +#endif // ENABLE_SSL #ifdef ENABLE_BITTORRENT case MetalinkResource::TYPE_BITTORRENT: #endif // ENABLE_BITTORRENT diff --git a/src/MetalinkEntry.h b/src/MetalinkEntry.h index 783e9d1f..9774e6e0 100644 --- a/src/MetalinkEntry.h +++ b/src/MetalinkEntry.h @@ -55,10 +55,9 @@ public: string version; string language; string os; - ChecksumHandle checksum; -public: MetalinkResources resources; #ifdef ENABLE_MESSAGE_DIGEST + ChecksumHandle checksum; ChunkChecksumHandle chunkChecksum; #endif // ENABLE_MESSAGE_DIGEST public: @@ -72,8 +71,8 @@ public: this->version = metalinkEntry.version; this->language = metalinkEntry.language; this->os = metalinkEntry.os; - this->checksum = metalinkEntry.checksum; #ifdef ENABLE_MESSAGE_DIGEST + this->checksum = metalinkEntry.checksum; this->chunkChecksum = metalinkEntry.chunkChecksum; #endif // ENABLE_MESSAGE_DIGEST } diff --git a/src/MetalinkRequestInfo.cc b/src/MetalinkRequestInfo.cc index ddae83d8..6da65841 100644 --- a/src/MetalinkRequestInfo.cc +++ b/src/MetalinkRequestInfo.cc @@ -131,15 +131,19 @@ RequestInfos MetalinkRequestInfo::execute() { entry->resources.end(), FindBitTorrentUrl()); Strings urls; +#ifdef ENABLE_MESSAGE_DIGEST ChecksumHandle checksum = 0; +#endif // ENABLE_MESSAGE_DIGEST if(itr == entry->resources.end()) { entry->reorderResourcesByPreference(); for_each(entry->resources.begin(), entry->resources.end(), AccumulateNonP2PUrl(&urls, op->getAsInt(PREF_SPLIT))); +#ifdef ENABLE_MESSAGE_DIGEST // TODO // set checksum checksum = entry->checksum; +#endif // ENABLE_MESSAGE_DIGEST } else { // BitTorrent downloading urls.push_back((*itr)->url); diff --git a/src/MultiDiskAdaptor.cc b/src/MultiDiskAdaptor.cc index 32375528..b866d68e 100644 --- a/src/MultiDiskAdaptor.cc +++ b/src/MultiDiskAdaptor.cc @@ -37,7 +37,6 @@ #include "DlAbortEx.h" #include "message.h" #include "Util.h" -#include <errno.h> void MultiDiskAdaptor::resetDiskWriterEntries() { diskWriterEntries.clear(); @@ -169,58 +168,11 @@ int32_t MultiDiskAdaptor::readData(unsigned char* data, int32_t len, int64_t off return totalReadLength; } -void MultiDiskAdaptor::hashUpdate(MessageDigestContext& ctx, - const DiskWriterEntryHandle& entry, - int64_t offset, int64_t length) -{ - int32_t BUFSIZE = 16*1024; - unsigned char buf[BUFSIZE]; - for(int64_t i = 0; i < length/BUFSIZE; i++) { - if(BUFSIZE != entry->getDiskWriter()->readData(buf, BUFSIZE, offset)) { - throw new DlAbortEx(EX_FILE_SHA1SUM, "", strerror(errno)); - } - ctx.digestUpdate(buf, BUFSIZE); - offset += BUFSIZE; - } - int32_t r = length%BUFSIZE; - if(r > 0) { - if((int32_t)r != entry->getDiskWriter()->readData(buf, r, offset)) { - throw new DlAbortEx(EX_FILE_SHA1SUM, "", strerror(errno)); - } - ctx.digestUpdate(buf, r); - } -} - -string MultiDiskAdaptor::messageDigest(int64_t offset, int64_t length, - const MessageDigestContext::DigestAlgo& algo) { - int64_t fileOffset = offset; - bool reading = false; - int32_t rem = length; - MessageDigestContext ctx(algo); - ctx.digestInit(); - - for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); - itr != diskWriterEntries.end() && rem != 0; itr++) { - if(isInRange(*itr, offset) || reading) { - int32_t readLength = calculateLength((*itr), fileOffset, rem); - hashUpdate(ctx, *itr, fileOffset, readLength); - rem -= readLength; - reading = true; - fileOffset = 0; - } else { - fileOffset -= (*itr)->getFileEntry()->getLength(); - } - } - if(!reading) { - throw new DlAbortEx(EX_FILE_OFFSET_OUT_OF_RANGE, Util::llitos(offset, true).c_str()); - } - unsigned char hashValue[20]; - ctx.digestFinal(hashValue); - return Util::toHex(hashValue, 20); -} - bool MultiDiskAdaptor::fileExists() { + if(diskWriterEntries.empty()) { + resetDiskWriterEntries(); + } for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end(); itr++) { if((*itr)->fileExists(getTopDirPath())) { @@ -229,3 +181,14 @@ bool MultiDiskAdaptor::fileExists() } return false; } + +// TODO call DiskWriter::openFile() before calling this function. +int64_t MultiDiskAdaptor::size() const +{ + int64_t size = 0; + for(DiskWriterEntries::const_iterator itr = diskWriterEntries.begin(); + itr != diskWriterEntries.end(); itr++) { + size += (*itr)->size(); + } + return size; +} diff --git a/src/MultiDiskAdaptor.h b/src/MultiDiskAdaptor.h index 0610517e..1d01d937 100644 --- a/src/MultiDiskAdaptor.h +++ b/src/MultiDiskAdaptor.h @@ -81,6 +81,11 @@ public: return File(getFilePath(topDir)).exists(); } + int64_t size() const + { + return diskWriter->size(); + } + FileEntryHandle getFileEntry() const { return fileEntry; } @@ -115,10 +120,6 @@ private: int64_t fileOffset, int32_t rem) const; - void hashUpdate(MessageDigestContext& ctx, - const DiskWriterEntryHandle& entry, - int64_t offset, int64_t length); - string getTopDirPath() const; public: MultiDiskAdaptor():pieceLength(0), @@ -142,15 +143,14 @@ public: virtual int32_t readData(unsigned char* data, int32_t len, int64_t offset); - virtual string messageDigest(int64_t offset, int64_t length, - const MessageDigestContext::DigestAlgo& algo); - virtual bool fileExists(); virtual string getFilePath() { return getTopDirPath(); } + virtual int64_t size() const; + void setTopDir(const string& topDir) { this->topDir = topDir; } diff --git a/src/Peer.cc b/src/Peer.cc index 685b1b36..1017c250 100644 --- a/src/Peer.cc +++ b/src/Peer.cc @@ -35,6 +35,7 @@ #include "Peer.h" #include "BitfieldManFactory.h" #include "Util.h" +#include "MessageDigestHelper.h" Peer::Peer(string ipaddr, int32_t port, int32_t pieceLength, int64_t totalLength): ipaddr(ipaddr), @@ -50,7 +51,7 @@ Peer::Peer(string ipaddr, int32_t port, int32_t pieceLength, int64_t totalLength this->bitfield = BitfieldManFactory::getFactoryInstance()-> createBitfieldMan(pieceLength, totalLength); string idSeed = ipaddr+":"+Util::itos(port); - id = Util::simpleMessageDigest(idSeed); + id = MessageDigestHelper::digestString("sha1", idSeed); } /* diff --git a/src/SegmentMan.cc b/src/SegmentMan.cc index 8c0f23a5..bcd784dd 100644 --- a/src/SegmentMan.cc +++ b/src/SegmentMan.cc @@ -41,7 +41,7 @@ #include "LogFactory.h" #include "BitfieldManFactory.h" #ifdef ENABLE_MESSAGE_DIGEST -#include "ChunkChecksumValidator.h" +#include "MessageDigestHelper.h" #endif // ENABLE_MESSAGE_DIGEST #include "a2io.h" #include <errno.h> @@ -54,11 +54,6 @@ SegmentMan::SegmentMan():logger(LogFactory::getInstance()), dir("."), errors(0), diskWriter(0) -#ifdef ENABLE_MESSAGE_DIGEST - , - chunkHashLength(0), - digestAlgo(DIGEST_ALGO_SHA1) -#endif // ENABLE_MESSAGE_DIGEST {} SegmentMan::~SegmentMan() { @@ -474,29 +469,16 @@ void SegmentMan::markPieceDone(int64_t length) } #ifdef ENABLE_MESSAGE_DIGEST -void SegmentMan::checkIntegrity() -{ - logger->notice(MSG_VALIDATING_FILE, - getFilePath().c_str()); - ChunkChecksumValidator v; - v.setDigestAlgo(digestAlgo); - v.setDiskWriter(diskWriter); - v.setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor()); - v.validate(bitfield, pieceHashes, chunkHashLength); -} -#endif // ENABLE_MESSAGE_DIGEST - -#ifdef ENABLE_MESSAGE_DIGEST -bool SegmentMan::isChunkChecksumValidationReady() const { - return bitfield && totalSize > 0 && - ((int64_t)pieceHashes.size())*chunkHashLength >= totalSize; +bool SegmentMan::isChunkChecksumValidationReady(const ChunkChecksumHandle& chunkChecksum) const { + return !chunkChecksum.isNull() && bitfield && totalSize > 0 && + chunkChecksum->getEstimatedDataLength() >= totalSize; } #endif // ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST -void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment) +void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment, const ChunkChecksumHandle& chunkChecksum) { - if(!isChunkChecksumValidationReady()) { + if(!isChunkChecksumValidationReady(chunkChecksum)) { return; } int32_t hashStartIndex; @@ -504,13 +486,13 @@ void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment) Util::indexRange(hashStartIndex, hashEndIndex, segment->getPosition(), segment->writtenLength, - chunkHashLength); - if(!bitfield->isBitSetOffsetRange((int64_t)hashStartIndex*chunkHashLength, - chunkHashLength)) { + chunkChecksum->getChecksumLength()); + if(!bitfield->isBitSetOffsetRange((int64_t)hashStartIndex*chunkChecksum->getChecksumLength(), + chunkChecksum->getChecksumLength())) { ++hashStartIndex; } - if(!bitfield->isBitSetOffsetRange((int64_t)hashEndIndex*chunkHashLength, - chunkHashLength)) { + if(!bitfield->isBitSetOffsetRange((int64_t)hashEndIndex*chunkChecksum->getChecksumLength(), + chunkChecksum->getChecksumLength())) { --hashEndIndex; } logger->debug("hashStartIndex=%d, hashEndIndex=%d", @@ -519,27 +501,27 @@ void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment) logger->debug(MSG_NO_CHUNK_CHECKSUM); return; } - int64_t hashOffset = ((int64_t)hashStartIndex)*chunkHashLength; + int64_t hashOffset = ((int64_t)hashStartIndex)*chunkChecksum->getChecksumLength(); int32_t startIndex; int32_t endIndex; Util::indexRange(startIndex, endIndex, hashOffset, - (hashEndIndex-hashStartIndex+1)*chunkHashLength, + (hashEndIndex-hashStartIndex+1)*chunkChecksum->getChecksumLength(), bitfield->getBlockLength()); logger->debug("startIndex=%d, endIndex=%d", startIndex, endIndex); if(bitfield->isBitRangeSet(startIndex, endIndex)) { for(int32_t index = hashStartIndex; index <= hashEndIndex; ++index) { - int64_t offset = ((int64_t)index)*chunkHashLength; + int64_t offset = ((int64_t)index)*chunkChecksum->getChecksumLength(); int32_t dataLength = - offset+chunkHashLength <= totalSize ? chunkHashLength : totalSize-offset; - string actualChecksum = diskWriter->messageDigest(offset, dataLength, digestAlgo); - string expectedChecksum = pieceHashes[index]; - if(expectedChecksum == actualChecksum) { - logger->info(MSG_GOOD_CHUNK_CHECKSUM); + offset+chunkChecksum->getChecksumLength() <= totalSize ? + chunkChecksum->getChecksumLength() : totalSize-offset; + string actualChecksum = MessageDigestHelper::digest(chunkChecksum->getAlgo(), diskWriter, offset, dataLength); + if(chunkChecksum->validateChunk(actualChecksum, index)) { + logger->info(MSG_GOOD_CHUNK_CHECKSUM, actualChecksum.c_str()); } else { logger->info(EX_INVALID_CHUNK_CHECKSUM, index, Util::llitos(offset, true).c_str(), - expectedChecksum.c_str(), actualChecksum.c_str()); + chunkChecksum->getChecksum(index).c_str(), actualChecksum.c_str()); logger->debug("Unset bit from %d to %d(inclusive)", startIndex, endIndex); bitfield->unsetBitRange(startIndex, endIndex); break; diff --git a/src/SegmentMan.h b/src/SegmentMan.h index 1dc869c2..7e877e6a 100644 --- a/src/SegmentMan.h +++ b/src/SegmentMan.h @@ -43,6 +43,9 @@ #include "Request.h" #include "BitfieldMan.h" #include "PeerStat.h" +#ifdef ENABLE_MESSAGE_DIGEST +# include "ChunkChecksum.h" +#endif // ENABLE_MESSAGE_DIGEST using namespace std; @@ -157,12 +160,6 @@ public: DiskWriterHandle diskWriter; Requests reserved; -#ifdef ENABLE_MESSAGE_DIGEST - Strings pieceHashes; - int32_t chunkHashLength; - MessageDigestContext::DigestAlgo digestAlgo; -#endif // ENABLE_MESSAGE_DIGEST - SegmentMan(); ~SegmentMan(); @@ -300,11 +297,9 @@ public: } #ifdef ENABLE_MESSAGE_DIGEST - void checkIntegrity(); - - void tryChunkChecksumValidation(const SegmentHandle& segment); + void tryChunkChecksumValidation(const SegmentHandle& segment, const ChunkChecksumHandle& chunkChecksum); - bool isChunkChecksumValidationReady() const; + bool isChunkChecksumValidationReady(const ChunkChecksumHandle& chunkChecksum) const; #endif // ENABLE_MESSAGE_DIGEST }; diff --git a/src/ShaVisitor.cc b/src/ShaVisitor.cc index b760d72c..3aae84bd 100644 --- a/src/ShaVisitor.cc +++ b/src/ShaVisitor.cc @@ -35,8 +35,9 @@ #include "ShaVisitor.h" #include "Util.h" -ShaVisitor::ShaVisitor(): - ctx(DIGEST_ALGO_SHA1) { +ShaVisitor::ShaVisitor() +{ + ctx.trySetAlgo("sha1"); ctx.digestInit(); } diff --git a/src/SimpleRandomizer.h b/src/SimpleRandomizer.h index 2afd068d..9a593c87 100644 --- a/src/SimpleRandomizer.h +++ b/src/SimpleRandomizer.h @@ -54,27 +54,22 @@ public: } static void init() { -#ifdef HAVE_SRANDOM - srandom(time(0)); -#else srand(time(0)); -#endif } virtual ~SimpleRandomizer() {} virtual long int getRandomNumber() { -#ifdef HAVE_RANDOM - return random(); -#else return rand(); -#endif } virtual long int getMaxRandomNumber() { return RAND_MAX; } + /** + * Returns random number in [0, to). + */ virtual long int getRandomNumber(long int to) { return(int32_t)(((double)to)*getRandomNumber()/(getMaxRandomNumber()+1.0)); diff --git a/src/TorrentRequestInfo.cc b/src/TorrentRequestInfo.cc index c95661d5..1eb6391b 100644 --- a/src/TorrentRequestInfo.cc +++ b/src/TorrentRequestInfo.cc @@ -80,7 +80,7 @@ RequestInfos TorrentRequestInfo::execute() { if(BT_PROGRESS_INFO_FILE(btContext)->exists()) { // load .aria2 file if it exists. BT_PROGRESS_INFO_FILE(btContext)->load(); - PIECE_STORAGE(btContext)->getDiskAdaptor()->openExistingFile(); + PIECE_STORAGE(btContext)->getDiskAdaptor()->openFile(); #ifdef ENABLE_MESSAGE_DIGEST if(op->get(PREF_CHECK_INTEGRITY) == V_TRUE) { PIECE_STORAGE(btContext)->checkIntegrity(); @@ -94,7 +94,7 @@ RequestInfos TorrentRequestInfo::execute() { BT_PROGRESS_INFO_FILE(btContext)->getFilename().c_str()); throw new FatalException(EX_DOWNLOAD_ABORTED); } else { - PIECE_STORAGE(btContext)->getDiskAdaptor()->openExistingFile(); + PIECE_STORAGE(btContext)->getDiskAdaptor()->openFile(); #ifdef ENABLE_MESSAGE_DIGEST if(op->get(PREF_CHECK_INTEGRITY) == V_TRUE) { PIECE_STORAGE(btContext)->markAllPiecesDone(); @@ -103,7 +103,7 @@ RequestInfos TorrentRequestInfo::execute() { #endif // ENABLE_MESSAGE_DIGEST } } else { - PIECE_STORAGE(btContext)->getDiskAdaptor()->initAndOpenFile(); + PIECE_STORAGE(btContext)->getDiskAdaptor()->openFile(); } } diff --git a/src/Util.cc b/src/Util.cc index 3c90208b..7e231c9c 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -480,93 +480,6 @@ string Util::getContentDispositionFilename(const string& header) { return trim(header.substr(filenamesp, filenameep-filenamesp), "\r\n '\""); } -#ifdef ENABLE_MESSAGE_DIGEST -void Util::sha1Sum(unsigned char* digest, const void* data, int32_t dataLength) { - MessageDigestContext ctx(DIGEST_ALGO_SHA1); - ctx.digestInit(); - ctx.digestUpdate(data, dataLength); - ctx.digestFinal(digest); -} - -string Util::simpleMessageDigest(const string& data) { - unsigned char checksum[20]; - sha1Sum(checksum, data.c_str(), data.size()); - return Util::toHex(checksum, sizeof(checksum)); -} - -#endif // ENABLE_MESSAGE_DIGEST - -#ifdef ENABLE_MESSAGE_DIGEST -void Util::fileChecksum(const string& filename, unsigned char* digest, - MessageDigestContext::DigestAlgo algo) { - MessageDigestContext ctx(algo); - ctx.digestInit(); - - int32_t BUFLEN = 4096; - char buf[BUFLEN]; - - int32_t fd; - if((fd = open(filename.c_str(), O_RDWR|O_BINARY, OPEN_MODE)) < 0) { - throw new DlAbortEx(EX_FILE_OPEN, filename.c_str(), strerror(errno)); - } - while(1) { - int32_t size = read(fd, buf, BUFLEN); - if(size == -1) { - if(errno == EINTR) { - continue; - } else { - close(fd); - throw new DlAbortEx(EX_FILE_READ, filename.c_str(), strerror(errno)); - } - } else if(size > 0) { - ctx.digestUpdate(buf, size); - } - if(size < BUFLEN) { - break; - } - } - ctx.digestFinal(digest); -} -#endif // ENABLE_MESSAGE_DIGEST - -#ifdef ENABLE_BITTORRENT -Integers Util::computeFastSet(string ipaddr, const unsigned char* infoHash, - int32_t pieces, int32_t fastSetSize) { - Integers fastSet; - struct in_addr saddr; - if(inet_aton(ipaddr.c_str(), &saddr) == 0) { - abort(); - } - unsigned char tx[24]; - memcpy(tx, (void*)&saddr.s_addr, 4); - if((tx[0] & 0x80) == 0 || (tx[0] & 0x40) == 0) { - tx[2] = 0x00; - tx[3] = 0x00; - } else { - tx[3] = 0x00; - } - memcpy(tx+4, infoHash, 20); - unsigned char x[20]; - sha1Sum(x, tx, 24); - while((int32_t)fastSet.size() < fastSetSize) { - for(int32_t i = 0; i < 5 && (int32_t)fastSet.size() < fastSetSize; i++) { - int32_t j = i*4; - uint32_t ny; - memcpy(&ny, x+j, 4); - uint32_t y = ntohl(ny); - int32_t index = y%pieces; - if(find(fastSet.begin(), fastSet.end(), index) == fastSet.end()) { - fastSet.push_back(index); - } - } - unsigned char temp[20]; - sha1Sum(temp, x, 20); - memcpy(x, temp, sizeof(x)); - } - return fastSet; -} -#endif // ENABLE_BITTORRENT - static int32_t nbits[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, @@ -36,15 +36,10 @@ #define _D_UTIL_H_ #include "common.h" -#include "FileEntry.h" #include "a2time.h" -#ifdef ENABLE_MESSAGE_DIGEST -#include "messageDigest.h" -#endif // ENABLE_MESSAGE_DIGEST -#include <string> +#include "FileEntry.h" #include <utility> #include <deque> -#include <stdio.h> #include <ostream> #define STRTOLL(X) strtoll(X, (char**)NULL, 10); @@ -111,28 +106,10 @@ public: // this function temporarily put here static string getContentDispositionFilename(const string& header); - // digest must be at least 20 bytes long. -#ifdef ENABLE_MESSAGE_DIGEST - static void sha1Sum(unsigned char* digest, const void* data, int32_t dataLength); - static string simpleMessageDigest(const string& data); -#endif // ENABLE_MESSAGE_DIGEST - - // Before call this method, allocate enough memory to the parameter "digest". - // For sha1, you need 20 bytes. For md5, 16 bytes. -#ifdef ENABLE_MESSAGE_DIGEST - static void fileChecksum(const string& filename, unsigned char* digest, - MessageDigestContext::DigestAlgo algo); -#endif // ENABLE_MESSAGE_DIGEST - -#ifdef ENABLE_BITTORRENT - static Integers computeFastSet(string ipaddr, const unsigned char* infoHash, - int32_t pieces, int32_t fastSetSize); -#endif // ENABLE_BITTORRENT - static int32_t countBit(uint32_t n); - + static string randomAlpha(int32_t length); - + static string toUpper(const string& src); static string toLower(const string& src); diff --git a/src/Xml2MetalinkProcessor.cc b/src/Xml2MetalinkProcessor.cc index 793d8656..f1743821 100644 --- a/src/Xml2MetalinkProcessor.cc +++ b/src/Xml2MetalinkProcessor.cc @@ -111,20 +111,36 @@ MetalinkEntryHandle Xml2MetalinkProcessor::getEntry(const string& xpath) { entry->language = Util::trim(xpathContent(xpath+"/m:language")); entry->os = Util::trim(xpathContent(xpath+"/m:os")); #ifdef ENABLE_MESSAGE_DIGEST - string md; - md = Util::toLower(Util::trim(xpathContent(xpath+"/m:verification/m:hash[@type=\"sha1\"]"))); - if(md.size() > 0) { - entry->checksum = new Checksum(); - entry->checksum->setMessageDigest(md); - entry->checksum->setDigestAlgo(DIGEST_ALGO_SHA1); - } else { - md = Util::toLower(Util::trim(xpathContent(xpath+"/m:verification/m:hash[@type=\"md5\"]"))); - if(md.size() > 0) { - entry->checksum = new Checksum(); - entry->checksum->setMessageDigest(md); - entry->checksum->setDigestAlgo(DIGEST_ALGO_MD5); + xmlXPathObjectPtr hashPathObj = xpathEvaluation(xpath+"/m:verification/m:hash"); + if(hashPathObj) { + xmlNodeSetPtr nodeSet = hashPathObj->nodesetval; + for(int32_t i = 0; i < nodeSet->nodeNr; ++i) { + xmlNodePtr node = nodeSet->nodeTab[i]; + string algo = Util::trim(xmlAttribute(node, "type")); + if(MessageDigestContext::supports(algo)) { + entry->checksum = new Checksum(algo, Util::trim(xmlContent(node))); + break; + } } } + xmlXPathFreeObject(hashPathObj); + + string piecesPath = xpath+"/m:verification/m:pieces"; + xmlXPathObjectPtr pieceHashPathObj = xpathEvaluation(piecesPath); + if(pieceHashPathObj) { + xmlNodeSetPtr nodeSet = pieceHashPathObj->nodesetval; + for(int32_t i = 0; i < nodeSet->nodeNr; ++i) { + xmlNodePtr node = nodeSet->nodeTab[i]; + string algo = Util::trim(xmlAttribute(node, "type")); + if(MessageDigestContext::supports(algo)) { + entry->chunkChecksum = getPieceHash(piecesPath+"[@type=\""+algo+"\"]", + entry->getLength()); + break; + } + } + } + xmlXPathFreeObject(pieceHashPathObj); + /* string piecesPath = xpath+"/m:verification/m:pieces"; string sha1PiecesPath = piecesPath+"[@type=\"sha1\"]"; string md5PiecesPath = piecesPath+"[@type=\"md5\"]"; @@ -133,6 +149,7 @@ MetalinkEntryHandle Xml2MetalinkProcessor::getEntry(const string& xpath) { } else if(xpathExists(md5PiecesPath)) { entry->chunkChecksum = getPieceHash(md5PiecesPath, entry->getLength()); } + */ #endif // ENABLE_MESSAGE_DIGEST for(int index = 1; 1; index++) { MetalinkResourceHandle resource(getResource(xpath+"/m:resources/m:url["+Util::itos(index)+"]")); @@ -159,12 +176,8 @@ ChunkChecksumHandle Xml2MetalinkProcessor::getPieceHash(const string& xpath, int64_t checksumLength = STRTOLL(Util::trim(xmlAttribute(node, "length")).c_str()); string algoString = Util::trim(xmlAttribute(node, "type")); xmlXPathFreeObject(result); - MessageDigestContext::DigestAlgo algo; - if(algoString == "sha1") { - algo = DIGEST_ALGO_SHA1; - } else if(algoString == "md5") { - algo = DIGEST_ALGO_MD5; - } else { + + if(!MessageDigestContext::supports(algoString)) { // unknown checksum type return 0; } @@ -178,7 +191,7 @@ ChunkChecksumHandle Xml2MetalinkProcessor::getPieceHash(const string& xpath, } checksums.push_back(pieceHash); } - return new ChunkChecksum(algo, checksums, checksumLength); + return new ChunkChecksum(algoString, checksums, checksumLength); } #endif // ENABLE_MESSAGE_DIGEST diff --git a/src/main.cc b/src/main.cc index 800106d2..2a3e8eab 100644 --- a/src/main.cc +++ b/src/main.cc @@ -71,7 +71,6 @@ extern int optind, opterr, optopt; #ifdef ENABLE_METALINK #include "MetalinkRequestInfo.h" -#include "Xml2MetalinkProcessor.h" #endif #ifdef HAVE_LIBSSL @@ -89,6 +88,9 @@ void showVersion() { cout << PACKAGE << _(" version ") << PACKAGE_VERSION << endl; cout << "**Configuration**" << endl; cout << FeatureConfig::getInstance()->getConfigurationSummary(); +#ifdef ENABLE_MESSAGE_DIGEST + cout << "message digest algorithms: " << MessageDigestContext::getSupportedAlgoString() << endl; +#endif // ENABLE_MESSAGE_DIGEST cout << endl; cout << "Copyright (C) 2006, 2007 Tatsuhiro Tsujikawa" << endl; cout << endl; @@ -109,7 +111,6 @@ void showVersion() { cout << endl; cout << _("Contact Info:") << endl; cout << "Tatsuhiro Tsujikawa <tujikawa at users dot sourceforge dot net>" << endl; - cout << "Ross Smith II <aria2spam at netebb dot com> (Windows port)" << endl; cout << endl; } diff --git a/src/message.h b/src/message.h index cf11733b..4db22946 100644 --- a/src/message.h +++ b/src/message.h @@ -118,7 +118,7 @@ #define MSG_SEEDING_END _("Seeding is over.") #define MSG_SEGMENT_FORWARDING _("CUID#%d cancels segment index=%d. CUID#%d handles it instead.") #define MSG_NO_CHUNK_CHECKSUM _("No chunk to verify.") -#define MSG_GOOD_CHUNK_CHECKSUM _("Good chunk checksum.") +#define MSG_GOOD_CHUNK_CHECKSUM _("Good chunk checksum. hash=%s") #define MSG_LOADING_COOKIE_FAILED _("Failed to load cookies from %s") #define MSG_INCORRECT_NETRC_PERMISSION _(".netrc file %s does not have correct permissions. It should be 600. netrc support disabled.") #define MSG_LOGGING_STARTED _("Logging started.") diff --git a/src/messageDigest.cc b/src/messageDigest.cc new file mode 100644 index 00000000..faa669d2 --- /dev/null +++ b/src/messageDigest.cc @@ -0,0 +1,63 @@ +/* <!-- copyright */ +/* + * aria2 - The high speed download utility + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +/* copyright --> */ +#include "messageDigest.h" + +static MessageDigestContext::DigestAlgoMap::value_type digests[] = { +#ifdef HAVE_LIBSSL + MessageDigestContext::DigestAlgoMap::value_type("md5", EVP_md5()), + MessageDigestContext::DigestAlgoMap::value_type("sha1", EVP_sha1()), +# ifdef HAVE_EVP_SHA256 + MessageDigestContext::DigestAlgoMap::value_type("sha256", EVP_sha256()), +# endif // HAVE_EVP_SHA256 +#elif HAVE_LIBGCRYPT + MessageDigestContext::DigestAlgoMap::value_type("md5", GCRY_MD_MD5), + MessageDigestContext::DigestAlgoMap::value_type("sha1", GCRY_MD_SHA1), + MessageDigestContext::DigestAlgoMap::value_type("sha256", GCRY_MD_SHA256), +#endif // HAVE_LIBGCRYPT +}; + +MessageDigestContext::DigestAlgoMap +MessageDigestContext::digestAlgos(&digests[0], + &digests[sizeof(digests)/sizeof(DigestAlgoMap::value_type)]); + +string MessageDigestContext::digestFinal() +{ + int32_t length = digestLength(algo); + unsigned char* rawMD = new unsigned char[length]; + digestFinal(rawMD); + string rawMDString(&rawMD[0], &rawMD[length]); + delete [] rawMD; + return rawMDString; +} diff --git a/src/messageDigest.h b/src/messageDigest.h index 345a5483..0f309feb 100644 --- a/src/messageDigest.h +++ b/src/messageDigest.h @@ -36,10 +36,8 @@ #define _D_MESSAGE_DIGEST_H_ #include "common.h" - -#ifdef ENABLE_SSL - -#define MAX_MD_LENGTH (16+20) +#include "FatalException.h" +#include <map> #ifdef HAVE_LIBSSL #include <openssl/evp.h> @@ -53,14 +51,11 @@ class MessageDigestContext { public: #ifdef HAVE_LIBSSL typedef const EVP_MD* DigestAlgo; -# define DIGEST_ALGO_MD5 EVP_md5() -# define DIGEST_ALGO_SHA1 EVP_sha1() #endif // HAVE_LIBSSL #ifdef HAVE_LIBGCRYPT typedef int32_t DigestAlgo; -# define DIGEST_ALGO_MD5 GCRY_MD_MD5 -# define DIGEST_ALGO_SHA1 GCRY_MD_SHA1 #endif // HAVE_LIBGCRYPT + typedef map<string, MessageDigestContext::DigestAlgo> DigestAlgoMap; private: #ifdef HAVE_LIBSSL EVP_MD_CTX ctx; @@ -69,17 +64,58 @@ private: gcry_md_hd_t ctx; #endif // HAVE_LIBGCRYPT DigestAlgo algo; + + static DigestAlgoMap digestAlgos; public: - MessageDigestContext(): - algo(DIGEST_ALGO_SHA1) {} - MessageDigestContext(DigestAlgo algo): - algo(algo) {} + MessageDigestContext():algo(getDigestAlgo("sha1")) + {} ~MessageDigestContext() { digestFree(); } + void trySetAlgo(const string& algostring) + { + algo = getDigestAlgo(algostring); + } + + static bool supports(const string& algostring) + { + DigestAlgoMap::const_iterator itr = digestAlgos.find(algostring); + if(itr == digestAlgos.end()) { + return false; + } else { + return true; + } + } + + static DigestAlgo getDigestAlgo(const string& algostring) + { + DigestAlgoMap::const_iterator itr = digestAlgos.find(algostring); + if(itr == digestAlgos.end()) { + throw new FatalException("Digest algorithm %s is not supported.", algostring.c_str()); + } + return (*itr).second; + } + + static string getSupportedAlgoString() + { + string algos; + for(DigestAlgoMap::const_iterator itr = digestAlgos.begin(); + itr != digestAlgos.end(); ++itr) { + algos += (*itr).first+" "; + } + return algos; + } + + static int digestLength(const string& algostring) + { + return digestLength(getDigestAlgo(algostring)); + } + + string digestFinal(); + #if defined(HAVE_OLD_LIBSSL) void digestInit() {EVP_DigestInit(&ctx, algo);} void digestReset() {EVP_DigestInit(&ctx, algo);} @@ -147,5 +183,4 @@ public: #endif // HAVE_LIBGCRYPT }; typedef SharedHandle<MessageDigestContext> MessageDigestContextHandle; -#endif // ENABLE_SSL #endif // _D_MESSAGE_DIGEST_H_ |
