소스 검색

2007-08-08 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	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
Tatsuhiro Tsujikawa 18 년 전
부모
커밋
e85f9ccfd6
67개의 변경된 파일1233개의 추가작업 그리고 790개의 파일을 삭제
  1. 1 0
      AUTHORS
  2. 71 0
      ChangeLog
  3. 9 0
      config.h.in
  4. 197 2
      configure
  5. 9 2
      m4/openssl.m4
  6. 1 30
      src/AbstractDiskWriter.cc
  7. 0 5
      src/AbstractDiskWriter.h
  8. 0 4
      src/AbstractSingleDiskAdaptor.cc
  9. 5 3
      src/AbstractSingleDiskAdaptor.h
  10. 3 0
      src/BtContext.h
  11. 5 2
      src/BtPieceMessage.cc
  12. 0 8
      src/ByteArrayDiskWriter.h
  13. 15 19
      src/Checksum.h
  14. 3 3
      src/ChunkChecksum.h
  15. 11 67
      src/ChunkChecksumValidator.cc
  16. 7 37
      src/ChunkChecksumValidator.h
  17. 38 0
      src/DefaultBtContext.cc
  18. 14 0
      src/DefaultBtContext.h
  19. 2 4
      src/DefaultBtInteractive.cc
  20. 10 5
      src/DefaultPieceStorage.cc
  21. 2 8
      src/DiskAdaptor.h
  22. 1 7
      src/DiskAdaptorWriter.h
  23. 0 7
      src/DiskWriter.h
  24. 1 1
      src/DownloadCommand.cc
  25. 2 1
      src/IteratableChecksumValidator.cc
  26. 2 1
      src/IteratableChunkChecksumValidator.cc
  27. 5 0
      src/IteratableChunkChecksumValidator.h
  28. 3 2
      src/Makefile.am
  29. 16 9
      src/Makefile.in
  30. 101 0
      src/MessageDigestHelper.cc
  31. 77 0
      src/MessageDigestHelper.h
  32. 3 1
      src/MetalinkEntry.cc
  33. 2 3
      src/MetalinkEntry.h
  34. 4 0
      src/MetalinkRequestInfo.cc
  35. 14 51
      src/MultiDiskAdaptor.cc
  36. 7 7
      src/MultiDiskAdaptor.h
  37. 2 1
      src/Peer.cc
  38. 20 38
      src/SegmentMan.cc
  39. 5 10
      src/SegmentMan.h
  40. 3 2
      src/ShaVisitor.cc
  41. 3 8
      src/SimpleRandomizer.h
  42. 3 3
      src/TorrentRequestInfo.cc
  43. 0 87
      src/Util.cc
  44. 3 26
      src/Util.h
  45. 32 19
      src/Xml2MetalinkProcessor.cc
  46. 3 2
      src/main.cc
  47. 1 1
      src/message.h
  48. 63 0
      src/messageDigest.cc
  49. 48 13
      src/messageDigest.h
  50. 71 43
      test/ChunkChecksumValidatorTest.cc
  51. 30 0
      test/DefaultBtContextTest.cc
  52. 22 2
      test/DefaultBtRequestFactoryTest.cc
  53. 6 15
      test/DefaultDiskWriterTest.cc
  54. 27 1
      test/FeatureConfigTest.cc
  55. 3 2
      test/IteratableChecksumValidatorTest.cc
  56. 2 2
      test/IteratableChunkChecksumValidatorTest.cc
  57. 25 21
      test/Makefile.am
  58. 72 53
      test/Makefile.in
  59. 15 5
      test/MetalinkEntryTest.cc
  60. 11 0
      test/MockBtContext.h
  61. 0 31
      test/MultiDiskAdaptorTest.cc
  62. 6 0
      test/RequestGroupManTest.cc
  63. 6 0
      test/RequestTest.cc
  64. 13 10
      test/TrackerWatcherCommandTest.cc
  65. 1 58
      test/UtilTest.cc
  66. 72 46
      test/Xml2MetalinkProcessorTest.cc
  67. 24 2
      test/test.xml

+ 1 - 0
AUTHORS

@@ -1 +1,2 @@
 Tatsuhiro Tsujikawa <tujikawa at users dot sourceforge dot net>
+Ross Smith II <aria2spam at netebb dot com> (Windows port)

+ 71 - 0
ChangeLog

@@ -1,3 +1,70 @@
+2007-08-08  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	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  <tujikawa at rednoah dot com>
 
 	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  <tujikawa at rednoah dot com>
 
 	Make a2netcompat.h include a2io.h to fix compilation error:

+ 9 - 0
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 <fcntl.h> header file. */
 #undef HAVE_FCNTL_H
 
@@ -199,6 +205,9 @@
 /* Define to 1 if you have the <nl_types.h> 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
 

+ 197 - 2
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 <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> 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 <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#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 <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> 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 <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#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
 

+ 9 - 2
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
 

+ 1 - 30
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;

+ 0 - 5
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);

+ 0 - 4
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();

+ 5 - 3
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;
   }

+ 3 - 0
src/BtContext.h

@@ -84,6 +84,9 @@ public:
    * Returns the peer id of localhost, 20 byte length
    */
   virtual const unsigned char* getPeerId() = 0;
