diff --git a/ChangeLog b/ChangeLog index 7ef4875c..5c87d847 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2007-11-12 Tatsuhiro Tsujikawa + + Implemented checksum validation feature(1 checksum for each file) + The validation takes place after the download. + * src/PieceHashCheckIntegrityEntry.{h, cc}: New class. + * src/IteratableChecksumValidator.{h, cc}: Rewritten. + * src/CheckIntegrityCommand.cc: Changed log message. + * src/Metalink2RequestGroup.cc: Set checksum to + SingleFileDownloadContext. + * src/StreamCheckIntegrityEntry.{h, cc}: Now derived from + PieceHashCheckIntegrity class. + * src/BtCheckIntegrityEntry.{h, cc}: Now derived from + PieceHashCheckIntegrity class. + * src/ChecksumCheckIntegrityEntry.{h, cc}: New class. + * src/IteratableValidator.h: New class. + * src/message.h + * src/CheckIntegrityEntry.{h, cc} + * src/IteratableChunkChecksumValidator.{h, cc} + * src/SingleFileDownloadContext.h + * src/DownloadCommand.cc + + --allow-overwrite=true is no longer needed to check file integrity + before download in BitTorrent download. + * src/RequestGroup.cc (getInitialCommand) + + Removed RequestGroup from queue when RequestGroup::getInitialCommand() + throws exception. + * src/RequestGroupMan.cc (getInitialCommands) + 2007-11-11 Tatsuhiro Tsujikawa urlencode the given url inside Request::parseUrl(...) diff --git a/TODO b/TODO index 736265b2..3bd03c54 100644 --- a/TODO +++ b/TODO @@ -56,7 +56,6 @@ FatalException .... Program should abort. -- remaining features to be implemented for 0.12.0 release -* Reimplement ChecksumCommand(validation using 1 checksum for 1 file) * Implement duplicate download checking in Bt * improve --metalink-location field * Piece length conversion when loading file \ No newline at end of file diff --git a/src/AnnounceList.cc b/src/AnnounceList.cc index a7166252..eced1559 100644 --- a/src/AnnounceList.cc +++ b/src/AnnounceList.cc @@ -103,6 +103,7 @@ void AnnounceList::announceSuccess() { } } +// TODO if currentTier reaches tiers.end(), then getAllTierTried() returns true void AnnounceList::announceFailure() { if(currentTrackerInitialized) { currentTracker++; diff --git a/src/BtCheckIntegrityEntry.cc b/src/BtCheckIntegrityEntry.cc index a115b7c6..284ade50 100644 --- a/src/BtCheckIntegrityEntry.cc +++ b/src/BtCheckIntegrityEntry.cc @@ -40,10 +40,9 @@ #include "PieceStorage.h" #include "DownloadEngine.h" #include "FileAllocationMan.h" -#include "DiskAdaptor.h" BtCheckIntegrityEntry::BtCheckIntegrityEntry(RequestGroup* requestGroup): - CheckIntegrityEntry(requestGroup, 0) {} + PieceHashCheckIntegrityEntry(requestGroup, 0) {} BtCheckIntegrityEntry::~BtCheckIntegrityEntry() {} diff --git a/src/BtCheckIntegrityEntry.h b/src/BtCheckIntegrityEntry.h index 18dd589e..977d3ecf 100644 --- a/src/BtCheckIntegrityEntry.h +++ b/src/BtCheckIntegrityEntry.h @@ -35,9 +35,9 @@ #ifndef _D_BT_CHECK_INTEGRITY_ENTRY_H_ #define _D_BT_CHECK_INTEGRITY_ENTRY_H_ -#include "CheckIntegrityEntry.h" +#include "PieceHashCheckIntegrityEntry.h" -class BtCheckIntegrityEntry : public CheckIntegrityEntry { +class BtCheckIntegrityEntry : public PieceHashCheckIntegrityEntry { public: BtCheckIntegrityEntry(RequestGroup* requestGroup); diff --git a/src/CheckIntegrityCommand.cc b/src/CheckIntegrityCommand.cc index 3b652898..d5db23c5 100644 --- a/src/CheckIntegrityCommand.cc +++ b/src/CheckIntegrityCommand.cc @@ -62,12 +62,13 @@ bool CheckIntegrityCommand::executeInternal() } _entry->validateChunk(); if(_entry->finished()) { - _entry->updatePieceStorage(); if(_requestGroup->downloadFinished()) { - logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, _requestGroup->getGID(), + logger->notice(MSG_VERIFICATION_SUCCESSFUL, _requestGroup->getFilePath().c_str()); _e->addCommand(_entry->onDownloadFinished(_e)); } else { + logger->error(MSG_VERIFICATION_FAILED, + _requestGroup->getFilePath().c_str()); _e->addCommand(_entry->onDownloadIncomplete(_e)); } return true; diff --git a/src/CheckIntegrityEntry.cc b/src/CheckIntegrityEntry.cc index 0377b907..43f5a6a1 100644 --- a/src/CheckIntegrityEntry.cc +++ b/src/CheckIntegrityEntry.cc @@ -33,12 +33,9 @@ */ /* copyright --> */ #include "CheckIntegrityEntry.h" -#include "DlAbortEx.h" #include "Command.h" #include "RequestGroup.h" -#include "IteratableChunkChecksumValidator.h" -#include "DownloadContext.h" -#include "DownloadEngine.h" +#include "IteratableValidator.h" CheckIntegrityEntry::CheckIntegrityEntry(RequestGroup* requestGroup, Command* nextCommand): @@ -75,23 +72,3 @@ bool CheckIntegrityEntry::finished() { return _validator->finished(); } - -bool CheckIntegrityEntry::isValidationReady() -{ - DownloadContextHandle dctx = _requestGroup->getDownloadContext(); - return dctx->getPieceHashes().size() > 0 && - dctx->getPieceHashes().size() == (uint32_t)dctx->getNumPieces(); -} - -void CheckIntegrityEntry::initValidator() -{ - IteratableChunkChecksumValidatorHandle validator = - new IteratableChunkChecksumValidator(_requestGroup->getDownloadContext(), - _requestGroup->getPieceStorage()); - _validator = validator; -} - -void CheckIntegrityEntry::updatePieceStorage() -{ - _validator->updatePieceStorage(); -} diff --git a/src/CheckIntegrityEntry.h b/src/CheckIntegrityEntry.h index a6d0bf1c..df22a79e 100644 --- a/src/CheckIntegrityEntry.h +++ b/src/CheckIntegrityEntry.h @@ -37,16 +37,16 @@ #include "RequestGroupEntry.h" -class IteratableChunkChecksumValidator; -extern typedef SharedHandle IteratableChunkChecksumValidatorHandle; +class IteratableValidator; +extern typedef SharedHandle IteratableValidatorHandle; class Command; extern typedef deque Commands; class DownloadEngine; class CheckIntegrityEntry : public RequestGroupEntry, public ProgressAwareEntry { -private: - IteratableChunkChecksumValidatorHandle _validator; +protected: + IteratableValidatorHandle _validator; public: CheckIntegrityEntry(RequestGroup* requestGroup, Command* nextCommand = 0); @@ -56,15 +56,13 @@ public: virtual int64_t getCurrentLength(); + virtual void validateChunk(); + virtual bool finished(); - bool isValidationReady(); + virtual bool isValidationReady() = 0; - void initValidator(); - - void validateChunk(); - - void updatePieceStorage(); + virtual void initValidator() = 0; virtual Commands onDownloadFinished(DownloadEngine* e) = 0; diff --git a/src/ChecksumCommand.cc b/src/ChecksumCheckIntegrityEntry.cc similarity index 51% rename from src/ChecksumCommand.cc rename to src/ChecksumCheckIntegrityEntry.cc index b2ec0964..e521415c 100644 --- a/src/ChecksumCommand.cc +++ b/src/ChecksumCheckIntegrityEntry.cc @@ -32,52 +32,40 @@ * files in the program, then also delete it here. */ /* copyright --> */ -#include "ChecksumCommand.h" -#include "DlAbortEx.h" -#include "message.h" +#include "ChecksumCheckIntegrityEntry.h" +#include "RequestGroup.h" +#include "Command.h" +#include "SingleFileDownloadContext.h" +#include "IteratableChecksumValidator.h" +#include "DownloadEngine.h" +#include "PieceStorage.h" -void ChecksumCommand::initValidator() +ChecksumCheckIntegrityEntry::ChecksumCheckIntegrityEntry(RequestGroup* requestGroup, Command* nextCommand): + CheckIntegrityEntry(requestGroup, nextCommand) {} + +ChecksumCheckIntegrityEntry::~ChecksumCheckIntegrityEntry() {} + +bool ChecksumCheckIntegrityEntry::isValidationReady() { - _validator = new IteratableChecksumValidator(); - // TODO checksum will be held by DownloadContext - _validator->setChecksum(0); - //_validator->setDiskWriter(new DiskAdaptorWriter(_requestGroup->getSegmentMan()->getDiskAdaptor())); - // TODO we should use PieceStorage instead of BitfieldMan - //_validator->setBitfield(_requestGroup->getSegmentMan()->getBitfield()); - if(!_validator->canValidate()) { - // insufficient checksums. - throw new DlAbortEx(EX_INSUFFICIENT_CHECKSUM); - } + SingleFileDownloadContextHandle dctx = _requestGroup->getDownloadContext(); + return !dctx.isNull() && dctx->getChecksum().size() > 0 && + dctx->getChecksumHashAlgo().size() > 0; +} + +void ChecksumCheckIntegrityEntry::initValidator() +{ + _validator = new IteratableChecksumValidator(_requestGroup->getDownloadContext(), + _requestGroup->getPieceStorage()); _validator->init(); } -bool ChecksumCommand::executeInternal() +Commands ChecksumCheckIntegrityEntry::onDownloadFinished(DownloadEngine* e) { - if(_e->isHaltRequested()) { - return true; - } - _validator->validateChunk(); - if(_validator->finished()) { - if(_requestGroup->downloadFinished()) { - logger->notice(MSG_GOOD_CHECKSUM, cuid, _requestGroup->getFilePath().c_str()); - return true; - } else { - logger->error(MSG_BAD_CHECKSUM, cuid, _requestGroup->getFilePath().c_str()); - return true; - } - } else { - _e->commands.push_back(this); - return false; - } - + return Commands(); } -bool ChecksumCommand::handleException(Exception* e) +Commands ChecksumCheckIntegrityEntry::onDownloadIncomplete(DownloadEngine* e) { - logger->error(MSG_FILE_VALIDATION_FAILURE, e, cuid); - logger->error(MSG_DOWNLOAD_NOT_COMPLETE, cuid, _requestGroup->getFilePath().c_str()); - // TODO We need to set bitfield back to the state when validation begun. - // The one of the solution is having a copy of bitfield before settting its - // all bit to 1. If exception is thrown, then assign the copy to the bitfield. - return true; + return Commands(); } + diff --git a/src/ChecksumCommand.h b/src/ChecksumCheckIntegrityEntry.h similarity index 71% rename from src/ChecksumCommand.h rename to src/ChecksumCheckIntegrityEntry.h index f460f1a8..dfe2252e 100644 --- a/src/ChecksumCommand.h +++ b/src/ChecksumCheckIntegrityEntry.h @@ -32,35 +32,25 @@ * files in the program, then also delete it here. */ /* copyright --> */ -#ifndef _D_CHECKSUM_COMMAND_H_ -#define _D_CHECKSUM_COMMAND_H_ +#ifndef _D_CHECKSUM_CHECK_INTEGRITY_ENTRY_H_ +#define _D_CHECKSUM_CHECK_INTEGRITY_ENTRY_H_ -#include "RealtimeCommand.h" -#include "IteratableChecksumValidator.h" +#include "CheckIntegrityEntry.h" -class ChecksumCommand : public RealtimeCommand +class ChecksumCheckIntegrityEntry:public CheckIntegrityEntry { -private: - IteratableChecksumValidatorHandle _validator; public: - ChecksumCommand(int cuid, RequestGroup* requestGroup, DownloadEngine* e): - RealtimeCommand(cuid, requestGroup, e), - _validator(0) - { - _requestGroup->increaseNumCommand(); - } + ChecksumCheckIntegrityEntry(RequestGroup* requestGroup, Command* nextCommand = 0); - virtual ~ChecksumCommand() - { - _requestGroup->decreaseNumCommand(); - } + virtual ~ChecksumCheckIntegrityEntry(); - void initValidator(); + virtual bool isValidationReady(); - virtual bool executeInternal(); + virtual void initValidator(); - virtual bool handleException(Exception* e); + virtual Commands onDownloadFinished(DownloadEngine* e); + + virtual Commands onDownloadIncomplete(DownloadEngine* e); }; - -#endif // _D_CHECKSUM_COMMAND_H_ +#endif // _D_CHECKSUM_CHECK_INTEGRITY_ENTRY_H_ diff --git a/src/DownloadCommand.cc b/src/DownloadCommand.cc index 9252911b..7042a3ed 100644 --- a/src/DownloadCommand.cc +++ b/src/DownloadCommand.cc @@ -48,6 +48,9 @@ #include "PieceStorage.h" #include "Option.h" #include "HttpRequestCommand.h" +#include "ChecksumCheckIntegrityEntry.h" +#include "CheckIntegrityCommand.h" +#include "CUIDCounter.h" #ifdef ENABLE_MESSAGE_DIGEST #include "MessageDigestHelper.h" #endif // ENABLE_MESSAGE_DIGEST @@ -145,17 +148,15 @@ bool DownloadCommand::executeInternal() { bool DownloadCommand::prepareForNextSegment() { if(_requestGroup->downloadFinished()) { - // TODO According to the current plan, checksum is held by DownloadContext. - /* #ifdef ENABLE_MESSAGE_DIGEST - if(!_requestGroup->getChecksum().isNull() && - !_requestGroup->getChecksum()->isEmpty()) { - ChecksumCommand* command = new ChecksumCommand(cuid, _requestGroup, e); - command->initValidator(); + CheckIntegrityEntryHandle entry = new ChecksumCheckIntegrityEntry(_requestGroup); + if(entry->isValidationReady()) { + entry->initValidator(); + CheckIntegrityCommand* command = + new CheckIntegrityCommand(CUIDCounterSingletonHolder::instance()->newID(), _requestGroup, e, entry); e->commands.push_back(command); } #endif // ENABLE_MESSAGE_DIGEST - */ return true; } else { SegmentHandle tempSegment = _segments.front(); diff --git a/src/IteratableChecksumValidator.cc b/src/IteratableChecksumValidator.cc index d99acb16..fc68474b 100644 --- a/src/IteratableChecksumValidator.cc +++ b/src/IteratableChecksumValidator.cc @@ -35,48 +35,59 @@ #include "IteratableChecksumValidator.h" #include "Util.h" #include "message.h" +#include "SingleFileDownloadContext.h" +#include "PieceStorage.h" +#include "messageDigest.h" +#include "LogFactory.h" +#include "Logger.h" +#include "DiskAdaptor.h" +#include "BitfieldMan.h" #define BUFSIZE 16*1024 +IteratableChecksumValidator::IteratableChecksumValidator(const SingleFileDownloadContextHandle& dctx, + const PieceStorageHandle& pieceStorage): + _dctx(dctx), + _pieceStorage(pieceStorage), + _currentOffset(0), + _ctx(0), + _logger(LogFactory::getInstance()) {} + +IteratableChecksumValidator::~IteratableChecksumValidator() {} + void IteratableChecksumValidator::validateChunk() { if(!finished()) { - unsigned char data[BUFSIZE]; - - int32_t size = _diskWriter->readData(data, sizeof(data), _currentOffset); - - _ctx->digestUpdate(data, size); - _currentOffset += sizeof(data); - + int32_t length = _pieceStorage->getDiskAdaptor()->readData(data, sizeof(data), _currentOffset); + _ctx->digestUpdate(data, length); + _currentOffset += length; if(finished()) { - unsigned char* digest = new unsigned char[_ctx->digestLength()]; - try { - _ctx->digestFinal(digest); - if(_checksum->getMessageDigest() != Util::toHex(digest, _ctx->digestLength())) { - _bitfield->clearAllBit(); - } - delete [] digest; - } catch(...) { - delete [] digest; - throw; + string actualChecksum = Util::toHex((const unsigned char*)_ctx->digestFinal().c_str(), _ctx->digestLength()); + if(_dctx->getChecksum() == actualChecksum) { + _pieceStorage->markAllPiecesDone(); + } else { + BitfieldMan bitfield(_dctx->getPieceLength(), _dctx->getTotalLength()); + _pieceStorage->setBitfield(bitfield.getBitfield(), bitfield.getBitfieldLength()); } } } } -bool IteratableChecksumValidator::canValidate() const +bool IteratableChecksumValidator::finished() const { - // We assume file is already opened using DiskWriter::open or openExistingFile. - return !_checksum.isNull() && !_checksum->isEmpty(); + return _currentOffset >= _dctx->getTotalLength(); +} + +int64_t IteratableChecksumValidator::getTotalLength() const +{ + return _dctx->getTotalLength(); } void IteratableChecksumValidator::init() { - _bitfield->setAllBit(); _currentOffset = 0; - _ctx = new MessageDigestContext(); - _ctx->trySetAlgo(_checksum->getAlgo()); + _ctx->trySetAlgo(_dctx->getChecksumHashAlgo()); _ctx->digestInit(); } diff --git a/src/IteratableChecksumValidator.h b/src/IteratableChecksumValidator.h index fd941072..a47eb170 100644 --- a/src/IteratableChecksumValidator.h +++ b/src/IteratableChecksumValidator.h @@ -35,57 +35,47 @@ #ifndef _D_ITERATABLE_CHECKSUM_VALIDATOR_H_ #define _D_ITERATABLE_CHECKSUM_VALIDATOR_H_ -#include "common.h" -#include "BitfieldMan.h" -#include "Checksum.h" -#include "DiskWriter.h" -#include "LogFactory.h" -#include "messageDigest.h" +#include "IteratableValidator.h" -class IteratableChecksumValidator +class SingleFileDownloadContext; +extern typedef SharedHandle SingleFileDownloadContextHandle; +class PieceStorage; +extern typedef SharedHandle PieceStorageHandle; +class Logger; +class MessageDigestContext; +extern typedef SharedHandle MessageDigestContextHandle; + +class IteratableChecksumValidator:public IteratableValidator { private: - DiskWriterHandle _diskWriter; - BitfieldMan* _bitfield; + SingleFileDownloadContextHandle _dctx; + + PieceStorageHandle _pieceStorage; + int64_t _currentOffset; - ChecksumHandle _checksum; - const Logger* logger; + MessageDigestContextHandle _ctx; - string calculateActualChecksum(); + const Logger* _logger; + public: - IteratableChecksumValidator():_diskWriter(0), _bitfield(0), _currentOffset(0), _checksum(0), logger(LogFactory::getInstance()), _ctx(0) {} + IteratableChecksumValidator(const SingleFileDownloadContextHandle& dctx, + const PieceStorageHandle& pieceStorage); - bool canValidate() const; + virtual ~IteratableChecksumValidator(); - void init(); + virtual void init(); - void validateChunk(); + virtual void validateChunk(); - bool finished() const - { - return _currentOffset >= _bitfield->getTotalLength(); - } + virtual bool finished() const; - void setDiskWriter(const DiskWriterHandle& diskWriter) - { - _diskWriter = diskWriter; - } - - void setBitfield(BitfieldMan* bitfield) - { - _bitfield = bitfield; - } - - void setChecksum(const ChecksumHandle& checksum) - { - _checksum = checksum; - } - - int64_t getCurrentOffset() const + virtual int64_t getCurrentOffset() const { return _currentOffset; } + + virtual int64_t getTotalLength() const; }; typedef SharedHandle IteratableChecksumValidatorHandle; diff --git a/src/IteratableChunkChecksumValidator.cc b/src/IteratableChunkChecksumValidator.cc index 2019fe41..725331a0 100644 --- a/src/IteratableChunkChecksumValidator.cc +++ b/src/IteratableChunkChecksumValidator.cc @@ -38,6 +38,23 @@ #include "MessageDigestHelper.h" #include "DiskAdaptor.h" #include "RecoverableException.h" +#include "DownloadContext.h" +#include "PieceStorage.h" +#include "BitfieldMan.h" +#include "LogFactory.h" +#include "Logger.h" + +IteratableChunkChecksumValidator:: +IteratableChunkChecksumValidator(const DownloadContextHandle& dctx, + const PieceStorageHandle& pieceStorage): + _dctx(dctx), + _pieceStorage(pieceStorage), + _bitfield(new BitfieldMan(_dctx->getPieceLength(), _dctx->getTotalLength())), + _currentIndex(0), + _logger(LogFactory::getInstance()) {} + +IteratableChunkChecksumValidator::~IteratableChunkChecksumValidator() {} + void IteratableChunkChecksumValidator::validateChunk() { @@ -63,6 +80,9 @@ void IteratableChunkChecksumValidator::validateChunk() _bitfield->unsetBit(_currentIndex); } _currentIndex++; + if(finished()) { + _pieceStorage->setBitfield(_bitfield->getBitfield(), _bitfield->getBitfieldLength()); + } } } @@ -87,7 +107,17 @@ void IteratableChunkChecksumValidator::init() _currentIndex = 0; } -void IteratableChunkChecksumValidator::updatePieceStorage() +bool IteratableChunkChecksumValidator::finished() const { - _pieceStorage->setBitfield(_bitfield->getBitfield(), _bitfield->getBitfieldLength()); + return _currentIndex >= (uint32_t)_dctx->getNumPieces(); +} + +int64_t IteratableChunkChecksumValidator::getCurrentOffset() const +{ + return (int64_t)_currentIndex*_dctx->getPieceLength(); +} + +int64_t IteratableChunkChecksumValidator::getTotalLength() const +{ + return _dctx->getTotalLength(); } diff --git a/src/IteratableChunkChecksumValidator.h b/src/IteratableChunkChecksumValidator.h index 75c2b2e1..3150f7a3 100644 --- a/src/IteratableChunkChecksumValidator.h +++ b/src/IteratableChunkChecksumValidator.h @@ -35,13 +35,16 @@ #ifndef _D_ITERATABLE_CHUNK_CHECKSUM_VALIDATOR_H_ #define _D_ITERATABLE_CHUNK_CHECKSUM_VALIDATOR_H_ -#include "common.h" -#include "DownloadContext.h" -#include "PieceStorage.h" -#include "BitfieldMan.h" -#include "LogFactory.h" +#include "IteratableValidator.h" -class IteratableChunkChecksumValidator +class DownloadContext; +extern typedef SharedHandle DownloadContextHandle; +class PieceStorage; +extern typedef SharedHandle PieceStorageHandle; +class BitfieldMan; +class Logger; + +class IteratableChunkChecksumValidator:public IteratableValidator { private: DownloadContextHandle _dctx; @@ -53,33 +56,19 @@ private: string calculateActualChecksum(); public: IteratableChunkChecksumValidator(const DownloadContextHandle& dctx, - const PieceStorageHandle& pieceStorage): - _dctx(dctx), - _pieceStorage(pieceStorage), - _bitfield(new BitfieldMan(_dctx->getPieceLength(), _dctx->getTotalLength())), - _currentIndex(0), - _logger(LogFactory::getInstance()) {} + const PieceStorageHandle& pieceStorage); - void init(); + virtual ~IteratableChunkChecksumValidator(); - void validateChunk(); + virtual void init(); - bool finished() const - { - return _currentIndex >= (uint32_t)_dctx->getNumPieces(); - } + virtual void validateChunk(); - int64_t getCurrentOffset() const - { - return ((int64_t)_currentIndex)*_dctx->getPieceLength(); - } + virtual bool finished() const; - int64_t getTotalLength() const - { - return _dctx->getTotalLength(); - } + virtual int64_t getCurrentOffset() const; - void updatePieceStorage(); + virtual int64_t getTotalLength() const; }; typedef SharedHandle IteratableChunkChecksumValidatorHandle; diff --git a/src/IteratableValidator.h b/src/IteratableValidator.h new file mode 100644 index 00000000..b0747e50 --- /dev/null +++ b/src/IteratableValidator.h @@ -0,0 +1,66 @@ +/* */ +#ifndef _D_ITERATABLE_VALIDATOR_H_ +#define _D_ITERATABLE_VALIDATOR_H_ + +#include "common.h" + +/** + * This class provides the interface to validate files. + * + * Be aware to call init() before first validateChunk() call. + * Then, call validateChunk() until finished() returns true. + * The progress information is available using getCurrentOffset() and + * getTotalLength(). + */ +class IteratableValidator +{ +public: + virtual ~IteratableValidator() {} + + virtual void init() = 0; + + virtual void validateChunk() = 0; + + virtual bool finished() const = 0; + + virtual int64_t getCurrentOffset() const = 0; + + virtual int64_t getTotalLength() const = 0; +}; + +typedef SharedHandle IteratableValidatorHandle; + +#endif // _D_ITERATABLE_VALIDATOR_H_ diff --git a/src/Makefile.am b/src/Makefile.am index eb3db74b..f464b5c3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -131,10 +131,12 @@ SRCS = Socket.h\ if ENABLE_MESSAGE_DIGEST SRCS += IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\ IteratableChecksumValidator.cc IteratableChecksumValidator.h\ - ChecksumCommand.cc ChecksumCommand.h\ + IteratableValidator.h\ CheckIntegrityCommand.cc CheckIntegrityCommand.h\ CheckIntegrityEntry.cc CheckIntegrityEntry.h\ + PieceHashCheckIntegrityEntry.cc PieceHashCheckIntegrityEntry.h\ StreamCheckIntegrityEntry.cc StreamCheckIntegrityEntry.h\ + ChecksumCheckIntegrityEntry.cc ChecksumCheckIntegrityEntry.h\ CheckIntegrityMan.cc CheckIntegrityMan.h\ messageDigest.cc messageDigest.h\ MessageDigestHelper.cc MessageDigestHelper.h diff --git a/src/Makefile.in b/src/Makefile.in index 62afcf35..92672dc8 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -42,10 +42,12 @@ bin_PROGRAMS = aria2c$(EXEEXT) # debug_new.cpp @ENABLE_MESSAGE_DIGEST_TRUE@am__append_1 = IteratableChunkChecksumValidator.cc IteratableChunkChecksumValidator.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidator.cc IteratableChecksumValidator.h\ -@ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCommand.cc ChecksumCommand.h\ +@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableValidator.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityCommand.cc CheckIntegrityCommand.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityEntry.cc CheckIntegrityEntry.h\ +@ENABLE_MESSAGE_DIGEST_TRUE@ PieceHashCheckIntegrityEntry.cc PieceHashCheckIntegrityEntry.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ StreamCheckIntegrityEntry.cc StreamCheckIntegrityEntry.h\ +@ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCheckIntegrityEntry.cc ChecksumCheckIntegrityEntry.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityMan.cc CheckIntegrityMan.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.cc messageDigest.h\ @ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelper.cc MessageDigestHelper.h @@ -272,10 +274,12 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ Piece.cc Piece.h IteratableChunkChecksumValidator.cc \ IteratableChunkChecksumValidator.h \ IteratableChecksumValidator.cc IteratableChecksumValidator.h \ - ChecksumCommand.cc ChecksumCommand.h CheckIntegrityCommand.cc \ + IteratableValidator.h CheckIntegrityCommand.cc \ CheckIntegrityCommand.h CheckIntegrityEntry.cc \ - CheckIntegrityEntry.h StreamCheckIntegrityEntry.cc \ - StreamCheckIntegrityEntry.h CheckIntegrityMan.cc \ + CheckIntegrityEntry.h PieceHashCheckIntegrityEntry.cc \ + PieceHashCheckIntegrityEntry.h StreamCheckIntegrityEntry.cc \ + StreamCheckIntegrityEntry.h ChecksumCheckIntegrityEntry.cc \ + ChecksumCheckIntegrityEntry.h CheckIntegrityMan.cc \ CheckIntegrityMan.h messageDigest.cc messageDigest.h \ MessageDigestHelper.cc MessageDigestHelper.h MetaEntry.h \ Data.cc Data.h Dictionary.cc Dictionary.h List.cc List.h \ @@ -352,10 +356,11 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ timegm.h @ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = IteratableChunkChecksumValidator.$(OBJEXT) \ @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@ PieceHashCheckIntegrityEntry.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ StreamCheckIntegrityEntry.$(OBJEXT) \ +@ENABLE_MESSAGE_DIGEST_TRUE@ ChecksumCheckIntegrityEntry.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ CheckIntegrityMan.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ messageDigest.$(OBJEXT) \ @ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelper.$(OBJEXT) @@ -893,7 +898,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CheckIntegrityCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CheckIntegrityEntry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CheckIntegrityMan.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChecksumCommand.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChecksumCheckIntegrityEntry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkedEncoding.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Command.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompactPeerListProcessor.Po@am__quote@ @@ -988,6 +993,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerMessageUtil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerReceiveHandshakeCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Piece.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PieceHashCheckIntegrityEntry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PiecedSegment.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Platform.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PostDownloadHandler.Po@am__quote@ diff --git a/src/Metalink2RequestGroup.cc b/src/Metalink2RequestGroup.cc index 81db02ce..e62e5e38 100644 --- a/src/Metalink2RequestGroup.cc +++ b/src/Metalink2RequestGroup.cc @@ -162,12 +162,15 @@ RequestGroups Metalink2RequestGroup::generate(const string& metalinkFile) "", entry->file->getPath()); dctx->setDir(_option->get(PREF_DIR)); - if(!entry->chunkChecksum.isNull()) { + if(entry->chunkChecksum.isNull()) { + if(!entry->checksum.isNull()) { + dctx->setChecksum(entry->checksum->getMessageDigest()); + dctx->setChecksumHashAlgo(entry->checksum->getAlgo()); + } + } else { dctx->setPieceHashes(entry->chunkChecksum->getChecksums()); dctx->setPieceHashAlgo(entry->chunkChecksum->getAlgo()); } - // TODO set checksum here to DownloadContext - // * hash and hash algorithm rg->setDownloadContext(dctx); rg->setHintTotalLength(entry->getLength()); diff --git a/src/PieceHashCheckIntegrityEntry.cc b/src/PieceHashCheckIntegrityEntry.cc new file mode 100644 index 00000000..dcc45565 --- /dev/null +++ b/src/PieceHashCheckIntegrityEntry.cc @@ -0,0 +1,61 @@ +/* */ +#include "PieceHashCheckIntegrityEntry.h" +#include "Command.h" +#include "RequestGroup.h" +#include "IteratableChunkChecksumValidator.h" +#include "DownloadContext.h" +#include "PieceStorage.h" + +PieceHashCheckIntegrityEntry::PieceHashCheckIntegrityEntry(RequestGroup* requestGroup, + Command* nextCommand): + CheckIntegrityEntry(requestGroup, nextCommand) {} + +PieceHashCheckIntegrityEntry::~PieceHashCheckIntegrityEntry() {} + +bool PieceHashCheckIntegrityEntry::isValidationReady() +{ + DownloadContextHandle dctx = _requestGroup->getDownloadContext(); + return dctx->getPieceHashes().size() > 0 && + dctx->getPieceHashes().size() == (uint32_t)dctx->getNumPieces(); +} + +void PieceHashCheckIntegrityEntry::initValidator() +{ + IteratableChunkChecksumValidatorHandle validator = + new IteratableChunkChecksumValidator(_requestGroup->getDownloadContext(), + _requestGroup->getPieceStorage()); + _validator = validator; +} diff --git a/src/PieceHashCheckIntegrityEntry.h b/src/PieceHashCheckIntegrityEntry.h new file mode 100644 index 00000000..44313cc4 --- /dev/null +++ b/src/PieceHashCheckIntegrityEntry.h @@ -0,0 +1,52 @@ +/* */ +#ifndef _D_PIECE_HASH_CHECK_INTEGRITY_ENTRY_H_ +#define _D_PIECE_HASH_CHECK_INTEGRITY_ENTRY_H_ + +#include "CheckIntegrityEntry.h" + +class PieceHashCheckIntegrityEntry : public CheckIntegrityEntry +{ +public: + PieceHashCheckIntegrityEntry(RequestGroup* requestGroup, Command* nextCommand = 0); + + virtual ~PieceHashCheckIntegrityEntry(); + + virtual bool isValidationReady(); + + virtual void initValidator(); +}; + +#endif // _D_PIECE_HASH_CHECK_INTEGRITY_ENTRY_H_ diff --git a/src/RequestGroup.cc b/src/RequestGroup.cc index 06546d7e..03bb8cea 100644 --- a/src/RequestGroup.cc +++ b/src/RequestGroup.cc @@ -190,7 +190,8 @@ Commands RequestGroup::createInitialCommand(DownloadEngine* e) _pieceStorage->getDiskAdaptor()->openFile(); } else { if(_pieceStorage->getDiskAdaptor()->fileExists()) { - if(_option->get(PREF_ALLOW_OVERWRITE) != V_TRUE) { + if(_option->get(PREF_CHECK_INTEGRITY) != V_TRUE && + _option->get(PREF_ALLOW_OVERWRITE) != V_TRUE) { _logger->error(MSG_FILE_ALREADY_EXISTS, getFilePath().c_str(), progressInfoFile->getFilename().c_str()); diff --git a/src/RequestGroupMan.cc b/src/RequestGroupMan.cc index 1e2893b0..a6deadbd 100644 --- a/src/RequestGroupMan.cc +++ b/src/RequestGroupMan.cc @@ -178,6 +178,7 @@ Commands RequestGroupMan::getInitialCommands(DownloadEngine* e) } catch(RecoverableException* e) { _logger->error(EX_EXCEPTION_CAUGHT, e); delete e; + itr = _requestGroups.erase(itr); } } else { _reservedGroups.push_front((*itr)); diff --git a/src/SingleFileDownloadContext.h b/src/SingleFileDownloadContext.h index 43a9d403..b0f19a6e 100644 --- a/src/SingleFileDownloadContext.h +++ b/src/SingleFileDownloadContext.h @@ -56,6 +56,9 @@ private: Strings _pieceHashes; string _pieceHashAlgo; + string _checksum; + string _checksumHashAlgo; + void updateFileEntry() { if(_ufilename != "") { @@ -136,11 +139,31 @@ public: return _pieceHashAlgo; } + const string& getChecksumHashAlgo() const + { + return _checksumHashAlgo; + } + + const string& getChecksum() const + { + return _checksum; + } + void setPieceHashes(const Strings& pieceHashes) { _pieceHashes = pieceHashes; } + void setChecksumHashAlgo(const string& algo) + { + _checksumHashAlgo = algo; + } + + void setChecksum(const string& checksum) + { + _checksum = checksum; + } + void setFilename(const string& filename) { _filename = filename; diff --git a/src/StreamCheckIntegrityEntry.cc b/src/StreamCheckIntegrityEntry.cc index b745d8e7..6760f99a 100644 --- a/src/StreamCheckIntegrityEntry.cc +++ b/src/StreamCheckIntegrityEntry.cc @@ -40,13 +40,12 @@ #include "CUIDCounter.h" #include "PieceStorage.h" #include "FileAllocationMan.h" -#include "DiskAdaptor.h" StreamCheckIntegrityEntry::StreamCheckIntegrityEntry(const RequestHandle& currentRequest, RequestGroup* requestGroup, Command* nextCommand): - CheckIntegrityEntry(requestGroup, nextCommand), - _currentRequest(currentRequest) + PieceHashCheckIntegrityEntry(requestGroup, nextCommand), + _currentRequest(currentRequest) {} StreamCheckIntegrityEntry::~StreamCheckIntegrityEntry() {} diff --git a/src/StreamCheckIntegrityEntry.h b/src/StreamCheckIntegrityEntry.h index 7608b239..55ee06d3 100644 --- a/src/StreamCheckIntegrityEntry.h +++ b/src/StreamCheckIntegrityEntry.h @@ -35,17 +35,13 @@ #ifndef _D_STREAM_CHECK_INTEGRITY_ENTRY_H_ #define _D_STREAM_CHECK_INTEGRITY_ENTRY_H_ -#include "CheckIntegrityEntry.h" +#include "PieceHashCheckIntegrityEntry.h" #include "TimeA2.h" class Request; typedef SharedHandle RequestHandle; -class Command; -typedef deque Commands; -class RequestGroup; -class DownloadEngine; -class StreamCheckIntegrityEntry:public CheckIntegrityEntry +class StreamCheckIntegrityEntry:public PieceHashCheckIntegrityEntry { private: RequestHandle _currentRequest; diff --git a/src/UrlRequestInfo.cc b/src/UrlRequestInfo.cc deleted file mode 100644 index 20707a2b..00000000 --- a/src/UrlRequestInfo.cc +++ /dev/null @@ -1,225 +0,0 @@ -/* */ -#include "UrlRequestInfo.h" -#include "TorrentRequestInfo.h" -#include "MetalinkRequestInfo.h" -#include "prefs.h" -#include "DownloadEngineFactory.h" -#include "RecoverableException.h" -#include "FatalException.h" -#include "message.h" -#include "RequestFactory.h" -#include "GlowFileAllocator.h" -#include "File.h" -#include "DefaultDiskWriter.h" -#include "DlAbortEx.h" -#include "DNSCache.h" - -std::ostream& operator<<(std::ostream& o, const HeadResult& hr) { - o << "filename = " << hr.filename << ", " << "totalLength = " << hr.totalLength; - return o; -} - -extern volatile sig_atomic_t haltRequested; - -void UrlRequestInfo::adjustRequestSize(Requests& requests, - Requests& reserved, - int maxConnections) const -{ - if(maxConnections > 0 && (int)requests.size() > maxConnections) { - copy(requests.begin()+maxConnections, requests.end(), - back_inserter(reserved)); - //insert_iterator(reserved, reserved.end())); - requests.erase(requests.begin()+maxConnections, requests.end()); - } -} - -RequestInfo* UrlRequestInfo::createNextRequestInfo() const -{ -#ifdef ENABLE_BITTORRENT - if(op->getAsBool(PREF_FOLLOW_TORRENT) && - Util::endsWith(fileInfo.filename, ".torrent")) { - return new TorrentRequestInfo(fileInfo.filename, op); - } else -#endif // ENABLE_BITTORRENT -#ifdef ENABLE_METALINK - if(op->getAsBool(PREF_FOLLOW_METALINK) && - Util::endsWith(fileInfo.filename, ".metalink")) { - return new MetalinkRequestInfo(fileInfo.filename, op); - } else -#endif // ENABLE_METALINK - { - return 0; - } -} - -void handler(int signal) { - haltRequested = true; -} -/* -class CreateRequest { -private: - Requests* requestsPtr; - string referer; - int split; - string method; -public: - CreateRequest(Requests* requestsPtr, - const string& referer, - int split, - const string& method = Request::METHOD_GET) - :requestsPtr(requestsPtr), - referer(referer), - split(split), - method(method) - {} - - void operator()(const string& url) { - for(int s = 1; s <= split; s++) { - RequestHandle req = RequestFactorySingletonHolder::instance()->createRequest(); - req->setReferer(referer); - req->setMethod(method); - if(req->setUrl(url)) { - requestsPtr->push_back(req); - } else { - fprintf(stderr, _("Unrecognized URL or unsupported protocol: %s\n"), - req->getUrl().c_str()); - } - } - } -}; -*/ -void UrlRequestInfo::printUrls(const Strings& urls) const { - for(Strings::const_iterator itr = urls.begin(); itr != urls.end(); itr++) { - logger->info("Adding URL: %s", itr->c_str()); - } -} -/* -HeadResultHandle UrlRequestInfo::getHeadResult() { - Requests requests; - for_each(urls.begin(), urls.end(), - CreateRequest(&requests, - op->get(PREF_REFERER), - 1, - Request::METHOD_HEAD)); - if(requests.size() == 0) { - return 0; - } - Requests reserved(requests.begin()+1, requests.end()); - requests.erase(requests.begin()+1, requests.end()); - - SharedHandle e(DownloadEngineFactory::newConsoleEngine(op, requests, reserved)); - - HeadResultHandle hr = 0; - - e->run(); - hr = new HeadResult(); - hr->filename = e->segmentMan->filename; - hr->totalLength = e->segmentMan->totalSize; - - return hr; -} -*/ - -RequestInfos UrlRequestInfo::execute() { - { - DNSCacheHandle dnsCache = new SimpleDNSCache(); - DNSCacheSingletonHolder::instance(dnsCache); - } - - RequestInfo* next = 0; - - try { - RequestGroups requestGroups; - - Strings urls; - urls.push_back("http://localhost/~tujikawa/linux-2.6.6.tar.bz2"); - RequestGroupHandle rg1 = new RequestGroup(urls, op); - - Strings urls2; - urls2.push_back("http://localhost/~tujikawa/linux-2.6.19.1.tar.bz2"); - RequestGroupHandle rg2 = new RequestGroup(urls2, op); - - requestGroups.push_back(rg1); - requestGroups.push_back(rg2); - - SharedHandle e(DownloadEngineFactory::newConsoleEngine(op, requestGroups)); - - - Strings reservedUrls1; - reservedUrls1.push_back("http://localhost/~tujikawa/linux-2.6.1.tar.bz2"); - - RequestGroupHandle rrg1 = new RequestGroup(reservedUrls1, op); - - e->_requestGroupMan->addReservedGroup(rrg1); - - e->fillCommand(); - - - - - // The number of simultaneous download is specified by PREF_MAX_CONCURRENT_DOWNLOADS. - // The remaining urls are queued into FillRequestGroupCommand. - // It observes the number of simultaneous downloads and if it is under - // the limit, it adds RequestGroup object from its queue to DownloadEngine. - // This is done every 1 second. At the same time, it removes finished/error - // RequestGroup from DownloadEngine. - - Util::setGlobalSignalHandler(SIGINT, handler, 0); - Util::setGlobalSignalHandler(SIGTERM, handler, 0); - - e->run(); - - if(e->_requestGroupMan->downloadFinished()) { - next = createNextRequestInfo(); - } else { - e->_requestGroupMan->save(); - e->_requestGroupMan->closeFile(); - printDownloadAbortMessage(); - } - } catch(RecoverableException *ex) { - logger->error("Exception caught", ex); - delete ex; - fail = true; - } - RequestInfos nextReqInfos; - if(next) { - nextReqInfos.push_front(next); - } - Util::setGlobalSignalHandler(SIGINT, SIG_DFL, 0); - Util::setGlobalSignalHandler(SIGTERM, SIG_DFL, 0); - - return nextReqInfos; -} diff --git a/src/UrlRequestInfo.h b/src/UrlRequestInfo.h deleted file mode 100644 index 210e9b51..00000000 --- a/src/UrlRequestInfo.h +++ /dev/null @@ -1,117 +0,0 @@ -/* */ -#ifndef _D_URL_REQUEST_INFO_H_ -#define _D_URL_REQUEST_INFO_H_ - -#include "RequestInfo.h" - -class HeadResult { -public: - string filename; - int64_t totalLength; -public: - HeadResult():totalLength(0) {} -}; - -std::ostream& operator<<(std::ostream& o, const HeadResult& hr); - -typedef SharedHandle HeadResultHandle; - -class UrlRequestInfo : public RequestInfo { -private: - Strings urls; - int32_t maxConnections; - string _filename; - int64_t _totalLength; -#ifdef ENABLE_MESSAGE_DIGEST - MessageDigestContext::DigestAlgo digestAlgo; - int32_t chunkChecksumLength; - Strings chunkChecksums; -#endif // ENABLE_MESSAGE_DIGEST - - RequestInfo* createNextRequestInfo() const; - void adjustRequestSize(Requests& requests, - Requests& reserved, - int32_t maxConnections) const; - void printUrls(const Strings& urls) const; - HeadResultHandle getHeadResult(); -public: - UrlRequestInfo(const Strings& urls, int32_t maxConnections, Option* op): - RequestInfo(op), - urls(urls), - maxConnections(maxConnections), - _totalLength(0) -#ifdef ENABLE_MESSAGE_DIGEST - , - digestAlgo(DIGEST_ALGO_SHA1), - chunkChecksumLength(0) -#endif // ENABLE_MESSAGE_DIGEST - {} - - virtual ~UrlRequestInfo() {} - - virtual RequestInfos execute(); - -#ifdef ENABLE_MESSAGE_DIGEST - void setDigestAlgo(const MessageDigestContext::DigestAlgo& algo) { - this->digestAlgo = algo; - } -#endif // ENABLE_MESSAGE_DIGEST - -#ifdef ENABLE_MESSAGE_DIGEST - void setChunkChecksumLength(int32_t chunkChecksumLength) { - this->chunkChecksumLength = chunkChecksumLength; - } -#endif // ENABLE_MESSAGE_DIGEST - -#ifdef ENABLE_MESSAGE_DIGEST - void setChunkChecksums(const Strings& chunkChecksums) { - this->chunkChecksums = chunkChecksums; - } -#endif // ENABLE_MESSAGE_DIGEST - - void setTotalLength(int64_t totalLength) - { - _totalLength = totalLength; - } - - void setFilename(const string& filename) - { - _filename = filename; - } -}; - -typedef SharedHandle UrlRequestInfoHandle; -#endif // _D_URL_REQUEST_INFO_H_ diff --git a/src/message.h b/src/message.h index 48098628..36b46a2f 100644 --- a/src/message.h +++ b/src/message.h @@ -124,6 +124,8 @@ #define MSG_LOGGING_STARTED _("Logging started.") #define MSG_URI_REQUIRED _("Specify at least one URL.") #define MSG_DAEMON_FAILED _("daemon failed.") +#define MSG_VERIFICATION_SUCCESSFUL _("Verification finished successfully. file=%s") +#define MSG_VERIFICATION_FAILED _("Checksum error detected. file=%s") #define EX_TIME_OUT _("Timeout.") #define EX_INVALID_CHUNK_SIZE _("Invalid chunk size.") diff --git a/test/IteratableChecksumValidatorTest.cc b/test/IteratableChecksumValidatorTest.cc index 7479c9f9..312e2d6c 100644 --- a/test/IteratableChecksumValidatorTest.cc +++ b/test/IteratableChecksumValidatorTest.cc @@ -1,5 +1,8 @@ #include "IteratableChecksumValidator.h" -#include "DefaultDiskWriter.h" +#include "SingleFileDownloadContext.h" +#include "DefaultPieceStorage.h" +#include "Option.h" +#include "DiskAdaptor.h" #include using namespace std; @@ -8,7 +11,7 @@ class IteratableChecksumValidatorTest:public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(IteratableChecksumValidatorTest); CPPUNIT_TEST(testValidate); - CPPUNIT_TEST(testValidate2); + CPPUNIT_TEST(testValidate_fail); CPPUNIT_TEST_SUITE_END(); private: @@ -17,103 +20,47 @@ public: } void testValidate(); - void testValidate2(); + void testValidate_fail(); }; CPPUNIT_TEST_SUITE_REGISTRATION( IteratableChecksumValidatorTest ); void IteratableChecksumValidatorTest::testValidate() { - BitfieldMan bitfieldMan(100, 250); - bitfieldMan.setAllBit(); - - ChecksumHandle checksum = new Checksum("sha1", - "898a81b8e0181280ae2ee1b81e269196d91e869a"); - - DefaultDiskWriterHandle diskWriter = new DefaultDiskWriter(); - diskWriter->openExistingFile("chunkChecksumTestFile250.txt"); - - IteratableChecksumValidator validator; - validator.setDiskWriter(diskWriter); - validator.setBitfield(&bitfieldMan); - validator.setChecksum(checksum); + Option option; + SingleFileDownloadContextHandle dctx = + new SingleFileDownloadContext(100, 250, "chunkChecksumTestFile250.txt"); + dctx->setChecksum("898a81b8e0181280ae2ee1b81e269196d91e869a"); + dctx->setChecksumHashAlgo("sha1"); + DefaultPieceStorageHandle ps = new DefaultPieceStorage(dctx, &option); + ps->initStorage(); + ps->getDiskAdaptor()->openFile(); + IteratableChecksumValidator validator(dctx, ps); validator.init(); while(!validator.finished()) { validator.validateChunk(); } - CPPUNIT_ASSERT(bitfieldMan.isAllBitSet()); + + CPPUNIT_ASSERT(ps->downloadFinished()); } -void IteratableChecksumValidatorTest::testValidate2() { - BitfieldMan bitfieldMan(100, 250); - bitfieldMan.setAllBit(); - - ChecksumHandle checksum = new Checksum("sha1", "ffffffffffffffffffffffffffffffffffffffff"); - - DefaultDiskWriterHandle diskWriter = new DefaultDiskWriter(); - diskWriter->openExistingFile("chunkChecksumTestFile250.txt"); - - IteratableChecksumValidator validator; - validator.setDiskWriter(diskWriter); - validator.setBitfield(&bitfieldMan); - validator.setChecksum(checksum); +void IteratableChecksumValidatorTest::testValidate_fail() { + Option option; + SingleFileDownloadContextHandle dctx = + new SingleFileDownloadContext(100, 250, "chunkChecksumTestFile250.txt"); + dctx->setChecksum(string(40, '0')); // set wrong checksum + dctx->setChecksumHashAlgo("sha1"); + DefaultPieceStorageHandle ps = new DefaultPieceStorage(dctx, &option); + ps->initStorage(); + ps->getDiskAdaptor()->openFile(); + IteratableChecksumValidator validator(dctx, ps); validator.init(); + while(!validator.finished()) { validator.validateChunk(); } - CPPUNIT_ASSERT(!bitfieldMan.isAllBitSet()); + + CPPUNIT_ASSERT(!ps->downloadFinished()); } -/* -void IteratableChecksumValidatorTest::testValidate3() { - BitfieldMan bitfieldMan(50, 250); - bitfieldMan.setAllBit(); - Strings checksums; - checksums.push_back("898a81b8e0181280ae2ee1b81e269196d91e869a"); - - DefaultDiskWriterHandle diskWriter = new DefaultDiskWriter(); - diskWriter->openExistingFile("chunkChecksumTestFile250.txt"); - - IteratableChecksumValidator validator; - validator.setDiskWriter(diskWriter); - - validator.validate(&bitfieldMan, checksums, 250); - - CPPUNIT_ASSERT(bitfieldMan.isAllBitSet()); - - checksums[0] = "ffffffffffffffffffffffffffffffffffffffff"; - - validator.validate(&bitfieldMan, checksums, 250); - - CPPUNIT_ASSERT(!bitfieldMan.isBitSet(0)); - CPPUNIT_ASSERT(!bitfieldMan.isBitSet(1)); - CPPUNIT_ASSERT(!bitfieldMan.isBitSet(2)); - CPPUNIT_ASSERT(!bitfieldMan.isBitSet(3)); - CPPUNIT_ASSERT(!bitfieldMan.isBitSet(4)); -} - -void IteratableChecksumValidatorTest::testValidate4() { - BitfieldMan bitfieldMan(70, 250); - bitfieldMan.setAllBit(); - Strings checksums(&csArray[0], &csArray[3]); - - DefaultDiskWriterHandle diskWriter = new DefaultDiskWriter(); - diskWriter->openExistingFile("chunkChecksumTestFile250.txt"); - - IteratableChecksumValidator validator; - validator.setDiskWriter(diskWriter); - - validator.validate(&bitfieldMan, checksums, 100); - - CPPUNIT_ASSERT(bitfieldMan.isAllBitSet()); - - checksums[1] = "ffffffffffffffffffffffffffffffffffffffff"; - validator.validate(&bitfieldMan, checksums, 100); - - CPPUNIT_ASSERT(bitfieldMan.isBitSet(0)); - CPPUNIT_ASSERT(!bitfieldMan.isBitSet(1)); - CPPUNIT_ASSERT(!bitfieldMan.isBitSet(2)); - CPPUNIT_ASSERT(bitfieldMan.isBitSet(3)); -} -*/ diff --git a/test/IteratableChunkChecksumValidatorTest.cc b/test/IteratableChunkChecksumValidatorTest.cc index 5e54795f..340494d2 100644 --- a/test/IteratableChunkChecksumValidatorTest.cc +++ b/test/IteratableChunkChecksumValidatorTest.cc @@ -47,7 +47,6 @@ void IteratableChunkChecksumValidatorTest::testValidate() { CPPUNIT_ASSERT(!validator.finished()); validator.validateChunk(); CPPUNIT_ASSERT(validator.finished()); - validator.updatePieceStorage(); CPPUNIT_ASSERT(ps->downloadFinished()); // make the test fail @@ -60,7 +59,6 @@ void IteratableChunkChecksumValidatorTest::testValidate() { while(!validator.finished()) { validator.validateChunk(); } - validator.updatePieceStorage(); CPPUNIT_ASSERT(ps->hasPiece(0)); CPPUNIT_ASSERT(!ps->hasPiece(1)); CPPUNIT_ASSERT(ps->hasPiece(2)); diff --git a/test/Makefile.am b/test/Makefile.am index 8c21447e..1476ae5c 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -46,7 +46,8 @@ aria2c_SOURCES = AllTest.cc\ if ENABLE_MESSAGE_DIGEST aria2c_SOURCES += MessageDigestHelperTest.cc\ - IteratableChunkChecksumValidatorTest.cc + IteratableChunkChecksumValidatorTest.cc\ + IteratableChecksumValidatorTest.cc endif # ENABLE_MESSAGE_DIGEST if ENABLE_BITTORRENT diff --git a/test/Makefile.in b/test/Makefile.in index 961c76a8..62880fc9 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -38,7 +38,8 @@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = $(am__EXEEXT_1) @ENABLE_MESSAGE_DIGEST_TRUE@am__append_1 = MessageDigestHelperTest.cc\ -@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidatorTest.cc +@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidatorTest.cc\ +@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidatorTest.cc @ENABLE_BITTORRENT_TRUE@am__append_2 = BtAllowedFastMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ BtBitfieldMessageTest.cc\ @@ -132,16 +133,17 @@ am__aria2c_SOURCES_DIST = AllTest.cc a2functionalTest.cc \ DefaultDiskWriterTest.cc FeatureConfigTest.cc SpeedCalcTest.cc \ FixedNumberRandomizer.h MessageDigestHelperTest.cc \ IteratableChunkChecksumValidatorTest.cc \ - BtAllowedFastMessageTest.cc BtBitfieldMessageTest.cc \ - BtCancelMessageTest.cc BtChokeMessageTest.cc \ - BtHandshakeMessageTest.cc BtHaveAllMessageTest.cc \ - BtHaveMessageTest.cc BtHaveNoneMessageTest.cc \ - BtInterestedMessageTest.cc BtKeepAliveMessageTest.cc \ - BtNotInterestedMessageTest.cc BtPieceMessageTest.cc \ - BtPortMessageTest.cc BtRejectMessageTest.cc \ - BtRequestMessageTest.cc BtSuggestPieceMessageTest.cc \ - BtUnchokeMessageTest.cc DefaultBtAnnounceTest.cc \ - DefaultBtContextTest.cc DefaultBtMessageDispatcherTest.cc \ + IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \ + BtBitfieldMessageTest.cc BtCancelMessageTest.cc \ + BtChokeMessageTest.cc BtHandshakeMessageTest.cc \ + BtHaveAllMessageTest.cc BtHaveMessageTest.cc \ + BtHaveNoneMessageTest.cc BtInterestedMessageTest.cc \ + BtKeepAliveMessageTest.cc BtNotInterestedMessageTest.cc \ + BtPieceMessageTest.cc BtPortMessageTest.cc \ + BtRejectMessageTest.cc BtRequestMessageTest.cc \ + BtSuggestPieceMessageTest.cc BtUnchokeMessageTest.cc \ + DefaultBtAnnounceTest.cc DefaultBtContextTest.cc \ + DefaultBtMessageDispatcherTest.cc \ DefaultBtRequestFactoryTest.cc MockBtMessage.h \ MockBtMessageDispatcher.h MockBtMessageFactory.h \ ShaVisitorTest.cc DefaultPeerListProcessorTest.cc \ @@ -157,7 +159,8 @@ am__aria2c_SOURCES_DIST = AllTest.cc a2functionalTest.cc \ MetalinkPostDownloadHandlerTest.cc MetalinkHelperTest.cc @ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = \ @ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelperTest.$(OBJEXT) \ -@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidatorTest.$(OBJEXT) +@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidatorTest.$(OBJEXT) \ +@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidatorTest.$(OBJEXT) @ENABLE_BITTORRENT_TRUE@am__objects_2 = \ @ENABLE_BITTORRENT_TRUE@ BtAllowedFastMessageTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtBitfieldMessageTest.$(OBJEXT) \ @@ -550,6 +553,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpHeaderTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpRequestTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpResponseTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChecksumValidatorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChunkChecksumValidatorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ListTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MessageDigestHelperTest.Po@am__quote@ diff --git a/test/Metalink2RequestGroupTest.cc b/test/Metalink2RequestGroupTest.cc index 724f6151..a5ad3ccc 100644 --- a/test/Metalink2RequestGroupTest.cc +++ b/test/Metalink2RequestGroupTest.cc @@ -39,6 +39,9 @@ void Metalink2RequestGroupTest::testGenerate() SingleFileDownloadContextHandle dctx = rg->getDownloadContext(); CPPUNIT_ASSERT(!dctx.isNull()); CPPUNIT_ASSERT_EQUAL((int64_t)0, dctx->getTotalLength()); + CPPUNIT_ASSERT_EQUAL(string("sha1"), dctx->getChecksumHashAlgo()); + CPPUNIT_ASSERT_EQUAL(string("a96cf3f0266b91d87d5124cf94326422800b627d"), + dctx->getChecksum()); } // second file { @@ -50,6 +53,8 @@ void Metalink2RequestGroupTest::testGenerate() CPPUNIT_ASSERT_EQUAL(string("sha1"), dctx->getPieceHashAlgo()); CPPUNIT_ASSERT_EQUAL((size_t)2, dctx->getPieceHashes().size()); CPPUNIT_ASSERT_EQUAL((int32_t)262144, dctx->getPieceLength()); + CPPUNIT_ASSERT_EQUAL(string(""), dctx->getChecksumHashAlgo()); + CPPUNIT_ASSERT_EQUAL(string(""), dctx->getChecksum()); } // fifth file <- downloading .torrent file