From e85f9ccfd64b52419d47bd8f76c4b08eb2e0c422 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 8 Aug 2007 14:40:11 +0000 Subject: [PATCH] 2007-08-08 Tatsuhiro Tsujikawa MessageDigestHelper is introduced in order to simplify the use of message digest. Removed repeated code. The message digest algorithm is now specified by string, like "sha1", "md5". * src/messageDigest.{h, cc} * src/MessageDigestHelper.{h, cc}: New class. * src/DefaultPieceStorage.cc * src/DefaultBtContext.{h, cc} (computeFastSet): New function. (setInfoHash): Added for unit testing. (setNumPieces): Added for unit testing. * src/DefaultBtInteractive.cc * src/BtPieceMessage.cc * src/Peer.cc * src/Checksum.h * src/message.h * src/IteratableChecksumValidator.h * src/ChunkChecksumValidator.{h, cc}: Use IteratableChecksumValidator inside it. * src/SegmentMan.{h, cc} (checkIntegrity): Removed. * src/IteratableChunkChecksumValidator.{h, cc} * src/Util.h (sha1Sum): Removed. (simpleMessageDigest): Removed. (fileChecksum): Removed. (computeFastSet): Removed. * src/ShaVisitor.cc * src/ChunkChecksum.h * src/DownloadCommand.cc Removed messageDigest virtual functions. * src/MultiDiskAdaptor.{h, cc} * src/DiskAdaptor.h * src/ByteArrayDiskWriter.h * src/DiskWriter.h * src/DiskAdaptorWriter.h * src/AbstractSingleDiskAdaptor.{h, cc} * src/AbstractDiskWriter.{h, cc} Fixed comilation error when message digest is disabled. * src/MetalinkEntry.{h, cc} * src/MetalinkRequestInfo.cc Removed srandom and random. * src/SimpleRandomizer.h Added size() virtual function to DiskAdaptor * src/MultiDiskAdaptor.h Fixed the bug that causes that files are not opened correctly in multi-file torrent. * src/TorrentRequestInfo.cc * src/MultiDiskAdaptor.cc Added SHA256 support * src/messageDigest.cc * src/Xml2MetalinkProcessor.cc Show supported message digest algorithms * src/main.cc Updated contact info. * src/main.cc --- AUTHORS | 1 + ChangeLog | 71 +++++++ config.h.in | 9 + configure | 199 ++++++++++++++++++- m4/openssl.m4 | 11 +- src/AbstractDiskWriter.cc | 31 +-- src/AbstractDiskWriter.h | 5 - src/AbstractSingleDiskAdaptor.cc | 4 - src/AbstractSingleDiskAdaptor.h | 8 +- src/BtContext.h | 3 + src/BtPieceMessage.cc | 7 +- src/ByteArrayDiskWriter.h | 8 - src/Checksum.h | 34 ++-- src/ChunkChecksum.h | 6 +- src/ChunkChecksumValidator.cc | 78 +------- src/ChunkChecksumValidator.h | 44 +--- src/DefaultBtContext.cc | 38 ++++ src/DefaultBtContext.h | 14 ++ src/DefaultBtInteractive.cc | 6 +- src/DefaultPieceStorage.cc | 15 +- src/DiskAdaptor.h | 10 +- src/DiskAdaptorWriter.h | 8 +- src/DiskWriter.h | 7 - src/DownloadCommand.cc | 2 +- src/IteratableChecksumValidator.cc | 3 +- src/IteratableChunkChecksumValidator.cc | 3 +- src/IteratableChunkChecksumValidator.h | 5 + src/Makefile.am | 5 +- src/Makefile.in | 25 ++- src/MessageDigestHelper.cc | 101 ++++++++++ src/MessageDigestHelper.h | 77 +++++++ src/MetalinkEntry.cc | 4 +- src/MetalinkEntry.h | 5 +- src/MetalinkRequestInfo.cc | 4 + src/MultiDiskAdaptor.cc | 65 ++---- src/MultiDiskAdaptor.h | 14 +- src/Peer.cc | 3 +- src/SegmentMan.cc | 58 ++---- src/SegmentMan.h | 15 +- src/ShaVisitor.cc | 5 +- src/SimpleRandomizer.h | 11 +- src/TorrentRequestInfo.cc | 6 +- src/Util.cc | 87 -------- src/Util.h | 29 +-- src/Xml2MetalinkProcessor.cc | 51 +++-- src/main.cc | 5 +- src/message.h | 2 +- src/messageDigest.cc | 63 ++++++ src/messageDigest.h | 61 ++++-- test/ChunkChecksumValidatorTest.cc | 114 +++++++---- test/DefaultBtContextTest.cc | 30 +++ test/DefaultBtRequestFactoryTest.cc | 24 ++- test/DefaultDiskWriterTest.cc | 21 +- test/FeatureConfigTest.cc | 28 ++- test/IteratableChecksumValidatorTest.cc | 5 +- test/IteratableChunkChecksumValidatorTest.cc | 4 +- test/Makefile.am | 46 +++-- test/Makefile.in | 123 +++++++----- test/MetalinkEntryTest.cc | 20 +- test/MockBtContext.h | 11 + test/MultiDiskAdaptorTest.cc | 31 --- test/RequestGroupManTest.cc | 6 + test/RequestTest.cc | 6 + test/TrackerWatcherCommandTest.cc | 23 ++- test/UtilTest.cc | 59 +----- test/Xml2MetalinkProcessorTest.cc | 114 +++++++---- test/test.xml | 26 ++- 67 files changed, 1230 insertions(+), 787 deletions(-) create mode 100644 src/MessageDigestHelper.cc create mode 100644 src/MessageDigestHelper.h create mode 100644 src/messageDigest.cc diff --git a/AUTHORS b/AUTHORS index 716cd10d..085940cc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1 +1,2 @@ Tatsuhiro Tsujikawa +Ross Smith II (Windows port) diff --git a/ChangeLog b/ChangeLog index d3c3a654..0e32d858 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,70 @@ +2007-08-08 Tatsuhiro Tsujikawa + + MessageDigestHelper is introduced in order to simplify the use + of message digest. Removed repeated code. + The message digest algorithm is now specified by string, like "sha1", + "md5". + * src/messageDigest.{h, cc} + * src/MessageDigestHelper.{h, cc}: New class. + * src/DefaultPieceStorage.cc + * src/DefaultBtContext.{h, cc} + (computeFastSet): New function. + (setInfoHash): Added for unit testing. + (setNumPieces): Added for unit testing. + * src/DefaultBtInteractive.cc + * src/BtPieceMessage.cc + * src/Peer.cc + * src/Checksum.h + * src/message.h + * src/IteratableChecksumValidator.h + * src/ChunkChecksumValidator.{h, cc}: Use IteratableChecksumValidator + inside it. + * src/SegmentMan.{h, cc} + (checkIntegrity): Removed. + * src/IteratableChunkChecksumValidator.{h, cc} + * src/Util.h + (sha1Sum): Removed. + (simpleMessageDigest): Removed. + (fileChecksum): Removed. + (computeFastSet): Removed. + * src/ShaVisitor.cc + * src/ChunkChecksum.h + * src/DownloadCommand.cc + + Removed messageDigest virtual functions. + * src/MultiDiskAdaptor.{h, cc} + * src/DiskAdaptor.h + * src/ByteArrayDiskWriter.h + * src/DiskWriter.h + * src/DiskAdaptorWriter.h + * src/AbstractSingleDiskAdaptor.{h, cc} + * src/AbstractDiskWriter.{h, cc} + + Fixed comilation error when message digest is disabled. + * src/MetalinkEntry.{h, cc} + * src/MetalinkRequestInfo.cc + + Removed srandom and random. + * src/SimpleRandomizer.h + + Added size() virtual function to DiskAdaptor + * src/MultiDiskAdaptor.h + + Fixed the bug that causes that files are not opened correctly in + multi-file torrent. + * src/TorrentRequestInfo.cc + * src/MultiDiskAdaptor.cc + + Added SHA256 support + * src/messageDigest.cc + * src/Xml2MetalinkProcessor.cc + + Show supported message digest algorithms + * src/main.cc + + Updated contact info. + * src/main.cc + 2007-08-02 Tatsuhiro Tsujikawa Merged Dan's patch: @@ -9,6 +76,10 @@ Updated contact info. * src/main.cc + Added #ifdef ENABLE_MESSAGE_DIGEST to fix test errors when message + digest is not available. + * src/MetalinkEntry.h + 2007-08-01 Tatsuhiro Tsujikawa Make a2netcompat.h include a2io.h to fix compilation error: diff --git a/config.h.in b/config.h.in index 6816c287..01b86721 100644 --- a/config.h.in +++ b/config.h.in @@ -53,6 +53,12 @@ /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #undef HAVE_DOPRNT +/* Define to 1 if you have the `EVP_DigestInit_ex' function. */ +#undef HAVE_EVP_DIGESTINIT_EX + +/* Define to 1 if you have the `EVP_sha256' function. */ +#undef HAVE_EVP_SHA256 + /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H @@ -199,6 +205,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NL_TYPES_H +/* Define to 1 if you have old openssl. */ +#undef HAVE_OLD_LIBSSL + /* Define to 1 if you have the `putenv' function. */ #undef HAVE_PUTENV diff --git a/configure b/configure index 54050693..179e9771 100755 --- a/configure +++ b/configure @@ -5280,7 +5280,7 @@ fi { echo "$as_me:$LINENO: result: $ac_cv_lib_ssl_SSL_library_init" >&5 echo "${ECHO_T}$ac_cv_lib_ssl_SSL_library_init" >&6; } if test $ac_cv_lib_ssl_SSL_library_init = yes; then - have_openssl=yes + have_openssl=yes; LIBS="-lssl $LIBS" fi @@ -5342,7 +5342,7 @@ fi { echo "$as_me:$LINENO: result: $ac_cv_lib_crypto_main" >&5 echo "${ECHO_T}$ac_cv_lib_crypto_main" >&6; } if test $ac_cv_lib_crypto_main = yes; then - have_openssl=yes + have_openssl=yes; LIBS="-lcrypto $LIBS" fi if test "x$have_openssl" = "xyes"; then @@ -5351,10 +5351,205 @@ cat >>confdefs.h <<\_ACEOF #define HAVE_LIBSSL 1 _ACEOF + +for ac_func in EVP_DigestInit_ex +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + have_digestinit_ex=yes +fi +done + + if test "x$have_digestinit_ex" = "x"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_OLD_LIBSSL 1 +_ACEOF + + fi OPENSSL_LIBS="-L$openssl_prefix_lib -lssl -lcrypto" OPENSSL_CFLAGS="-I$openssl_prefix_include" + +for ac_func in EVP_sha256 +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + fi fi diff --git a/m4/openssl.m4 b/m4/openssl.m4 index e9d16069..072d915d 100644 --- a/m4/openssl.m4 +++ b/m4/openssl.m4 @@ -18,17 +18,24 @@ CPPFLAGS_save=$CPPFLAGS LIBS="-L$openssl_prefix_lib $LIBS" CPPFLAGS="-I$openssl_prefix_include $CPPFLAGS" -AC_CHECK_LIB([ssl], [SSL_library_init], [have_openssl=yes]) +AC_CHECK_LIB([ssl], [SSL_library_init], [have_openssl=yes; LIBS="-lssl $LIBS"]) if test "x$have_openssl" = "xyes"; then have_openssl=no - AC_CHECK_LIB([crypto], [main], [have_openssl=yes]) + AC_CHECK_LIB([crypto], [main], [have_openssl=yes; LIBS="-lcrypto $LIBS"]) if test "x$have_openssl" = "xyes"; then AC_DEFINE([HAVE_LIBSSL], [1], [Define to 1 if you have openssl.]) + dnl check whether EVP_DigestInit_ex exists. Old openssl doesn't have it. + AC_CHECK_FUNCS([EVP_DigestInit_ex], [have_digestinit_ex=yes]) + if test "x$have_digestinit_ex" = "x"; then + AC_DEFINE([HAVE_OLD_LIBSSL], [1], [Define to 1 if you have old openssl.]) + fi OPENSSL_LIBS="-L$openssl_prefix_lib -lssl -lcrypto" OPENSSL_CFLAGS="-I$openssl_prefix_include" AC_SUBST(OPENSSL_LIBS) AC_SUBST(OPENSSL_CFLAGS) + dnl search for sha256 support + AC_CHECK_FUNCS([EVP_sha256]) fi fi 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 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 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 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 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 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 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 @@ +/* */ +#include "MessageDigestHelper.h" +#include "messageDigest.h" +#include "DlAbortEx.h" +#include "message.h" +#include "DefaultDiskWriter.h" +#include "Util.h" +#include + +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 @@ +/* */ +#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 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 @@ -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); +bool SegmentMan::isChunkChecksumValidationReady(const ChunkChecksumHandle& chunkChecksum) const { + return !chunkChecksum.isNull() && bitfield && totalSize > 0 && + chunkChecksum->getEstimatedDataLength() >= totalSize; } #endif // ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST -bool SegmentMan::isChunkChecksumValidationReady() const { - return bitfield && totalSize > 0 && - ((int64_t)pieceHashes.size())*chunkHashLength >= 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, const ChunkChecksumHandle& chunkChecksum); - void tryChunkChecksumValidation(const SegmentHandle& segment); - - 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, diff --git a/src/Util.h b/src/Util.h index 799cf105..89be6fc7 100644 --- a/src/Util.h +++ b/src/Util.h @@ -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 +#include "FileEntry.h" #include #include -#include #include #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 " << endl; - cout << "Ross Smith II (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 @@ +/* */ +#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 #ifdef HAVE_LIBSSL #include @@ -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 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 MessageDigestContextHandle; -#endif // ENABLE_SSL #endif // _D_MESSAGE_DIGEST_H_ diff --git a/test/ChunkChecksumValidatorTest.cc b/test/ChunkChecksumValidatorTest.cc index e01523e6..4ad8b9d8 100644 --- a/test/ChunkChecksumValidatorTest.cc +++ b/test/ChunkChecksumValidatorTest.cc @@ -17,10 +17,25 @@ private: static const char* csArray[];// = { "29b0e7878271645fffb7eec7db4a7473a1c00bc1", // "4df75a661cb7eb2733d9cdaa7f772eae3a4e2976", // "0a4ea2f7dd7c52ddf2099a444ab2184b4d341bdb" }; + public: void setUp() { } + + ChunkChecksumValidatorHandle + createChunkChecksumValidator(const string& filename, BitfieldMan* bitfield, const ChunkChecksumHandle& chunkChecksum) + { + IteratableChunkChecksumValidatorHandle iv = new IteratableChunkChecksumValidator(); + DefaultDiskWriterHandle dw = new DefaultDiskWriter(); + dw->openExistingFile(filename); + iv->setDiskWriter(dw); + iv->setBitfield(bitfield); + iv->setChunkChecksum(chunkChecksum); + + return new ChunkChecksumValidator(iv); + } + void testValidate(); void testValidate2(); void testValidate3(); @@ -30,114 +45,127 @@ public: CPPUNIT_TEST_SUITE_REGISTRATION( ChunkChecksumValidatorTest ); -const char* ChunkChecksumValidatorTest::csArray[] = { "29b0e7878271645fffb7eec7db4a7473a1c00bc1", - "4df75a661cb7eb2733d9cdaa7f772eae3a4e2976", - "0a4ea2f7dd7c52ddf2099a444ab2184b4d341bdb" }; +const char* ChunkChecksumValidatorTest::csArray[] = + { "29b0e7878271645fffb7eec7db4a7473a1c00bc1", + "4df75a661cb7eb2733d9cdaa7f772eae3a4e2976", + "0a4ea2f7dd7c52ddf2099a444ab2184b4d341bdb" }; void ChunkChecksumValidatorTest::testValidate() { -#ifdef ENABLE_MESSAGE_DIGEST BitfieldMan bitfieldMan(100, 250); bitfieldMan.setAllBit(); Strings checksums(&csArray[0], &csArray[3]); - DefaultDiskWriterHandle diskWriter = new DefaultDiskWriter(); - diskWriter->openExistingFile("chunkChecksumTestFile250.txt"); - - ChunkChecksumValidator validator; - validator.setDiskWriter(diskWriter); - - validator.validate(&bitfieldMan, checksums, 100); + ChunkChecksumValidatorHandle validator = + createChunkChecksumValidator("chunkChecksumTestFile250.txt", + &bitfieldMan, new ChunkChecksum("sha1", + checksums, + 100)); + validator->validate(); CPPUNIT_ASSERT(bitfieldMan.isAllBitSet()); checksums[1] = "ffffffffffffffffffffffffffffffffffffffff"; - validator.validate(&bitfieldMan, checksums, 100); + validator = + createChunkChecksumValidator("chunkChecksumTestFile250.txt", + &bitfieldMan, new ChunkChecksum("sha1", + checksums, + 100)); + + validator->validate(); CPPUNIT_ASSERT(bitfieldMan.isBitSet(0)); CPPUNIT_ASSERT(!bitfieldMan.isBitSet(1)); CPPUNIT_ASSERT(bitfieldMan.isBitSet(2)); -#endif /* ENABLE_MESSAGE_DIGEST */ } void ChunkChecksumValidatorTest::testValidate2() { -#ifdef ENABLE_MESSAGE_DIGEST BitfieldMan bitfieldMan(50, 250); bitfieldMan.setAllBit(); Strings checksums(&csArray[0], &csArray[3]); - DefaultDiskWriterHandle diskWriter = new DefaultDiskWriter(); - diskWriter->openExistingFile("chunkChecksumTestFile250.txt"); - - ChunkChecksumValidator validator; - validator.setDiskWriter(diskWriter); - - validator.validate(&bitfieldMan, checksums, 100); + ChunkChecksumValidatorHandle validator = + createChunkChecksumValidator("chunkChecksumTestFile250.txt", + &bitfieldMan, new ChunkChecksum("sha1", + checksums, + 100)); + validator->validate(); CPPUNIT_ASSERT(bitfieldMan.isAllBitSet()); checksums[1] = "ffffffffffffffffffffffffffffffffffffffff"; - validator.validate(&bitfieldMan, checksums, 100); + validator = + createChunkChecksumValidator("chunkChecksumTestFile250.txt", + &bitfieldMan, new ChunkChecksum("sha1", + checksums, + 100)); + validator->validate(); 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)); -#endif /* ENABLE_MESSAGE_DIGEST */ } void ChunkChecksumValidatorTest::testValidate3() { -#ifdef ENABLE_MESSAGE_DIGEST BitfieldMan bitfieldMan(50, 250); bitfieldMan.setAllBit(); Strings checksums; checksums.push_back("898a81b8e0181280ae2ee1b81e269196d91e869a"); - DefaultDiskWriterHandle diskWriter = new DefaultDiskWriter(); - diskWriter->openExistingFile("chunkChecksumTestFile250.txt"); - - ChunkChecksumValidator validator; - validator.setDiskWriter(diskWriter); - - validator.validate(&bitfieldMan, checksums, 250); + ChunkChecksumValidatorHandle validator = + createChunkChecksumValidator("chunkChecksumTestFile250.txt", + &bitfieldMan, new ChunkChecksum("sha1", + checksums, + 250)); + validator->validate(); CPPUNIT_ASSERT(bitfieldMan.isAllBitSet()); checksums[0] = "ffffffffffffffffffffffffffffffffffffffff"; - validator.validate(&bitfieldMan, checksums, 250); + validator = + createChunkChecksumValidator("chunkChecksumTestFile250.txt", + &bitfieldMan, new ChunkChecksum("sha1", + checksums, + 250)); + validator->validate(); 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)); -#endif /* ENABLE_MESSAGE_DIGEST */ } void ChunkChecksumValidatorTest::testValidate4() { -#ifdef ENABLE_MESSAGE_DIGEST BitfieldMan bitfieldMan(70, 250); bitfieldMan.setAllBit(); Strings checksums(&csArray[0], &csArray[3]); - DefaultDiskWriterHandle diskWriter = new DefaultDiskWriter(); - diskWriter->openExistingFile("chunkChecksumTestFile250.txt"); - - ChunkChecksumValidator validator; - validator.setDiskWriter(diskWriter); - - validator.validate(&bitfieldMan, checksums, 100); + ChunkChecksumValidatorHandle validator = + createChunkChecksumValidator("chunkChecksumTestFile250.txt", + &bitfieldMan, new ChunkChecksum("sha1", + checksums, + 100)); + validator->validate(); CPPUNIT_ASSERT(bitfieldMan.isAllBitSet()); checksums[1] = "ffffffffffffffffffffffffffffffffffffffff"; - validator.validate(&bitfieldMan, checksums, 100); + + validator = + createChunkChecksumValidator("chunkChecksumTestFile250.txt", + &bitfieldMan, new ChunkChecksum("sha1", + checksums, + 100)); + + validator->validate(); CPPUNIT_ASSERT(bitfieldMan.isBitSet(0)); CPPUNIT_ASSERT(!bitfieldMan.isBitSet(1)); CPPUNIT_ASSERT(!bitfieldMan.isBitSet(2)); CPPUNIT_ASSERT(bitfieldMan.isBitSet(3)); -#endif /* ENABLE_MESSAGE_DIGEST */ } + diff --git a/test/DefaultBtContextTest.cc b/test/DefaultBtContextTest.cc index b6417399..1e563b63 100644 --- a/test/DefaultBtContextTest.cc +++ b/test/DefaultBtContextTest.cc @@ -23,6 +23,7 @@ class DefaultBtContextTest:public CppUnit::TestFixture { CPPUNIT_TEST(testGetPieceLength); CPPUNIT_TEST(testGetInfoHashAsString); CPPUNIT_TEST(testGetPeerId); + CPPUNIT_TEST(testComputeFastSet); CPPUNIT_TEST_SUITE_END(); public: void setUp() { @@ -43,6 +44,7 @@ public: void testGetPieceLength(); void testGetInfoHashAsString(); void testGetPeerId(); + void testComputeFastSet(); }; @@ -224,3 +226,31 @@ void DefaultBtContextTest::testGetPeerId() { DefaultBtContext btContext; Util::torrentUrlencode(btContext.getPeerId(), 20); } + +void DefaultBtContextTest::testComputeFastSet() +{ + string ipaddr = "192.168.0.1"; + unsigned char infoHash[20]; + memset(infoHash, 0, sizeof(infoHash)); + infoHash[0] = 0xff; + + int pieces = 1000; + int fastSetSize = 10; + + DefaultBtContext btContext; + btContext.setInfoHash(infoHash); + btContext.setNumPieces(pieces); + + Integers fastSet = btContext.computeFastSet(ipaddr, fastSetSize); + //for_each(fastSet.begin(), fastSet.end(), Printer()); + //cerr << endl; + int ans1[] = { 686, 459, 278, 200, 404, 834, 64, 203, 760, 950 }; + Integers ansSet1(&ans1[0], &ans1[10]); + CPPUNIT_ASSERT(equal(fastSet.begin(), fastSet.end(), ansSet1.begin())); + + ipaddr = "10.0.0.1"; + fastSet = btContext.computeFastSet(ipaddr, fastSetSize); + int ans2[] = { 568, 188, 466, 452, 550, 662, 109, 226, 398, 11 }; + Integers ansSet2(&ans2[0], &ans2[10]); + CPPUNIT_ASSERT(equal(fastSet.begin(), fastSet.end(), ansSet2.begin())); +} diff --git a/test/DefaultBtRequestFactoryTest.cc b/test/DefaultBtRequestFactoryTest.cc index 4a8a554e..d8d083fa 100644 --- a/test/DefaultBtRequestFactoryTest.cc +++ b/test/DefaultBtRequestFactoryTest.cc @@ -55,6 +55,24 @@ public: } }; + class SortMockBtRequestMessage { + public: + bool operator()(const SharedHandle& a, + const SharedHandle& b) { + if(a->index < b->index) { + return true; + } else if(b->index < a->index) { + return false; + } else if(a->blockIndex < b->blockIndex) { + return true; + } else if(b->blockIndex < a->blockIndex) { + return false; + } else { + return true; + } + } + }; + void setUp() { BtRegistry::clear(); btContext = new MockBtContext(); @@ -142,6 +160,8 @@ void DefaultBtRequestFactoryTest::testCreateRequestMessages_onEndGame() { BtMessages msgs = btRequestFactory->createRequestMessagesOnEndGame(3); + sort(msgs.begin(), msgs.end(), SortMockBtRequestMessage()); + CPPUNIT_ASSERT_EQUAL((size_t)3, msgs.size()); BtMessages::iterator itr = msgs.begin(); MockBtRequestMessage* msg = (MockBtRequestMessage*)itr->get(); @@ -150,11 +170,11 @@ void DefaultBtRequestFactoryTest::testCreateRequestMessages_onEndGame() { ++itr; msg = (MockBtRequestMessage*)itr->get(); CPPUNIT_ASSERT_EQUAL(1, msg->index); - CPPUNIT_ASSERT_EQUAL(1, msg->blockIndex); + CPPUNIT_ASSERT_EQUAL(0, msg->blockIndex); ++itr; msg = (MockBtRequestMessage*)itr->get(); CPPUNIT_ASSERT_EQUAL(1, msg->index); - CPPUNIT_ASSERT_EQUAL(0, msg->blockIndex); + CPPUNIT_ASSERT_EQUAL(1, msg->blockIndex); } void DefaultBtRequestFactoryTest::testRemoveTargetPiece() { diff --git a/test/DefaultDiskWriterTest.cc b/test/DefaultDiskWriterTest.cc index ab54bf12..417810b2 100644 --- a/test/DefaultDiskWriterTest.cc +++ b/test/DefaultDiskWriterTest.cc @@ -1,5 +1,4 @@ #include "DefaultDiskWriter.h" -#include #include using namespace std; @@ -7,7 +6,7 @@ using namespace std; class DefaultDiskWriterTest:public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DefaultDiskWriterTest); - CPPUNIT_TEST(testMessageDigest); + CPPUNIT_TEST(testSize); CPPUNIT_TEST_SUITE_END(); private: @@ -15,24 +14,16 @@ public: void setUp() { } - void testMessageDigest(); + void testSize(); }; CPPUNIT_TEST_SUITE_REGISTRATION( DefaultDiskWriterTest ); -void DefaultDiskWriterTest::testMessageDigest() { -#ifdef ENABLE_MESSAGE_DIGEST - +void DefaultDiskWriterTest::testSize() +{ DefaultDiskWriter dw; dw.openExistingFile("4096chunk.txt"); - - CPPUNIT_ASSERT_EQUAL(string("608cabc0f2fa18c260cafd974516865c772363d5"), - dw.messageDigest(0, 4096, DIGEST_ALGO_SHA1)); - - CPPUNIT_ASSERT_EQUAL(string("7a4a9ae537ebbbb826b1060e704490ad0f365ead"), - dw.messageDigest(5, 100, DIGEST_ALGO_SHA1)); - - dw.closeFile(); -#endif // ENABLE_MESSAGE_DIGEST + CPPUNIT_ASSERT_EQUAL((int64_t)4096, dw.size()); } + diff --git a/test/FeatureConfigTest.cc b/test/FeatureConfigTest.cc index 6af5f059..ec493974 100644 --- a/test/FeatureConfigTest.cc +++ b/test/FeatureConfigTest.cc @@ -31,8 +31,13 @@ void FeatureConfigTest::testGetDefaultPort() { void FeatureConfigTest::testIsSupported() { CPPUNIT_ASSERT_EQUAL(true, FeatureConfig::getInstance()->isSupported("http")); +#ifdef ENABLE_SSL CPPUNIT_ASSERT_EQUAL(true, FeatureConfig::getInstance()->isSupported("https")); +#else + CPPUNIT_ASSERT_EQUAL(false, + FeatureConfig::getInstance()->isSupported("https")); +#endif // ENABLE_SSL CPPUNIT_ASSERT_EQUAL(true, FeatureConfig::getInstance()->isSupported("ftp")); CPPUNIT_ASSERT_EQUAL(false, @@ -41,11 +46,32 @@ void FeatureConfigTest::testIsSupported() { void FeatureConfigTest::testGetConfigurationSummary() { CPPUNIT_ASSERT_EQUAL(string("http: yes\n") +#ifdef ENABLE_SSL +"https: yes\n" +#else + +"https: no\n" +#endif // ENABLE_SSL +"ftp: yes\n" +#ifdef ENABLE_BITTORRENT +"bittorrent: yes\n" +#else + +"bittorrent: no\n" +#endif // ENABLE_BITTORRENT +#ifdef ENABLE_METALINK +"metalink: yes\n" +#else + +"metalink: no\n" +#endif // ENABLE_METALINK +#ifdef ENABLE_MESSAGE_DIGEST +"message digest: yes\n" - +"async dns: yes\n", +#else + +"message digest: no\n" +#endif // ENABLE_MESSAGE_DIGEST +#ifdef ENABLE_ASYNC_DNS + +"async dns: yes\n" +#else + +"async dns: no\n" +#endif // ENABLE_ASYNC_DNS + , FeatureConfig::getInstance()->getConfigurationSummary()); } diff --git a/test/IteratableChecksumValidatorTest.cc b/test/IteratableChecksumValidatorTest.cc index 8b78e106..7479c9f9 100644 --- a/test/IteratableChecksumValidatorTest.cc +++ b/test/IteratableChecksumValidatorTest.cc @@ -27,7 +27,8 @@ void IteratableChecksumValidatorTest::testValidate() { BitfieldMan bitfieldMan(100, 250); bitfieldMan.setAllBit(); - ChecksumHandle checksum = new Checksum("898a81b8e0181280ae2ee1b81e269196d91e869a", DIGEST_ALGO_SHA1); + ChecksumHandle checksum = new Checksum("sha1", + "898a81b8e0181280ae2ee1b81e269196d91e869a"); DefaultDiskWriterHandle diskWriter = new DefaultDiskWriter(); diskWriter->openExistingFile("chunkChecksumTestFile250.txt"); @@ -48,7 +49,7 @@ void IteratableChecksumValidatorTest::testValidate2() { BitfieldMan bitfieldMan(100, 250); bitfieldMan.setAllBit(); - ChecksumHandle checksum = new Checksum("ffffffffffffffffffffffffffffffffffffffff", DIGEST_ALGO_SHA1); + ChecksumHandle checksum = new Checksum("sha1", "ffffffffffffffffffffffffffffffffffffffff"); DefaultDiskWriterHandle diskWriter = new DefaultDiskWriter(); diskWriter->openExistingFile("chunkChecksumTestFile250.txt"); diff --git a/test/IteratableChunkChecksumValidatorTest.cc b/test/IteratableChunkChecksumValidatorTest.cc index fb34d243..65dbbe18 100644 --- a/test/IteratableChunkChecksumValidatorTest.cc +++ b/test/IteratableChunkChecksumValidatorTest.cc @@ -46,7 +46,7 @@ void IteratableChunkChecksumValidatorTest::testValidate() { DefaultDiskWriterHandle diskWriter = new DefaultDiskWriter(); diskWriter->openExistingFile("chunkChecksumTestFile250.txt"); - ChunkChecksumHandle chunkChecksum = new ChunkChecksum(DIGEST_ALGO_SHA1, + ChunkChecksumHandle chunkChecksum = new ChunkChecksum("sha1", checksums, 100); IteratableChunkChecksumValidator validator; @@ -64,7 +64,7 @@ void IteratableChunkChecksumValidatorTest::testValidate() { CPPUNIT_ASSERT(bitfieldMan.isAllBitSet()); checksums[1] = "ffffffffffffffffffffffffffffffffffffffff"; - chunkChecksum = new ChunkChecksum(DIGEST_ALGO_SHA1, + chunkChecksum = new ChunkChecksum("sha1", checksums, 100); validator.setChunkChecksum(chunkChecksum); diff --git a/test/Makefile.am b/test/Makefile.am index 4c0320bc..11ece44b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -10,12 +10,7 @@ aria2c_SOURCES = AllTest.cc\ CookieParserTest.cc\ HttpRequestTest.cc\ CookieBoxFactoryTest.cc\ - ByteArrayDiskWriterTest.cc\ RequestGroupManTest.cc\ - IteratableChecksumValidatorTest.cc\ - IteratableChunkChecksumValidatorTest.cc\ - PeerTest.cc\ - DefaultPeerStorageTest.cc\ RequestFactoryTest.cc\ NetrcAuthResolverTest.cc\ DefaultAuthResolverTest.cc\ @@ -32,25 +27,19 @@ aria2c_SOURCES = AllTest.cc\ FileTest.cc\ OptionTest.cc\ Base64Test.cc\ - DataTest.cc\ - DictionaryTest.cc\ - ListTest.cc\ - MetaFileUtilTest.cc\ - PeerMessageUtilTest.cc\ DefaultDiskWriterTest.cc\ - MultiDiskAdaptorTest.cc\ FeatureConfigTest.cc\ - ShareRatioSeedCriteriaTest.cc\ - TimeSeedCriteriaTest.cc\ SpeedCalcTest.cc\ - DefaultPeerListProcessorTest.cc\ - AnnounceListTest.cc\ - TrackerWatcherCommandTest.cc\ - MockPeerStorage.h\ FixedNumberRandomizer.h\ - ConsoleFileAllocationMonitorTest.cc\ - ChunkChecksumValidatorTest.cc - + ConsoleFileAllocationMonitorTest.cc + +if ENABLE_MESSAGE_DIGEST +aria2c_SOURCES += ChunkChecksumValidatorTest.cc\ + IteratableChecksumValidatorTest.cc\ + IteratableChunkChecksumValidatorTest.cc\ + MessageDigestHelperTest.cc +endif # ENABLE_MESSAGE_DIGEST + if ENABLE_BITTORRENT aria2c_SOURCES += BtAllowedFastMessageTest.cc\ BtBitfieldMessageTest.cc\ @@ -78,7 +67,22 @@ aria2c_SOURCES += BtAllowedFastMessageTest.cc\ MockBtMessage.h\ MockBtMessageDispatcher.h\ MockBtMessageFactory.h\ - ShaVisitorTest.cc + ShaVisitorTest.cc\ + DefaultPeerListProcessorTest.cc\ + AnnounceListTest.cc\ + TrackerWatcherCommandTest.cc\ + DefaultPeerStorageTest.cc\ + MockPeerStorage.h\ + DataTest.cc\ + DictionaryTest.cc\ + ListTest.cc\ + MetaFileUtilTest.cc\ + MultiDiskAdaptorTest.cc\ + ByteArrayDiskWriterTest.cc\ + PeerTest.cc\ + PeerMessageUtilTest.cc\ + ShareRatioSeedCriteriaTest.cc\ + TimeSeedCriteriaTest.cc endif # ENABLE_BITTORRENT if ENABLE_METALINK diff --git a/test/Makefile.in b/test/Makefile.in index 943af20c..f83bff0f 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -37,7 +37,12 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = $(am__EXEEXT_1) -@ENABLE_BITTORRENT_TRUE@am__append_1 = BtAllowedFastMessageTest.cc\ +@ENABLE_MESSAGE_DIGEST_TRUE@am__append_1 = ChunkChecksumValidatorTest.cc\ +@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidatorTest.cc\ +@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidatorTest.cc\ +@ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelperTest.cc + +@ENABLE_BITTORRENT_TRUE@am__append_2 = BtAllowedFastMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ BtBitfieldMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ BtCancelMessageTest.cc\ @ENABLE_BITTORRENT_TRUE@ BtChokeMessageTest.cc\ @@ -63,9 +68,24 @@ check_PROGRAMS = $(am__EXEEXT_1) @ENABLE_BITTORRENT_TRUE@ MockBtMessage.h\ @ENABLE_BITTORRENT_TRUE@ MockBtMessageDispatcher.h\ @ENABLE_BITTORRENT_TRUE@ MockBtMessageFactory.h\ -@ENABLE_BITTORRENT_TRUE@ ShaVisitorTest.cc +@ENABLE_BITTORRENT_TRUE@ ShaVisitorTest.cc\ +@ENABLE_BITTORRENT_TRUE@ DefaultPeerListProcessorTest.cc\ +@ENABLE_BITTORRENT_TRUE@ AnnounceListTest.cc\ +@ENABLE_BITTORRENT_TRUE@ TrackerWatcherCommandTest.cc\ +@ENABLE_BITTORRENT_TRUE@ DefaultPeerStorageTest.cc\ +@ENABLE_BITTORRENT_TRUE@ MockPeerStorage.h\ +@ENABLE_BITTORRENT_TRUE@ DataTest.cc\ +@ENABLE_BITTORRENT_TRUE@ DictionaryTest.cc\ +@ENABLE_BITTORRENT_TRUE@ ListTest.cc\ +@ENABLE_BITTORRENT_TRUE@ MetaFileUtilTest.cc\ +@ENABLE_BITTORRENT_TRUE@ MultiDiskAdaptorTest.cc\ +@ENABLE_BITTORRENT_TRUE@ ByteArrayDiskWriterTest.cc\ +@ENABLE_BITTORRENT_TRUE@ PeerTest.cc\ +@ENABLE_BITTORRENT_TRUE@ PeerMessageUtilTest.cc\ +@ENABLE_BITTORRENT_TRUE@ ShareRatioSeedCriteriaTest.cc\ +@ENABLE_BITTORRENT_TRUE@ TimeSeedCriteriaTest.cc -@ENABLE_METALINK_TRUE@am__append_2 = MetalinkerTest.cc\ +@ENABLE_METALINK_TRUE@am__append_3 = MetalinkerTest.cc\ @ENABLE_METALINK_TRUE@ MetalinkEntryTest.cc\ @ENABLE_METALINK_TRUE@ Xml2MetalinkProcessorTest.cc @@ -94,24 +114,18 @@ am__aria2c_SOURCES_DIST = AllTest.cc FileUriListParserTest.cc \ StreamUriListParserTest.cc HttpHeaderProcessorTest.cc \ UtilTest.cc CookieBoxTest.cc RequestTest.cc \ CookieParserTest.cc HttpRequestTest.cc CookieBoxFactoryTest.cc \ - ByteArrayDiskWriterTest.cc RequestGroupManTest.cc \ - IteratableChecksumValidatorTest.cc \ - IteratableChunkChecksumValidatorTest.cc PeerTest.cc \ - DefaultPeerStorageTest.cc RequestFactoryTest.cc \ + RequestGroupManTest.cc RequestFactoryTest.cc \ NetrcAuthResolverTest.cc DefaultAuthResolverTest.cc \ OptionHandlerTest.cc SegmentManTest.cc BitfieldManTest.cc \ GlowFileAllocatorTest.cc NetrcTest.cc SingletonHolderTest.cc \ HttpHeaderTest.cc HttpResponseTest.cc SharedHandleTest.cc \ ChunkedEncodingTest.cc FileTest.cc OptionTest.cc Base64Test.cc \ - DataTest.cc DictionaryTest.cc ListTest.cc MetaFileUtilTest.cc \ - PeerMessageUtilTest.cc DefaultDiskWriterTest.cc \ - MultiDiskAdaptorTest.cc FeatureConfigTest.cc \ - ShareRatioSeedCriteriaTest.cc TimeSeedCriteriaTest.cc \ - SpeedCalcTest.cc DefaultPeerListProcessorTest.cc \ - AnnounceListTest.cc TrackerWatcherCommandTest.cc \ - MockPeerStorage.h FixedNumberRandomizer.h \ - ConsoleFileAllocationMonitorTest.cc \ - ChunkChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \ + DefaultDiskWriterTest.cc FeatureConfigTest.cc SpeedCalcTest.cc \ + FixedNumberRandomizer.h ConsoleFileAllocationMonitorTest.cc \ + ChunkChecksumValidatorTest.cc \ + IteratableChecksumValidatorTest.cc \ + IteratableChunkChecksumValidatorTest.cc \ + MessageDigestHelperTest.cc BtAllowedFastMessageTest.cc \ BtBitfieldMessageTest.cc BtCancelMessageTest.cc \ BtChokeMessageTest.cc BtHandshakeMessageTest.cc \ BtHaveAllMessageTest.cc BtHaveMessageTest.cc \ @@ -124,9 +138,20 @@ am__aria2c_SOURCES_DIST = AllTest.cc FileUriListParserTest.cc \ DefaultBtMessageDispatcherTest.cc \ DefaultBtRequestFactoryTest.cc DefaultPieceStorageTest.cc \ MockBtMessage.h MockBtMessageDispatcher.h \ - MockBtMessageFactory.h ShaVisitorTest.cc MetalinkerTest.cc \ - MetalinkEntryTest.cc Xml2MetalinkProcessorTest.cc -@ENABLE_BITTORRENT_TRUE@am__objects_1 = \ + MockBtMessageFactory.h ShaVisitorTest.cc \ + DefaultPeerListProcessorTest.cc AnnounceListTest.cc \ + TrackerWatcherCommandTest.cc DefaultPeerStorageTest.cc \ + MockPeerStorage.h DataTest.cc DictionaryTest.cc ListTest.cc \ + MetaFileUtilTest.cc MultiDiskAdaptorTest.cc \ + ByteArrayDiskWriterTest.cc PeerTest.cc PeerMessageUtilTest.cc \ + ShareRatioSeedCriteriaTest.cc TimeSeedCriteriaTest.cc \ + MetalinkerTest.cc MetalinkEntryTest.cc \ + Xml2MetalinkProcessorTest.cc +@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = ChunkChecksumValidatorTest.$(OBJEXT) \ +@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChecksumValidatorTest.$(OBJEXT) \ +@ENABLE_MESSAGE_DIGEST_TRUE@ IteratableChunkChecksumValidatorTest.$(OBJEXT) \ +@ENABLE_MESSAGE_DIGEST_TRUE@ MessageDigestHelperTest.$(OBJEXT) +@ENABLE_BITTORRENT_TRUE@am__objects_2 = \ @ENABLE_BITTORRENT_TRUE@ BtAllowedFastMessageTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtBitfieldMessageTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ BtCancelMessageTest.$(OBJEXT) \ @@ -150,8 +175,22 @@ am__aria2c_SOURCES_DIST = AllTest.cc FileUriListParserTest.cc \ @ENABLE_BITTORRENT_TRUE@ DefaultBtMessageDispatcherTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DefaultBtRequestFactoryTest.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ DefaultPieceStorageTest.$(OBJEXT) \ -@ENABLE_BITTORRENT_TRUE@ ShaVisitorTest.$(OBJEXT) -@ENABLE_METALINK_TRUE@am__objects_2 = MetalinkerTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ ShaVisitorTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ DefaultPeerListProcessorTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ AnnounceListTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ TrackerWatcherCommandTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ DefaultPeerStorageTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ DataTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ DictionaryTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ ListTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ MetaFileUtilTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ MultiDiskAdaptorTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ ByteArrayDiskWriterTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ PeerTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ PeerMessageUtilTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ ShareRatioSeedCriteriaTest.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ TimeSeedCriteriaTest.$(OBJEXT) +@ENABLE_METALINK_TRUE@am__objects_3 = MetalinkerTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkEntryTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ Xml2MetalinkProcessorTest.$(OBJEXT) am_aria2c_OBJECTS = AllTest.$(OBJEXT) FileUriListParserTest.$(OBJEXT) \ @@ -159,12 +198,7 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) FileUriListParserTest.$(OBJEXT) \ HttpHeaderProcessorTest.$(OBJEXT) UtilTest.$(OBJEXT) \ CookieBoxTest.$(OBJEXT) RequestTest.$(OBJEXT) \ CookieParserTest.$(OBJEXT) HttpRequestTest.$(OBJEXT) \ - CookieBoxFactoryTest.$(OBJEXT) \ - ByteArrayDiskWriterTest.$(OBJEXT) \ - RequestGroupManTest.$(OBJEXT) \ - IteratableChecksumValidatorTest.$(OBJEXT) \ - IteratableChunkChecksumValidatorTest.$(OBJEXT) \ - PeerTest.$(OBJEXT) DefaultPeerStorageTest.$(OBJEXT) \ + CookieBoxFactoryTest.$(OBJEXT) RequestGroupManTest.$(OBJEXT) \ RequestFactoryTest.$(OBJEXT) NetrcAuthResolverTest.$(OBJEXT) \ DefaultAuthResolverTest.$(OBJEXT) OptionHandlerTest.$(OBJEXT) \ SegmentManTest.$(OBJEXT) BitfieldManTest.$(OBJEXT) \ @@ -172,18 +206,11 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) FileUriListParserTest.$(OBJEXT) \ SingletonHolderTest.$(OBJEXT) HttpHeaderTest.$(OBJEXT) \ HttpResponseTest.$(OBJEXT) SharedHandleTest.$(OBJEXT) \ ChunkedEncodingTest.$(OBJEXT) FileTest.$(OBJEXT) \ - OptionTest.$(OBJEXT) Base64Test.$(OBJEXT) DataTest.$(OBJEXT) \ - DictionaryTest.$(OBJEXT) ListTest.$(OBJEXT) \ - MetaFileUtilTest.$(OBJEXT) PeerMessageUtilTest.$(OBJEXT) \ - DefaultDiskWriterTest.$(OBJEXT) MultiDiskAdaptorTest.$(OBJEXT) \ - FeatureConfigTest.$(OBJEXT) \ - ShareRatioSeedCriteriaTest.$(OBJEXT) \ - TimeSeedCriteriaTest.$(OBJEXT) SpeedCalcTest.$(OBJEXT) \ - DefaultPeerListProcessorTest.$(OBJEXT) \ - AnnounceListTest.$(OBJEXT) TrackerWatcherCommandTest.$(OBJEXT) \ - ConsoleFileAllocationMonitorTest.$(OBJEXT) \ - ChunkChecksumValidatorTest.$(OBJEXT) $(am__objects_1) \ - $(am__objects_2) + OptionTest.$(OBJEXT) Base64Test.$(OBJEXT) \ + DefaultDiskWriterTest.$(OBJEXT) FeatureConfigTest.$(OBJEXT) \ + SpeedCalcTest.$(OBJEXT) \ + ConsoleFileAllocationMonitorTest.$(OBJEXT) $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) aria2c_OBJECTS = $(am_aria2c_OBJECTS) am__DEPENDENCIES_1 = aria2c_DEPENDENCIES = ../src/libaria2c.a $(am__DEPENDENCIES_1) @@ -372,24 +399,15 @@ aria2c_SOURCES = AllTest.cc FileUriListParserTest.cc \ StreamUriListParserTest.cc HttpHeaderProcessorTest.cc \ UtilTest.cc CookieBoxTest.cc RequestTest.cc \ CookieParserTest.cc HttpRequestTest.cc CookieBoxFactoryTest.cc \ - ByteArrayDiskWriterTest.cc RequestGroupManTest.cc \ - IteratableChecksumValidatorTest.cc \ - IteratableChunkChecksumValidatorTest.cc PeerTest.cc \ - DefaultPeerStorageTest.cc RequestFactoryTest.cc \ + RequestGroupManTest.cc RequestFactoryTest.cc \ NetrcAuthResolverTest.cc DefaultAuthResolverTest.cc \ OptionHandlerTest.cc SegmentManTest.cc BitfieldManTest.cc \ GlowFileAllocatorTest.cc NetrcTest.cc SingletonHolderTest.cc \ HttpHeaderTest.cc HttpResponseTest.cc SharedHandleTest.cc \ ChunkedEncodingTest.cc FileTest.cc OptionTest.cc Base64Test.cc \ - DataTest.cc DictionaryTest.cc ListTest.cc MetaFileUtilTest.cc \ - PeerMessageUtilTest.cc DefaultDiskWriterTest.cc \ - MultiDiskAdaptorTest.cc FeatureConfigTest.cc \ - ShareRatioSeedCriteriaTest.cc TimeSeedCriteriaTest.cc \ - SpeedCalcTest.cc DefaultPeerListProcessorTest.cc \ - AnnounceListTest.cc TrackerWatcherCommandTest.cc \ - MockPeerStorage.h FixedNumberRandomizer.h \ - ConsoleFileAllocationMonitorTest.cc \ - ChunkChecksumValidatorTest.cc $(am__append_1) $(am__append_2) + DefaultDiskWriterTest.cc FeatureConfigTest.cc SpeedCalcTest.cc \ + FixedNumberRandomizer.h ConsoleFileAllocationMonitorTest.cc \ + $(am__append_1) $(am__append_2) $(am__append_3) #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64 #aria2c_LDFLAGS = ${CPPUNIT_LIBS} @@ -504,6 +522,7 @@ distclean-compile: @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@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetaFileUtilTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkEntryTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkerTest.Po@am__quote@ diff --git a/test/MetalinkEntryTest.cc b/test/MetalinkEntryTest.cc index 0a3f9253..37be134a 100644 --- a/test/MetalinkEntryTest.cc +++ b/test/MetalinkEntryTest.cc @@ -64,17 +64,27 @@ void MetalinkEntryTest::testDropUnsupportedResource() { MetalinkEntry* entry = createTestEntry(); entry->dropUnsupportedResource(); - +#if defined ENABLE_SSL && ENABLE_BITTORRENT CPPUNIT_ASSERT_EQUAL(4, (int)entry->resources.size()); +#elif defined ENABLE_SSL || ENABLE_BITTORRENT + CPPUNIT_ASSERT_EQUAL(3, (int)entry->resources.size()); +#else + CPPUNIT_ASSERT_EQUAL(2, (int)entry->resources.size()); +#endif // ENABLE_MESSAGE_DIGEST + MetalinkResources::const_iterator itr = entry->resources.begin(); CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, - entry->resources.at(0)->type); + (*itr++)->type); CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_HTTP, - entry->resources.at(1)->type); + (*itr++)->type); +#ifdef ENABLE_BITTORRENT CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_BITTORRENT, - entry->resources.at(2)->type); + (*itr++)->type); +#endif // ENABLE_BITTORRENT +#ifdef ENABLE_SSL CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_HTTPS, - entry->resources.at(3)->type); + (*itr++)->type); +#endif // ENABLE_SSL } void MetalinkEntryTest::testReorderResourcesByPreference() { diff --git a/test/MockBtContext.h b/test/MockBtContext.h index 3965f1f8..165b87b5 100644 --- a/test/MockBtContext.h +++ b/test/MockBtContext.h @@ -16,6 +16,7 @@ private: unsigned char peerId[20]; FileEntries fileEntries; AnnounceTiers announceTiers; + Integers fastSet; public: MockBtContext():totalLength(0), pieceLength(0), @@ -117,6 +118,16 @@ public: memcpy(this->peerId, peerId, sizeof(this->peerId)); } + virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize) + { + return fastSet; + } + + void setFastSet(const Integers& fastSet) + { + this->fastSet = fastSet; + } + }; typedef SharedHandle MockBtContextHandle; diff --git a/test/MultiDiskAdaptorTest.cc b/test/MultiDiskAdaptorTest.cc index 00740bea..2f81012b 100644 --- a/test/MultiDiskAdaptorTest.cc +++ b/test/MultiDiskAdaptorTest.cc @@ -9,9 +9,6 @@ class MultiDiskAdaptorTest:public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(MultiDiskAdaptorTest); CPPUNIT_TEST(testWriteData); CPPUNIT_TEST(testReadData); -#ifdef ENABLE_MESSAGE_DIGEST - CPPUNIT_TEST(testMessageDigest); -#endif // ENABLE_MESSAGE_DIGEST CPPUNIT_TEST_SUITE_END(); private: Option* option; @@ -32,9 +29,6 @@ public: void testWriteData(); void testReadData(); -#ifdef ENABLE_MESSAGE_DIGEST - void testMessageDigest(); -#endif // ENABLE_MESSAGE_DIGEST }; @@ -137,28 +131,3 @@ void MultiDiskAdaptorTest::testReadData() { buf[25] = '\0'; CPPUNIT_ASSERT_EQUAL(string("1234567890ABCDEFGHIJKLMNO"), string((char*)buf)); } - -#ifdef ENABLE_MESSAGE_DIGEST - -void MultiDiskAdaptorTest::testMessageDigest() { - FileEntryHandle entry1(new FileEntry("file1r.txt", 15, 0)); - FileEntryHandle entry2(new FileEntry("file2r.txt", 7, 15)); - FileEntryHandle entry3(new FileEntry("file3r.txt", 3, 22)); - FileEntries entries; - entries.push_back(entry1); - entries.push_back(entry2); - entries.push_back(entry3); - - adaptor->setFileEntries(entries); - - adaptor->openFile(); - string sha1sum = adaptor->messageDigest(0, 25, DIGEST_ALGO_SHA1); - CPPUNIT_ASSERT_EQUAL(string("76495faf71ca63df66dce99547d2c58da7266d9e"), sha1sum); - sha1sum = adaptor->messageDigest(15, 7, DIGEST_ALGO_SHA1); - CPPUNIT_ASSERT_EQUAL(string("737660d816fb23c2d5bc74f62d9b01b852b2aaca"), sha1sum); - sha1sum = adaptor->messageDigest(10, 14, DIGEST_ALGO_SHA1); - CPPUNIT_ASSERT_EQUAL(string("6238bf61dd8df8f77156b2378e9e39cd3939680c"), sha1sum); - adaptor->closeFile(); -} - -#endif // ENABLE_MESSAGE_DIGEST diff --git a/test/RequestGroupManTest.cc b/test/RequestGroupManTest.cc index 39428139..2723a067 100644 --- a/test/RequestGroupManTest.cc +++ b/test/RequestGroupManTest.cc @@ -2,6 +2,7 @@ #include "ConsoleDownloadEngine.h" #include "CUIDCounter.h" #include "prefs.h" +#include "RequestFactory.h" #include using namespace std; @@ -60,6 +61,11 @@ void RequestGroupManTest::testGetInitialCommands() Option option; option.put(PREF_SPLIT, "1"); option.put(PREF_TIMEOUT, "10"); + + RequestFactoryHandle requestFactory = new RequestFactory(); + requestFactory->setOption(&option); + RequestFactorySingletonHolder::instance(requestFactory); + RequestGroupMan gm; RequestGroupHandle rg1 = new RequestGroup("aria2.tar.bz2.metalink", diff --git a/test/RequestTest.cc b/test/RequestTest.cc index 1af40569..3840ea22 100644 --- a/test/RequestTest.cc +++ b/test/RequestTest.cc @@ -296,12 +296,18 @@ void RequestTest::testMetalink() { Request req; bool v = req.setUrl("http://aria.rednoah.com/download/aria.tar.bz2#!metalink3!http://aria2.sourceforge.net/download/aria.metalink"); CPPUNIT_ASSERT(v); +#ifdef ENABLE_METALINK CPPUNIT_ASSERT_EQUAL(string("aria2.sourceforge.net"), req.getHost()); CPPUNIT_ASSERT_EQUAL(string("/download"), req.getDir()); CPPUNIT_ASSERT_EQUAL(string("aria.metalink"), req.getFile()); bool v2 = req.setUrl("http://aria.rednoah.com/download/aria.tar.bz2#!metalink3!"); CPPUNIT_ASSERT(!v2); +#else + CPPUNIT_ASSERT_EQUAL(string("aria.rednoah.com"), req.getHost()); + CPPUNIT_ASSERT_EQUAL(string("/download"), req.getDir()); + CPPUNIT_ASSERT_EQUAL(string("aria.tar.bz2"), req.getFile()); +#endif // ENABLE_METALINK } void RequestTest::testResolveHttpAuthConfig() diff --git a/test/TrackerWatcherCommandTest.cc b/test/TrackerWatcherCommandTest.cc index 93c8bad1..d3f6a3e1 100644 --- a/test/TrackerWatcherCommandTest.cc +++ b/test/TrackerWatcherCommandTest.cc @@ -22,20 +22,21 @@ class TrackerWatcherCommandTest:public CppUnit::TestFixture { CPPUNIT_TEST(testCreateCommand); CPPUNIT_TEST_SUITE_END(); private: - Option* op; + Option op; public: - TrackerWatcherCommandTest():op(new Option()) + TrackerWatcherCommandTest() { - op->put(PREF_TRACKER_MAX_TRIES, "10"); - RequestFactoryHandle requestFactory = new RequestFactory(); - requestFactory->setOption(op); - RequestFactorySingletonHolder::instance(requestFactory); } void setUp() { CUIDCounterHandle counter = new CUIDCounter(); CUIDCounterSingletonHolder::instance(counter); + + op.put(PREF_TRACKER_MAX_TRIES, "10"); + RequestFactoryHandle requestFactory = new RequestFactory(); + requestFactory->setOption(&op); + RequestFactorySingletonHolder::instance(requestFactory); } void testCreateCommand(); @@ -53,22 +54,24 @@ void TrackerWatcherCommandTest::testCreateCommand() { BtRuntimeHandle btRuntime; BtRegistry::registerBtRuntime(btContext->getInfoHashAsString(), btRuntime); - PieceStorageHandle pieceStorage(new DefaultPieceStorage(btContext, op)); + PieceStorageHandle pieceStorage(new DefaultPieceStorage(btContext, &op)); BtRegistry::registerPieceStorage(btContext->getInfoHashAsString(), pieceStorage); - PeerStorageHandle peerStorage(new DefaultPeerStorage(btContext, op)); + PeerStorageHandle peerStorage(new DefaultPeerStorage(btContext, &op)); BtRegistry::registerPeerStorage(btContext->getInfoHashAsString(), peerStorage); - BtAnnounceHandle btAnnounce(new DefaultBtAnnounce(btContext, op)); + BtAnnounceHandle btAnnounce(new DefaultBtAnnounce(btContext, &op)); BtRegistry::registerBtAnnounce(btContext->getInfoHashAsString(), btAnnounce); TorrentConsoleDownloadEngine* te = new TorrentConsoleDownloadEngine(); - te->option = op; + te->option = &op; te->_requestGroupMan = new RequestGroupMan(); TrackerWatcherCommand command(1, te, btContext); + RequestFactorySingletonHolder::instance()->createHttpAuthResolver(); + CPPUNIT_ASSERT(dynamic_cast(command.createCommand())); //cerr << btAnnounce->getAnnounceUrl() << endl; diff --git a/test/UtilTest.cc b/test/UtilTest.cc index 811ace7e..765cf53a 100644 --- a/test/UtilTest.cc +++ b/test/UtilTest.cc @@ -15,13 +15,7 @@ class UtilTest:public CppUnit::TestFixture { CPPUNIT_TEST(testStartsWith); // may be moved to other helper class in the future. CPPUNIT_TEST(testGetContentDispositionFilename); -#ifdef ENABLE_BITTORRENT - CPPUNIT_TEST(testComputeFastSet); -#endif CPPUNIT_TEST(testRandomAlpha); -#ifdef ENABLE_MESSAGE_DIGEST - CPPUNIT_TEST(testFileChecksum); -#endif CPPUNIT_TEST(testToUpper); CPPUNIT_TEST(testToLower); CPPUNIT_TEST(testUrldecode); @@ -42,15 +36,9 @@ public: void testEndsWith(); void testReplace(); void testStartsWith(); -#ifdef ENABLE_BITTORRENT - void testComputeFastSet(); -#endif // may be moved to other helper class in the future. void testGetContentDispositionFilename(); void testRandomAlpha(); -#ifdef ENABLE_MESSAGE_DIGEST - void testFileChecksum(); -#endif void testToUpper(); void testToLower(); void testUrldecode(); @@ -243,55 +231,10 @@ public: } }; -#ifdef ENABLE_BITTORRENT - -void UtilTest::testComputeFastSet() { - string ipaddr = "192.168.0.1"; - unsigned char infoHash[20]; - memset(infoHash, 0, sizeof(infoHash)); - infoHash[0] = 0xff; - - int pieces = 1000; - int fastSetSize = 10; - - Integers fastSet = Util::computeFastSet(ipaddr, infoHash, pieces, fastSetSize); - //for_each(fastSet.begin(), fastSet.end(), Printer()); - //cerr << endl; - int ans1[] = { 686, 459, 278, 200, 404, 834, 64, 203, 760, 950 }; - Integers ansSet1(&ans1[0], &ans1[10]); - CPPUNIT_ASSERT(equal(fastSet.begin(), fastSet.end(), ansSet1.begin())); - - ipaddr = "10.0.0.1"; - fastSet = Util::computeFastSet(ipaddr, infoHash, pieces, fastSetSize); - int ans2[] = { 568, 188, 466, 452, 550, 662, 109, 226, 398, 11 }; - Integers ansSet2(&ans2[0], &ans2[10]); - CPPUNIT_ASSERT(equal(fastSet.begin(), fastSet.end(), ansSet2.begin())); -} - -#endif - void UtilTest::testRandomAlpha() { - CPPUNIT_ASSERT_EQUAL(string("rUopvKRn"), Util::randomAlpha(8)); + CPPUNIT_ASSERT_EQUAL((size_t)8, Util::randomAlpha(8).size()); } -#ifdef ENABLE_MESSAGE_DIGEST - -void UtilTest::testFileChecksum() { - unsigned char buf[20]; - string filename = "4096chunk.txt"; - Util::fileChecksum(filename, buf, DIGEST_ALGO_SHA1); - string sha1 = Util::toHex(buf, 20); - CPPUNIT_ASSERT_EQUAL(string("608cabc0f2fa18c260cafd974516865c772363d5"), - sha1); - - Util::fileChecksum(filename, buf, DIGEST_ALGO_MD5); - string md5 = Util::toHex(buf, 16); - CPPUNIT_ASSERT_EQUAL(string("82a7348c2e03731109d0cf45a7325b88"), - md5); -} - -#endif - void UtilTest::testToUpper() { string src = "608cabc0f2fa18c260cafd974516865c772363d5"; string upp = "608CABC0F2FA18C260CAFD974516865C772363D5"; diff --git a/test/Xml2MetalinkProcessorTest.cc b/test/Xml2MetalinkProcessorTest.cc index 0c437135..801e05c1 100644 --- a/test/Xml2MetalinkProcessorTest.cc +++ b/test/Xml2MetalinkProcessorTest.cc @@ -28,54 +28,80 @@ CPPUNIT_TEST_SUITE_REGISTRATION( Xml2MetalinkProcessorTest ); void Xml2MetalinkProcessorTest::testParseFile() { Xml2MetalinkProcessor proc; try { - MetalinkerHandle metalinker = proc.parseFile("test.xml"); + MetalinkerHandle metalinker = proc.parseFile("test.xml"); - MetalinkEntries::iterator entryItr = metalinker->entries.begin(); - MetalinkEntryHandle entry1 = *entryItr; - CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.2.tar.bz2"), entry1->getPath()); - CPPUNIT_ASSERT_EQUAL((int64_t)0, entry1->getLength()); - CPPUNIT_ASSERT_EQUAL(string("0.5.2"), entry1->version); - CPPUNIT_ASSERT_EQUAL(string("en-US"), entry1->language); - CPPUNIT_ASSERT_EQUAL(string("Linux-x86"), entry1->os); - CPPUNIT_ASSERT_EQUAL(string("a96cf3f0266b91d87d5124cf94326422800b627d"), - entry1->checksum->getMessageDigest()); - CPPUNIT_ASSERT(DIGEST_ALGO_SHA1 == entry1->checksum->getDigestAlgo()); - - MetalinkResources::iterator resourceItr1 = entry1->resources.begin(); - MetalinkResourceHandle resource1 = *resourceItr1; - CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, resource1->type); - CPPUNIT_ASSERT_EQUAL(string("jp"), resource1->location); - CPPUNIT_ASSERT_EQUAL(100, resource1->preference); - CPPUNIT_ASSERT_EQUAL(string("ftp://ftphost/aria2-0.5.2.tar.bz2"), - resource1->url); - resourceItr1++; - MetalinkResourceHandle resource2 = *resourceItr1; - CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_HTTP, resource2->type); - CPPUNIT_ASSERT_EQUAL(string("us"), resource2->location); - CPPUNIT_ASSERT_EQUAL(100, resource2->preference); - CPPUNIT_ASSERT_EQUAL(string("http://httphost/aria2-0.5.2.tar.bz2"), - resource2->url); - - entryItr++; - - MetalinkEntryHandle entry2 = *entryItr; - CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.1.tar.bz2"), entry2->getPath()); - CPPUNIT_ASSERT_EQUAL((int64_t)345689, entry2->getLength()); - CPPUNIT_ASSERT_EQUAL(string("0.5.1"), entry2->version); - CPPUNIT_ASSERT_EQUAL(string("ja-JP"), entry2->language); - CPPUNIT_ASSERT_EQUAL(string("Linux-m68k"), entry2->os); + MetalinkEntries::iterator entryItr = metalinker->entries.begin(); + MetalinkEntryHandle entry1 = *entryItr; + CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.2.tar.bz2"), entry1->getPath()); + CPPUNIT_ASSERT_EQUAL((int64_t)0, entry1->getLength()); + CPPUNIT_ASSERT_EQUAL(string("0.5.2"), entry1->version); + CPPUNIT_ASSERT_EQUAL(string("en-US"), entry1->language); + CPPUNIT_ASSERT_EQUAL(string("Linux-x86"), entry1->os); #ifdef ENABLE_MESSAGE_DIGEST - CPPUNIT_ASSERT_EQUAL(string("4c255b0ed130f5ea880f0aa061c3da0487e251cc"), - entry2->checksum->getMessageDigest()); + CPPUNIT_ASSERT_EQUAL(string("a96cf3f0266b91d87d5124cf94326422800b627d"), + entry1->checksum->getMessageDigest()); + CPPUNIT_ASSERT_EQUAL(string("sha1"), entry1->checksum->getAlgo()); #endif // ENABLE_MESSAGE_DIGEST - CPPUNIT_ASSERT_EQUAL((int32_t)2, entry2->chunkChecksum->countChecksum()); - CPPUNIT_ASSERT_EQUAL((int32_t)262144, entry2->chunkChecksum->getChecksumLength()); - CPPUNIT_ASSERT_EQUAL(string("179463a88d79cbf0b1923991708aead914f26142"), - entry2->chunkChecksum->getChecksum(0)); - CPPUNIT_ASSERT_EQUAL(string("fecf8bc9a1647505fe16746f94e97a477597dbf3"), - entry2->chunkChecksum->getChecksum(1)); + MetalinkResources::iterator resourceItr1 = entry1->resources.begin(); + MetalinkResourceHandle resource1 = *resourceItr1; + CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_FTP, resource1->type); + CPPUNIT_ASSERT_EQUAL(string("jp"), resource1->location); + CPPUNIT_ASSERT_EQUAL(100, resource1->preference); + CPPUNIT_ASSERT_EQUAL(string("ftp://ftphost/aria2-0.5.2.tar.bz2"), + resource1->url); + resourceItr1++; + MetalinkResourceHandle resource2 = *resourceItr1; + CPPUNIT_ASSERT_EQUAL(MetalinkResource::TYPE_HTTP, resource2->type); + CPPUNIT_ASSERT_EQUAL(string("us"), resource2->location); + CPPUNIT_ASSERT_EQUAL(100, resource2->preference); + CPPUNIT_ASSERT_EQUAL(string("http://httphost/aria2-0.5.2.tar.bz2"), + resource2->url); + + entryItr++; + + MetalinkEntryHandle entry2 = *entryItr; + CPPUNIT_ASSERT_EQUAL(string("aria2-0.5.1.tar.bz2"), entry2->getPath()); + CPPUNIT_ASSERT_EQUAL((int64_t)345689, entry2->getLength()); + CPPUNIT_ASSERT_EQUAL(string("0.5.1"), entry2->version); + CPPUNIT_ASSERT_EQUAL(string("ja-JP"), entry2->language); + CPPUNIT_ASSERT_EQUAL(string("Linux-m68k"), entry2->os); +#ifdef ENABLE_MESSAGE_DIGEST + CPPUNIT_ASSERT_EQUAL(string("4c255b0ed130f5ea880f0aa061c3da0487e251cc"), + entry2->checksum->getMessageDigest()); + CPPUNIT_ASSERT_EQUAL((int32_t)2, entry2->chunkChecksum->countChecksum()); + CPPUNIT_ASSERT_EQUAL((int32_t)262144, entry2->chunkChecksum->getChecksumLength()); + CPPUNIT_ASSERT_EQUAL(string("179463a88d79cbf0b1923991708aead914f26142"), + entry2->chunkChecksum->getChecksum(0)); + CPPUNIT_ASSERT_EQUAL(string("fecf8bc9a1647505fe16746f94e97a477597dbf3"), + entry2->chunkChecksum->getChecksum(1)); + CPPUNIT_ASSERT_EQUAL(string("sha1"), entry2->checksum->getAlgo()); +#endif // ENABLE_MESSAGE_DIGEST + + entryItr++; + + // test case: verification hash is not provided + MetalinkEntryHandle entry3 = *entryItr; + CPPUNIT_ASSERT_EQUAL(string("NoVerificationHash"), entry3->getPath()); +#ifdef ENABLE_MESSAGE_DIGEST + CPPUNIT_ASSERT(entry3->checksum.isNull()); + CPPUNIT_ASSERT(entry3->chunkChecksum.isNull()); +#endif // ENABLE_MESSAGE_DIGEST + + entryItr++; + + // test case: unsupported verification hash is included + MetalinkEntryHandle entry4 = *entryItr; + CPPUNIT_ASSERT_EQUAL(string("UnsupportedVerificationHashTypeIncluded"), entry4->getPath()); +#ifdef ENABLE_MESSAGE_DIGEST + CPPUNIT_ASSERT_EQUAL(string("sha1"), + entry4->checksum->getAlgo()); + CPPUNIT_ASSERT_EQUAL(string("4c255b0ed130f5ea880f0aa061c3da0487e251cc"), + entry4->checksum->getMessageDigest()); + CPPUNIT_ASSERT_EQUAL(string("sha1"), + entry4->chunkChecksum->getAlgo()); +#endif // ENABLE_MESSAGE_DIGEST + - CPPUNIT_ASSERT(DIGEST_ALGO_SHA1 == entry2->checksum->getDigestAlgo()); } catch(Exception* e) { CPPUNIT_FAIL(e->getMsg()); delete e; diff --git a/test/test.xml b/test/test.xml index e63572d0..f071c064 100644 --- a/test/test.xml +++ b/test/test.xml @@ -11,8 +11,8 @@ en-US Linux-x86 - fc4d834e89c18c99b2615d902750948c a96cf3f0266b91d87d5124cf94326422800b627d + fc4d834e89c18c99b2615d902750948c ftp://ftphost/aria2-0.5.2.tar.bz2 @@ -25,8 +25,8 @@ ja-JP Linux-m68k - 92296e19c406d77d21bda0bb944eac46 4c255b0ed130f5ea880f0aa061c3da0487e251cc + 92296e19c406d77d21bda0bb944eac46 179463a88d79cbf0b1923991708aead914f26142 fecf8bc9a1647505fe16746f94e97a477597dbf3 @@ -37,5 +37,27 @@ http://httphost/aria2-0.5.1.tar.bz2 + + + ftp://host/file + + + + + 92296e19c406d77d21bda0bb944eac46 + 4c255b0ed130f5ea880f0aa061c3da0487e251cc + + 179463a88d79cbf0b1923991708aead914f26142 + fecf8bc9a1647505fe16746f94e97a477597dbf3 + + + 179463a88d79cbf0b1923991708aead914f26142 + fecf8bc9a1647505fe16746f94e97a477597dbf3 + + + + ftp://host/file + +