+
+  virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize) = 0;
+
 };
 
 typedef SharedHandle<BtContext> BtContextHandle;

+ 5 - 2
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) {

+ 0 - 8
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_

+ 15 - 19
src/Checksum.h

@@ -36,43 +36,39 @@
 #define _D_CHECKSUM_H_
 
 #include "common.h"
-#ifdef ENABLE_MESSAGE_DIGEST
-#include "messageDigest.h"
 
 class Checksum {
 private:
-  string md;
-  MessageDigestContext::DigestAlgo algo;
+  string _algo;
+  string _messageDigest;
 public:
-  Checksum(const string& md, MessageDigestContext::DigestAlgo algo):
-    md(md),
-    algo(algo) {}
+  // _messageDigest is ascii hexadecimal notation.
+  Checksum(const string& algo, const string& messageDigest):
+    _algo(algo), _messageDigest(messageDigest) {}
   Checksum():
-    algo(DIGEST_ALGO_SHA1) {}
+    _algo("sha1") {}
+
   ~Checksum() {}
 
   bool isEmpty() const {
-    return md.size() == 0;
+    return _messageDigest.size() == 0;
   }
 
   void setMessageDigest(const string& md) {
-    this->md = md;
+    this->_messageDigest = md;
   }
   const string& getMessageDigest() const {
-    return md;
+    return _messageDigest;
   }
   
-  void setDigestAlgo(MessageDigestContext::DigestAlgo algo) {
-    this->algo = algo;
+  void setAlgo(const string& algo) {
+    this->_algo = algo;
   }
-  const MessageDigestContext::DigestAlgo& getDigestAlgo() const {
-    return algo;
+
+  const string& getAlgo() const {
+    return _algo;
   }
 };
-#else
-class Checksum {
-};
-#endif // ENABLE_MESSAGE_DIGEST
 
 typedef SharedHandle<Checksum> ChecksumHandle;
 

+ 3 - 3
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;
   }

+ 11 - 67
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

+ 7 - 37
src/ChunkChecksumValidator.h

@@ -36,63 +36,33 @@
 #define _D_CHUNK_CHECKSUM_VALIDATOR_H_
 
 #include "common.h"
-#include "DiskWriter.h"
-#include "BitfieldMan.h"
-#ifdef ENABLE_MESSAGE_DIGEST
-#include "messageDigest.h"
-#endif // ENABLE_MESSAGE_DIGEST
 #include "LogFactory.h"
 #include "FileAllocationMonitor.h"
 #include "NullFileAllocationMonitor.h"
+#include "IteratableChunkChecksumValidator.h"
 
 class ChunkChecksumValidator {
-#ifdef ENABLE_MESSAGE_DIGEST
-protected:
-  DiskWriterHandle diskWriter;
-
-  MessageDigestContext::DigestAlgo algo;
+private:
+  IteratableChunkChecksumValidatorHandle _validator;
 
   FileAllocationMonitorHandle fileAllocationMonitor;
 
   const Logger* logger;
-
-  void validateSameLengthChecksum(BitfieldMan* bitfieldMan,
-				  int32_t index,
-				  const string& expectedChecksum,
-				  int32_t thisLength,
-				  int32_t checksumLength);
-
-  void validateDifferentLengthChecksum(BitfieldMan* bitfieldMan,
-				       int32_t index,
-				       const string& expectedChecksum,
-				       int32_t thisLength,
-				       int32_t checksumLength);
 public:
-  ChunkChecksumValidator():
-    diskWriter(0),
-    algo(DIGEST_ALGO_SHA1),
+  ChunkChecksumValidator(const IteratableChunkChecksumValidatorHandle v):
+    _validator(v),
     fileAllocationMonitor(new NullFileAllocationMonitor()),
     logger(LogFactory::getInstance())
   {}
 
   ~ChunkChecksumValidator() {}
 
-  void validate(BitfieldMan* bitfieldMan, 
-		const Strings& checksums,
-		int32_t checksumLength);
-
-  void setDiskWriter(const DiskWriterHandle& diskWriter) {
-    this->diskWriter = diskWriter;
-  }
-
-  void setDigestAlgo(const MessageDigestContext::DigestAlgo& algo) {
-    this->algo = algo;
-  }
+  void validate();
 
   void setFileAllocationMonitor(const FileAllocationMonitorHandle& monitor) {
     this->fileAllocationMonitor = monitor;
   }
-#endif // ENABLE_MESSAGE_DIGEST
 };
 
+typedef SharedHandle<ChunkChecksumValidator> ChunkChecksumValidatorHandle;
 #endif // _D_CHUNK_CHECKSUM_VALIDATOR_H_

+ 38 - 0
src/DefaultBtContext.cc

@@ -40,6 +40,8 @@
 #include "DlAbortEx.h"
 #include "ShaVisitor.h"
 #include "Util.h"
+#include "MessageDigestHelper.h"
+#include "a2netcompat.h"
 #include <libgen.h>
 
 DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-") {}
@@ -245,3 +247,39 @@ int32_t DefaultBtContext::getPieceLength() const {
 int32_t DefaultBtContext::getNumPieces() const {
   return numPieces;
 }
+
+Integers DefaultBtContext::computeFastSet(const string& ipaddr, int32_t fastSetSize)
+{
+  Integers fastSet;
+  struct in_addr saddr;
+  if(inet_aton(ipaddr.c_str(), &saddr) == 0) {
+    abort();
+  }
+  unsigned char tx[24];
+  memcpy(tx, (void*)&saddr.s_addr, 4);
+  if((tx[0] & 0x80) == 0 || (tx[0] & 0x40) == 0) {
+    tx[2] = 0x00;
+    tx[3] = 0x00;
+  } else {
+    tx[3] = 0x00;
+  }
+  memcpy(tx+4, infoHash, 20);
+  unsigned char x[20];
+  MessageDigestHelper::digest(x, sizeof(x), "sha1", tx, 24);
+  while((int32_t)fastSet.size() < fastSetSize) {
+    for(int32_t i = 0; i < 5 && (int32_t)fastSet.size() < fastSetSize; i++) {
+      int32_t j = i*4;
+      uint32_t ny;
+      memcpy(&ny, x+j, 4);
+      uint32_t y = ntohl(ny);
+      int32_t index = y%numPieces;
+      if(find(fastSet.begin(), fastSet.end(), index) == fastSet.end()) {
+	fastSet.push_back(index);
+      }
+    }
+    unsigned char temp[20];
+    MessageDigestHelper::digest(temp, sizeof(temp), "sha1", x, sizeof(x));
+    memcpy(x, temp, sizeof(x));
+  }
+  return fastSet;
+}

+ 14 - 0
src/DefaultBtContext.h

@@ -107,12 +107,26 @@ private:
     return (const unsigned char*)peerId.c_str();
   }
 
+  virtual Integers computeFastSet(const string& ipaddr, int32_t fastSetSize);
+
   string generatePeerId() const;
 
   void setPeerIdPrefix(const string& peerIdPrefix)
   {
     _peerIdPrefix = peerIdPrefix;
   }
+
+  // for unit test
+  void setInfoHash(const unsigned char* infoHash)
+  {
+    memcpy(this->infoHash, infoHash, sizeof(this->infoHash));
+  }
+
+  void setNumPieces(int32_t numPieces)
+  {
+    this->numPieces = numPieces;
+  }
+      
 };
 
 typedef SharedHandle<DefaultBtContext> DefaultBtContextHandle;

+ 2 - 4
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));

+ 10 - 5
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();
 }

+ 2 - 8
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;
   }

+ 1 - 7
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();
   }
 };
 

+ 0 - 7
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;
 

+ 1 - 1
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.

+ 2 - 1
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();
 }

+ 2 - 1
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

+ 5 - 0
src/IteratableChunkChecksumValidator.h

@@ -89,6 +89,11 @@ public:
   {
     return _bitfield->getTotalLength();
   }
+
+  ChunkChecksumHandle getChunkChecksum()
+  {
+    return _chunkChecksum;
+  }
 };
 
 typedef SharedHandle<IteratableChunkChecksumValidator> IteratableChunkChecksumValidatorHandle;

+ 3 - 2
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

+ 16 - 9
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:

+ 101 - 0
src/MessageDigestHelper.cc

@@ -0,0 +1,101 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "MessageDigestHelper.h"
+#include "messageDigest.h"
+#include "DlAbortEx.h"
+#include "message.h"
+#include "DefaultDiskWriter.h"
+#include "Util.h"
+#include <errno.h>
+
+string MessageDigestHelper::digest(const string& algo, DiskWriterHandle diskWriter, int64_t offset, int64_t length)
+{
+  MessageDigestContext ctx;
+  ctx.trySetAlgo(algo);
+  ctx.digestInit();
+
+  int32_t BUFSIZE = 4096;
+  char BUF[BUFSIZE];
+  int64_t iteration = length/BUFSIZE;
+  int32_t tail = length%BUFSIZE;
+  for(int64_t i = 0; i < iteration; ++i) {
+    int32_t readLength = diskWriter->readData(BUF, BUFSIZE, offset);
+    if(readLength != BUFSIZE) {
+      throw new DlAbortEx(EX_FILE_READ, "n/a", strerror(errno));
+    }
+    ctx.digestUpdate(BUF, readLength);
+    offset += readLength;
+  }
+  if(tail) {
+    int32_t readLength = diskWriter->readData(BUF, tail, offset);
+    if(readLength != tail) {
+      throw new DlAbortEx(EX_FILE_READ, "n/a", strerror(errno));
+    }
+    ctx.digestUpdate(BUF, readLength);
+  }
+  string rawMD = ctx.digestFinal();
+  return Util::toHex((const unsigned char*)rawMD.c_str(), rawMD.size());
+}
+
+string MessageDigestHelper::digest(const string& algo, const string& filename)
+{
+  DiskWriterHandle writer = new DefaultDiskWriter();
+  writer->openExistingFile(filename);
+  return digest(algo, writer);
+}
+
+string MessageDigestHelper::digest(const string& algo, const void* data, int32_t length)
+{
+  MessageDigestContext ctx;
+  ctx.trySetAlgo(algo);
+  ctx.digestInit();
+  ctx.digestUpdate(data, length);
+  string rawMD = ctx.digestFinal();
+  return Util::toHex((const unsigned char*)rawMD.c_str(), rawMD.size());
+}
+
+void MessageDigestHelper::digest(unsigned char* md, int32_t mdLength,
+				 const string& algo, const void* data, int32_t length)
+{
+  if(mdLength < MessageDigestContext::digestLength(algo)) {
+    throw new DlAbortEx("Insufficient space for storing message digest: %d required, but only %d is allocated", MessageDigestContext::digestLength(algo), mdLength);
+  }
+  MessageDigestContext ctx;
+  ctx.trySetAlgo(algo);
+  ctx.digestInit();
+  ctx.digestUpdate(data, length);
+  ctx.digestFinal(md);
+}
+

+ 77 - 0
src/MessageDigestHelper.h

@@ -0,0 +1,77 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_MESSAGE_DIGEST_HELPER_H_
+#define _D_MESSAGE_DIGEST_HELPER_H_
+
+#include "common.h"
+#include "DiskWriter.h"
+
+class MessageDigestHelper {
+public:
+  /**
+   * Returns message digest in hexadecimal notation.
+   * Digest algorithm is specified by algo.
+   */
+  static string digest(const string& algo, DiskWriterHandle diskWriter, int64_t offset, int64_t length);
+
+  /**
+   * Calculates message digest of file opened by diskWriter.
+   */
+  static string digest(const string& algo, DiskWriterHandle diskWriter)
+  {
+    return digest(algo, diskWriter, 0, diskWriter->size());
+  }
+
+  /**
+   * Calculates message digest of file denoted by filename.
+   */
+  static string digest(const string& algo, const string& filename);
+
+  static string digest(const string& algo, const void* data, int32_t length);
+
+  static string digestString(const string& algo, const string& data)
+  {
+    return digest(algo, data.c_str(), data.size());
+  }
+
+  /**
+   * Stores *raw* message digest into md.
+   * Throws exception when mdLength is less than the size of message digest.
+   */
+  static void digest(unsigned char* md, int32_t mdLength,
+		     const string& algo, const void* data, int32_t length);
+};
+
+#endif // _D_MESSAGE_DIGEST_HELPER_H_

+ 3 - 1
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

+ 2 - 3
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
     }

+ 4 - 0
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);

+ 14 - 51
src/MultiDiskAdaptor.cc

@@ -37,7 +37,6 @@
 #include "DlAbortEx.h"
 #include "message.h"
 #include "Util.h"
-#include <errno.h>
 
 void MultiDiskAdaptor::resetDiskWriterEntries() {
   diskWriterEntries.clear();
@@ -169,58 +168,11 @@ int32_t MultiDiskAdaptor::readData(unsigned char* data, int32_t len, int64_t off
   return totalReadLength;
 }
 
-void MultiDiskAdaptor::hashUpdate(MessageDigestContext& ctx,
-				  const DiskWriterEntryHandle& entry,
-				  int64_t offset, int64_t length)
-{
-  int32_t BUFSIZE = 16*1024;
-  unsigned char buf[BUFSIZE];
-  for(int64_t i = 0; i < length/BUFSIZE; i++) {
-    if(BUFSIZE != entry->getDiskWriter()->readData(buf, BUFSIZE, offset)) {
-      throw new DlAbortEx(EX_FILE_SHA1SUM, "", strerror(errno));
-    }
-    ctx.digestUpdate(buf, BUFSIZE);
-    offset += BUFSIZE;
-  }
-  int32_t r = length%BUFSIZE;
-  if(r > 0) {
-    if((int32_t)r != entry->getDiskWriter()->readData(buf, r, offset)) {
-      throw new DlAbortEx(EX_FILE_SHA1SUM, "", strerror(errno));
-    }
-    ctx.digestUpdate(buf, r);
-  }
-}
-
-string MultiDiskAdaptor::messageDigest(int64_t offset, int64_t length,
-				       const MessageDigestContext::DigestAlgo& algo) {
-  int64_t fileOffset = offset;
-  bool reading = false;
-  int32_t rem = length;
-  MessageDigestContext ctx(algo);
-  ctx.digestInit();
-
-  for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
-      itr != diskWriterEntries.end() && rem != 0; itr++) {
-    if(isInRange(*itr, offset) || reading) {
-      int32_t readLength = calculateLength((*itr), fileOffset, rem);
-      hashUpdate(ctx, *itr, fileOffset, readLength);
-      rem -= readLength;
-      reading = true;
-      fileOffset = 0;
-    } else {
-      fileOffset -= (*itr)->getFileEntry()->getLength();
-    }
-  }
-  if(!reading) {
-    throw new DlAbortEx(EX_FILE_OFFSET_OUT_OF_RANGE, Util::llitos(offset, true).c_str());
-  }
-  unsigned char hashValue[20];
-  ctx.digestFinal(hashValue);
-  return Util::toHex(hashValue, 20);
-}
-
 bool MultiDiskAdaptor::fileExists()
 {
+  if(diskWriterEntries.empty()) {
+    resetDiskWriterEntries();
+  }
   for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
       itr != diskWriterEntries.end(); itr++) {
     if((*itr)->fileExists(getTopDirPath())) {
@@ -229,3 +181,14 @@ bool MultiDiskAdaptor::fileExists()
   }
   return false;
 }
+
+// TODO call DiskWriter::openFile() before calling this function.
+int64_t MultiDiskAdaptor::size() const
+{
+  int64_t size = 0;
+  for(DiskWriterEntries::const_iterator itr = diskWriterEntries.begin();
+      itr != diskWriterEntries.end(); itr++) {
+    size += (*itr)->size();
+  }
+  return size;
+}

+ 7 - 7
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;
   }

+ 2 - 1
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);
 }
 
 /*

+ 20 - 38
src/SegmentMan.cc

@@ -41,7 +41,7 @@
 #include "LogFactory.h"
 #include "BitfieldManFactory.h"
 #ifdef ENABLE_MESSAGE_DIGEST
-#include "ChunkChecksumValidator.h"
+#include "MessageDigestHelper.h"
 #endif // ENABLE_MESSAGE_DIGEST
 #include "a2io.h"
 #include <errno.h>
@@ -54,11 +54,6 @@ SegmentMan::SegmentMan():logger(LogFactory::getInstance()),
 			 dir("."),
 			 errors(0),
 			 diskWriter(0)
-#ifdef ENABLE_MESSAGE_DIGEST
-			,
-			 chunkHashLength(0),
-			 digestAlgo(DIGEST_ALGO_SHA1)
-#endif // ENABLE_MESSAGE_DIGEST
 {}
 
 SegmentMan::~SegmentMan() {
@@ -474,29 +469,16 @@ void SegmentMan::markPieceDone(int64_t length)
 }
 
 #ifdef ENABLE_MESSAGE_DIGEST
-void SegmentMan::checkIntegrity()
-{
-  logger->notice(MSG_VALIDATING_FILE,
-		 getFilePath().c_str());
-  ChunkChecksumValidator v;
-  v.setDigestAlgo(digestAlgo);
-  v.setDiskWriter(diskWriter);
-  v.setFileAllocationMonitor(FileAllocationMonitorFactory::getFactory()->createNewMonitor());
-  v.validate(bitfield, pieceHashes, chunkHashLength);
-}
-#endif // ENABLE_MESSAGE_DIGEST
-
-#ifdef ENABLE_MESSAGE_DIGEST
-bool SegmentMan::isChunkChecksumValidationReady() const {
-  return bitfield && totalSize > 0 &&
-    ((int64_t)pieceHashes.size())*chunkHashLength >= totalSize;
+bool SegmentMan::isChunkChecksumValidationReady(const ChunkChecksumHandle& chunkChecksum) const {
+  return !chunkChecksum.isNull() && bitfield && totalSize > 0 &&
+    chunkChecksum->getEstimatedDataLength() >= totalSize;
 }
 #endif // ENABLE_MESSAGE_DIGEST
 
 #ifdef ENABLE_MESSAGE_DIGEST
-void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment)
+void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment, const ChunkChecksumHandle& chunkChecksum)
 {
-  if(!isChunkChecksumValidationReady()) {
+  if(!isChunkChecksumValidationReady(chunkChecksum)) {
     return;
   }
   int32_t hashStartIndex;
@@ -504,13 +486,13 @@ void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment)
   Util::indexRange(hashStartIndex, hashEndIndex,
 		   segment->getPosition(),
 		   segment->writtenLength,
-		   chunkHashLength);
-  if(!bitfield->isBitSetOffsetRange((int64_t)hashStartIndex*chunkHashLength,
-				    chunkHashLength)) {
+		   chunkChecksum->getChecksumLength());
+  if(!bitfield->isBitSetOffsetRange((int64_t)hashStartIndex*chunkChecksum->getChecksumLength(),
+				    chunkChecksum->getChecksumLength())) {
     ++hashStartIndex;
   }
-  if(!bitfield->isBitSetOffsetRange((int64_t)hashEndIndex*chunkHashLength,
-				    chunkHashLength)) {
+  if(!bitfield->isBitSetOffsetRange((int64_t)hashEndIndex*chunkChecksum->getChecksumLength(),
+				    chunkChecksum->getChecksumLength())) {
     --hashEndIndex;
   }
   logger->debug("hashStartIndex=%d, hashEndIndex=%d",
@@ -519,27 +501,27 @@ void SegmentMan::tryChunkChecksumValidation(const SegmentHandle& segment)
     logger->debug(MSG_NO_CHUNK_CHECKSUM);
     return;
   }
-  int64_t hashOffset = ((int64_t)hashStartIndex)*chunkHashLength;
+  int64_t hashOffset = ((int64_t)hashStartIndex)*chunkChecksum->getChecksumLength();
   int32_t startIndex;
   int32_t endIndex;
   Util::indexRange(startIndex, endIndex,
 		   hashOffset,
-		   (hashEndIndex-hashStartIndex+1)*chunkHashLength,
+		   (hashEndIndex-hashStartIndex+1)*chunkChecksum->getChecksumLength(),
 		   bitfield->getBlockLength());
   logger->debug("startIndex=%d, endIndex=%d", startIndex, endIndex);
   if(bitfield->isBitRangeSet(startIndex, endIndex)) {
     for(int32_t index = hashStartIndex; index <= hashEndIndex; ++index) {
-      int64_t offset = ((int64_t)index)*chunkHashLength;
+      int64_t offset = ((int64_t)index)*chunkChecksum->getChecksumLength();
       int32_t dataLength =
-	offset+chunkHashLength <= totalSize ? chunkHashLength : totalSize-offset;
-      string actualChecksum = diskWriter->messageDigest(offset, dataLength, digestAlgo);
-      string expectedChecksum = pieceHashes[index];
-      if(expectedChecksum == actualChecksum) {
-	logger->info(MSG_GOOD_CHUNK_CHECKSUM);
+	offset+chunkChecksum->getChecksumLength() <= totalSize ?
+	chunkChecksum->getChecksumLength() : totalSize-offset;
+      string actualChecksum = MessageDigestHelper::digest(chunkChecksum->getAlgo(), diskWriter, offset, dataLength);
+      if(chunkChecksum->validateChunk(actualChecksum, index)) {
+	logger->info(MSG_GOOD_CHUNK_CHECKSUM, actualChecksum.c_str());
       } else {
 	logger->info(EX_INVALID_CHUNK_CHECKSUM,
 		     index, Util::llitos(offset, true).c_str(),
-		     expectedChecksum.c_str(), actualChecksum.c_str());
+		     chunkChecksum->getChecksum(index).c_str(), actualChecksum.c_str());
 	logger->debug("Unset bit from %d to %d(inclusive)", startIndex, endIndex);
 	bitfield->unsetBitRange(startIndex, endIndex);
 	break;

+ 5 - 10
src/SegmentMan.h

@@ -43,6 +43,9 @@
 #include "Request.h"
 #include "BitfieldMan.h"
 #include "PeerStat.h"
+#ifdef ENABLE_MESSAGE_DIGEST
+# include "ChunkChecksum.h"
+#endif // ENABLE_MESSAGE_DIGEST
 
 using namespace std;
 
@@ -157,12 +160,6 @@ public:
   DiskWriterHandle diskWriter;
   Requests reserved;
 
-#ifdef ENABLE_MESSAGE_DIGEST
-  Strings pieceHashes;
-  int32_t chunkHashLength;
-  MessageDigestContext::DigestAlgo digestAlgo;
-#endif // ENABLE_MESSAGE_DIGEST
-
   SegmentMan();
   ~SegmentMan();
   
@@ -300,11 +297,9 @@ public:
   }
 
 #ifdef ENABLE_MESSAGE_DIGEST
-  void checkIntegrity();
-
-  void tryChunkChecksumValidation(const SegmentHandle& segment);
+  void tryChunkChecksumValidation(const SegmentHandle& segment, const ChunkChecksumHandle& chunkChecksum);
 
-  bool isChunkChecksumValidationReady() const;
+  bool isChunkChecksumValidationReady(const ChunkChecksumHandle& chunkChecksum) const;
 #endif // ENABLE_MESSAGE_DIGEST
 };
 

+ 3 - 2
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();
 }
 

+ 3 - 8
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));

+ 3 - 3
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();
     }
   }
 

+ 0 - 87
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, 

+ 3 - 26
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 <string>
+#include "FileEntry.h"
 #include <utility>
 #include <deque>
-#include <stdio.h>
 #include <ostream>
 
 #define STRTOLL(X) strtoll(X, (char**)NULL, 10);
@@ -111,28 +106,10 @@ public:
   // this function temporarily put here
   static string getContentDispositionFilename(const string& header);
 
-  // digest must be at least 20 bytes long.
-#ifdef ENABLE_MESSAGE_DIGEST
-  static void sha1Sum(unsigned char* digest, const void* data, int32_t dataLength);
-  static string simpleMessageDigest(const string& data);
-#endif // ENABLE_MESSAGE_DIGEST
-
-  // Before call this method, allocate enough memory to the parameter "digest".
-  // For sha1, you need 20 bytes. For md5, 16 bytes.
-#ifdef ENABLE_MESSAGE_DIGEST
-  static void fileChecksum(const string& filename, unsigned char* digest,
-			   MessageDigestContext::DigestAlgo algo);
-#endif // ENABLE_MESSAGE_DIGEST
-
-#ifdef ENABLE_BITTORRENT
-  static Integers computeFastSet(string ipaddr, const unsigned char* infoHash,
-				int32_t pieces, int32_t fastSetSize);
-#endif // ENABLE_BITTORRENT
-
   static int32_t countBit(uint32_t n);
-
+  
   static string randomAlpha(int32_t length);
-
+  
   static string toUpper(const string& src);
 
   static string toLower(const string& src);

+ 32 - 19
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
 

+ 3 - 2
src/main.cc

@@ -71,7 +71,6 @@ extern int optind, opterr, optopt;
 
 #ifdef ENABLE_METALINK
 #include "MetalinkRequestInfo.h"
-#include "Xml2MetalinkProcessor.h"
 #endif
 
 #ifdef HAVE_LIBSSL
@@ -89,6 +88,9 @@ void showVersion() {
   cout << PACKAGE << _(" version ") << PACKAGE_VERSION << endl;
   cout << "**Configuration**" << endl;
   cout << FeatureConfig::getInstance()->getConfigurationSummary();
+#ifdef ENABLE_MESSAGE_DIGEST
+  cout << "message digest algorithms: " << MessageDigestContext::getSupportedAlgoString() << endl;
+#endif // ENABLE_MESSAGE_DIGEST
   cout << endl;
   cout << "Copyright (C) 2006, 2007 Tatsuhiro Tsujikawa" << endl;
   cout << endl;
@@ -109,7 +111,6 @@ void showVersion() {
   cout << endl;
   cout << _("Contact Info:") << endl;
   cout << "Tatsuhiro Tsujikawa <tujikawa at users dot sourceforge dot net>" << endl;
-  cout << "Ross Smith II <aria2spam at netebb dot com> (Windows port)" << endl;
   cout << endl;
 
 }

+ 1 - 1
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.")

+ 63 - 0
src/messageDigest.cc

@@ -0,0 +1,63 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "messageDigest.h"
+
+static MessageDigestContext::DigestAlgoMap::value_type digests[] = {
+#ifdef HAVE_LIBSSL
+  MessageDigestContext::DigestAlgoMap::value_type("md5", EVP_md5()),
+  MessageDigestContext::DigestAlgoMap::value_type("sha1", EVP_sha1()),
+# ifdef HAVE_EVP_SHA256
+  MessageDigestContext::DigestAlgoMap::value_type("sha256", EVP_sha256()),
+# endif // HAVE_EVP_SHA256
+#elif HAVE_LIBGCRYPT
+  MessageDigestContext::DigestAlgoMap::value_type("md5", GCRY_MD_MD5),
+  MessageDigestContext::DigestAlgoMap::value_type("sha1", GCRY_MD_SHA1),
+  MessageDigestContext::DigestAlgoMap::value_type("sha256", GCRY_MD_SHA256),
+#endif // HAVE_LIBGCRYPT
+};
+
+MessageDigestContext::DigestAlgoMap
+MessageDigestContext::digestAlgos(&digests[0],
+				  &digests[sizeof(digests)/sizeof(DigestAlgoMap::value_type)]);
+
+string MessageDigestContext::digestFinal()
+{
+  int32_t length = digestLength(algo);
+  unsigned char* rawMD = new unsigned char[length];
+  digestFinal(rawMD);
+  string rawMDString(&rawMD[0], &rawMD[length]);
+  delete [] rawMD;
+  return rawMDString;
+}

+ 48 - 13
src/messageDigest.h

@@ -36,10 +36,8 @@
 #define _D_MESSAGE_DIGEST_H_
 
 #include "common.h"
-
-#ifdef ENABLE_SSL
-
-#define MAX_MD_LENGTH (16+20)
+#include "FatalException.h"
+#include <map>
 
 #ifdef HAVE_LIBSSL
 #include <openssl/evp.h>
@@ -53,14 +51,11 @@ class MessageDigestContext {
 public:
 #ifdef HAVE_LIBSSL
   typedef const EVP_MD* DigestAlgo;
-# define DIGEST_ALGO_MD5 EVP_md5()
-# define DIGEST_ALGO_SHA1 EVP_sha1()
 #endif // HAVE_LIBSSL
 #ifdef HAVE_LIBGCRYPT
   typedef int32_t DigestAlgo;
-# define DIGEST_ALGO_MD5 GCRY_MD_MD5
-# define DIGEST_ALGO_SHA1 GCRY_MD_SHA1
 #endif // HAVE_LIBGCRYPT
+  typedef map<string, MessageDigestContext::DigestAlgo> DigestAlgoMap;
 private:
 #ifdef HAVE_LIBSSL
   EVP_MD_CTX ctx;
@@ -69,17 +64,58 @@ private:
   gcry_md_hd_t ctx;
 #endif // HAVE_LIBGCRYPT  
   DigestAlgo algo;
+
+  static DigestAlgoMap digestAlgos;
 public:
-  MessageDigestContext():
-    algo(DIGEST_ALGO_SHA1) {}
-  MessageDigestContext(DigestAlgo algo):
-    algo(algo) {}
+  MessageDigestContext():algo(getDigestAlgo("sha1"))
+  {}
 
   ~MessageDigestContext()
   {
     digestFree();
   }
 
+  void trySetAlgo(const string& algostring)
+  {
+    algo = getDigestAlgo(algostring);
+  }
+
+  static bool supports(const string& algostring)
+  {
+    DigestAlgoMap::const_iterator itr = digestAlgos.find(algostring);
+    if(itr == digestAlgos.end()) {
+      return false;
+    } else {
+      return true;
+    }
+  }
+
+  static DigestAlgo getDigestAlgo(const string& algostring)
+  {
+    DigestAlgoMap::const_iterator itr = digestAlgos.find(algostring);
+    if(itr == digestAlgos.end()) {
+      throw new FatalException("Digest algorithm %s is not supported.", algostring.c_str());
+    }
+    return (*itr).second;
+  }
+
+  static string getSupportedAlgoString()
+  {
+    string algos;
+    for(DigestAlgoMap::const_iterator itr = digestAlgos.begin();
+	itr != digestAlgos.end(); ++itr) {
+      algos += (*itr).first+" ";
+    }
+    return algos;
+  }
+
+  static int digestLength(const string& algostring)
+  {
+    return digestLength(getDigestAlgo(algostring));
+  }
+
+  string digestFinal();
+
 #if defined(HAVE_OLD_LIBSSL)
   void digestInit() {EVP_DigestInit(&ctx, algo);}
   void digestReset() {EVP_DigestInit(&ctx, algo);}
@@ -147,5 +183,4 @@ public:
 #endif // HAVE_LIBGCRYPT
 };
 typedef SharedHandle<MessageDigestContext> MessageDigestContextHandle;
-#endif // ENABLE_SSL
 #endif // _D_MESSAGE_DIGEST_H_

+ 71 - 43
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 */
 }
+

+ 30 - 0
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()));
+}

+ 22 - 2
test/DefaultBtRequestFactoryTest.cc

@@ -55,6 +55,24 @@ public:
     }
   };
 
+  class SortMockBtRequestMessage {
+  public:
+    bool operator()(const SharedHandle<MockBtRequestMessage>& a,
+		    const SharedHandle<MockBtRequestMessage>& 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() {

+ 6 - 15
test/DefaultDiskWriterTest.cc

@@ -1,5 +1,4 @@
 #include "DefaultDiskWriter.h"
-#include <string>
 #include <cppunit/extensions/HelperMacros.h>
 
 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());
 }
+

+ 27 - 1
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());
 }

+ 3 - 2
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");

+ 2 - 2
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);

+ 25 - 21
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

+ 72 - 53
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_METALINK_TRUE@am__append_2 = MetalinkerTest.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_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@

+ 15 - 5
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() {

+ 11 - 0
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<MockBtContext> MockBtContextHandle;

+ 0 - 31
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

+ 6 - 0
test/RequestGroupManTest.cc

@@ -2,6 +2,7 @@
 #include "ConsoleDownloadEngine.h"
 #include "CUIDCounter.h"
 #include "prefs.h"
+#include "RequestFactory.h"
 #include <cppunit/extensions/HelperMacros.h>
 
 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",

+ 6 - 0
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()

+ 13 - 10
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<HttpInitiateConnectionCommand*>(command.createCommand()));
     //cerr << btAnnounce->getAnnounceUrl() << endl;
     

+ 1 - 58
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";

+ 72 - 46
test/Xml2MetalinkProcessorTest.cc

@@ -28,54 +28,80 @@ CPPUNIT_TEST_SUITE_REGISTRATION( Xml2MetalinkProcessorTest );
 void Xml2MetalinkProcessorTest::testParseFile() {
   Xml2MetalinkProcessor proc;
   try {
-  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);
+    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);
+#ifdef ENABLE_MESSAGE_DIGEST
+    CPPUNIT_ASSERT_EQUAL(string("a96cf3f0266b91d87d5124cf94326422800b627d"),
+			 entry1->checksum->getMessageDigest());
+    CPPUNIT_ASSERT_EQUAL(string("sha1"), entry1->checksum->getAlgo());
+#endif // ENABLE_MESSAGE_DIGEST
+    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(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
-  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(DIGEST_ALGO_SHA1 == entry2->checksum->getDigestAlgo());
+
+    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
+
+
   } catch(Exception* e) {
     CPPUNIT_FAIL(e->getMsg());
     delete e;

+ 24 - 2
test/test.xml

@@ -11,8 +11,8 @@
       <language>en-US</language>
       <os>Linux-x86</os>
       <verification>
-        <hash type="md5">fc4d834e89c18c99b2615d902750948c</hash>
         <hash type="sha1">a96cf3f0266b91d87d5124cf94326422800b627d</hash>
+        <hash type="md5">fc4d834e89c18c99b2615d902750948c</hash>
       </verification>
       <resources>
         <url type="ftp" location="jp" preference="100">ftp://ftphost/aria2-0.5.2.tar.bz2</url>
@@ -25,8 +25,8 @@
       <language>ja-JP</language>
       <os>Linux-m68k</os>
       <verification>
-        <hash type="md5">92296e19c406d77d21bda0bb944eac46</hash>
         <hash type="sha1">4c255b0ed130f5ea880f0aa061c3da0487e251cc</hash>
+        <hash type="md5">92296e19c406d77d21bda0bb944eac46</hash>
 	<pieces length="262144" type="sha1">
 	  <hash piece="0">179463a88d79cbf0b1923991708aead914f26142</hash>
 	  <hash piece="1">fecf8bc9a1647505fe16746f94e97a477597dbf3</hash>
@@ -37,5 +37,27 @@
         <url type="http" preference="100">http://httphost/aria2-0.5.1.tar.bz2</url>
       </resources>
     </file>
+    <file name="NoVerificationHash">
+    <resources>
+    <url type="ftp" preference="100">ftp://host/file</url>
+    </resources>
+    </file>
+    <file name="UnsupportedVerificationHashTypeIncluded">
+      <verification>
+        <hash type="notsupported">92296e19c406d77d21bda0bb944eac46</hash>
+        <hash type="sha1">4c255b0ed130f5ea880f0aa061c3da0487e251cc</hash>
+	<pieces length="262144" type="notsupported">
+	  <hash piece="0">179463a88d79cbf0b1923991708aead914f26142</hash>
+	  <hash piece="1">fecf8bc9a1647505fe16746f94e97a477597dbf3</hash>
+	</pieces>
+	<pieces length="262144" type="sha1">
+	  <hash piece="0">179463a88d79cbf0b1923991708aead914f26142</hash>
+	  <hash piece="1">fecf8bc9a1647505fe16746f94e97a477597dbf3</hash>
+	</pieces>
+      </verification>
+      <resources>
+        <url type="ftp" preference="100">ftp://host/file</url>
+      </resources>
+    </file>
   </files>
 </metalink>