فهرست منبع

2007-11-04 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	Fixed: the listen port sent to the tracker is wrong. If aria2 
fails
	to open listen port, then remove the port number from the 
tracker
	request.
	* src/DefaultBtAnnounce.cc 
	* test/DefaultBtAnnounceTest.cc
	* test/MockPieceStorage.h
	
	Inject randomizer to DefaultBtAnnounce and DefaultBtContext to 
make
	them more testable.
	* src/DefaultBtAnnounce.{h, cc}
	* src/DefaultBtContext.{h, cc}
	* src/Util.{h, cc}
	* test/DefaultBtAnnounceTest.cc
	* test/DefaultBtContextTest.cc
	* test/UtilTest.cc
	
	Added 'B' to upload bytes readout.
	* src/ConsoleStatCalc.cc

	Now the listen port for BitTorrent download is opened when it is
	needed.
	* src/DownloadEngineFactory.cc
	* src/BtSetup.{h, cc}
	* src/PeerListenCommand.{h, cc}
	
	Now an exception thrown while parsing tracker response is now 
logged.
	If DlAbortEx is catched, then btAnnounce->resetAnnounce() 
immediately
	called, which means no retry is made in this case, assuming a 
tracker
	has a problem.
	* src/TrackerWatcherCommand.cc
	
	Fixed: downloading a file whose length is unkown fails.
	* src/DownloadCommand.cc

	Simplified prepareForNextSegment()
	* src/DownloadCommand.cc

	Updated
	* po/POTFILES.in
Tatsuhiro Tsujikawa 18 سال پیش
والد
کامیت
d8ae699182

+ 42 - 0
ChangeLog

@@ -1,3 +1,45 @@
+2007-11-04  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	Fixed: the listen port sent to the tracker is wrong. If aria2 fails
+	to open listen port, then remove the port number from the tracker
+	request.
+	* src/DefaultBtAnnounce.cc 
+	* test/DefaultBtAnnounceTest.cc
+	* test/MockPieceStorage.h
+	
+	Inject randomizer to DefaultBtAnnounce and DefaultBtContext to make
+	them more testable.
+	* src/DefaultBtAnnounce.{h, cc}
+	* src/DefaultBtContext.{h, cc}
+	* src/Util.{h, cc}
+	* test/DefaultBtAnnounceTest.cc
+	* test/DefaultBtContextTest.cc
+	* test/UtilTest.cc
+	
+	Added 'B' to upload bytes readout.
+	* src/ConsoleStatCalc.cc
+
+	Now the listen port for BitTorrent download is opened when it is
+	needed.
+	* src/DownloadEngineFactory.cc
+	* src/BtSetup.{h, cc}
+	* src/PeerListenCommand.{h, cc}
+	
+	Now an exception thrown while parsing tracker response is now logged.
+	If DlAbortEx is catched, then btAnnounce->resetAnnounce() immediately
+	called, which means no retry is made in this case, assuming a tracker
+	has a problem.
+	* src/TrackerWatcherCommand.cc
+	
+	Fixed: downloading a file whose length is unkown fails.
+	* src/DownloadCommand.cc
+
+	Simplified prepareForNextSegment()
+	* src/DownloadCommand.cc
+
+	Updated
+	* po/POTFILES.in
+	
 2007-11-03  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 2007-11-03  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 
 	Re-implemented a file listing for Metalink, which was dropped while
 	Re-implemented a file listing for Metalink, which was dropped while

+ 0 - 3
TODO

@@ -51,9 +51,6 @@
 -- remaining features to be implemented for 0.12.0 release
 -- remaining features to be implemented for 0.12.0 release
 * Reimplement ChecksumCommand(validation using 1 checksum for 1 file)
 * Reimplement ChecksumCommand(validation using 1 checksum for 1 file)
 * Implement duplicate download checking in Bt
 * Implement duplicate download checking in Bt
-* Add PeerListenCommand to DownloadEngine only when it is really necessary.
 * improve --metalink-location field
 * improve --metalink-location field
 * Use content-type for PostDownloadHandler
 * Use content-type for PostDownloadHandler
-* Torrent information
 * Fix SleepCommand to catch halt signal
 * Fix SleepCommand to catch halt signal
-

+ 2 - 1
po/POTFILES

@@ -5,4 +5,5 @@
      ../src/MultiUrlRequestInfo.cc \
      ../src/MultiUrlRequestInfo.cc \
      ../src/RequestGroupMan.cc \
      ../src/RequestGroupMan.cc \
      ../src/Util.cc \
      ../src/Util.cc \
-     ../src/version_usage.cc
+     ../src/version_usage.cc \
+     ../src/BtSetup.cc

+ 1 - 0
po/POTFILES.in

@@ -6,3 +6,4 @@ src/MultiUrlRequestInfo.cc
 src/RequestGroupMan.cc
 src/RequestGroupMan.cc
 src/Util.cc
 src/Util.cc
 src/version_usage.cc
 src/version_usage.cc
+src/BtSetup.cc

+ 24 - 0
src/BtSetup.cc

@@ -42,6 +42,7 @@
 #include "SeedCheckCommand.h"
 #include "SeedCheckCommand.h"
 #include "PeerChokeCommand.h"
 #include "PeerChokeCommand.h"
 #include "ActivePeerConnectionCommand.h"
 #include "ActivePeerConnectionCommand.h"
+#include "PeerListenCommand.h"
 #include "UnionSeedCriteria.h"
 #include "UnionSeedCriteria.h"
 #include "TimeSeedCriteria.h"
 #include "TimeSeedCriteria.h"
 #include "ShareRatioSeedCriteria.h"
 #include "ShareRatioSeedCriteria.h"
@@ -49,6 +50,11 @@
 #include "DefaultBtProgressInfoFile.h"
 #include "DefaultBtProgressInfoFile.h"
 #include "CUIDCounter.h"
 #include "CUIDCounter.h"
 #include "prefs.h"
 #include "prefs.h"
+#include "LogFactory.h"
+#include "Logger.h"
+#include "Util.h"
+
+BtSetup::BtSetup():_logger(LogFactory::getInstance()) {}
 
 
 Commands BtSetup::setup(RequestGroup* requestGroup,
 Commands BtSetup::setup(RequestGroup* requestGroup,
 			DownloadEngine* e,
 			DownloadEngine* e,
@@ -92,6 +98,24 @@ Commands BtSetup::setup(RequestGroup* requestGroup,
 					    unionCri));
 					    unionCri));
   }
   }
 
 
+  if(PeerListenCommand::getNumInstance() == 0) {
+    PeerListenCommand* listenCommand = PeerListenCommand::getInstance(e);
+    int32_t port;
+    int32_t listenPort = option->getAsInt(PREF_LISTEN_PORT);
+    if(listenPort == -1) {
+      port = listenCommand->bindPort(6881, 6999);
+    } else {
+      port = listenCommand->bindPort(listenPort, listenPort);
+    }
+    if(port == -1) {
+      _logger->error(_("Errors occurred while binding port.\n"));
+      delete listenCommand;
+    } else {
+      BT_RUNTIME(btContext)->setListenPort(port);
+      commands.push_back(listenCommand);
+    }
+  }
+
   BT_RUNTIME(btContext)->setReady(true);
   BT_RUNTIME(btContext)->setReady(true);
   return commands;
   return commands;
 }
 }

+ 5 - 0
src/BtSetup.h

@@ -37,6 +37,7 @@
 
 
 #include "common.h"
 #include "common.h"
 
 
+class Logger;
 class RequestGroup;
 class RequestGroup;
 class DownloadEngine;
 class DownloadEngine;
 class Option;
 class Option;
@@ -44,7 +45,11 @@ class Command;
 extern typedef deque<Command*> Commands;
 extern typedef deque<Command*> Commands;
 
 
 class BtSetup {
 class BtSetup {
+private:
+  const Logger* _logger;
 public:
 public:
+  BtSetup();
+
   Commands setup(RequestGroup* requestGroup,
   Commands setup(RequestGroup* requestGroup,
 		 DownloadEngine* e,
 		 DownloadEngine* e,
 		 const Option* option);
 		 const Option* option);

+ 1 - 1
src/ConsoleStatCalc.cc

@@ -101,7 +101,7 @@ ConsoleStatCalc::calculateStat(const RequestGroupManHandle& requestGroupMan,
       cout << " "
       cout << " "
 	   << "UP:"
 	   << "UP:"
 	   << fixed << setprecision(2) << stat.getUploadSpeed()/1024.0 << "KiB/s"
 	   << fixed << setprecision(2) << stat.getUploadSpeed()/1024.0 << "KiB/s"
-	   << "(" << Util::abbrevSize(stat.getAllTimeUploadLength()) << ")";
+	   << "(" << Util::abbrevSize(stat.getAllTimeUploadLength()) << "B)";
     }
     }
     if(eta > 0) {
     if(eta > 0) {
       cout << " "
       cout << " "

+ 16 - 6
src/DefaultBtAnnounce.cc

@@ -44,6 +44,7 @@
 #include "prefs.h"
 #include "prefs.h"
 #include "DlAbortEx.h"
 #include "DlAbortEx.h"
 #include "message.h"
 #include "message.h"
+#include "SimpleRandomizer.h"
 
 
 DefaultBtAnnounce::DefaultBtAnnounce(BtContextHandle btContext,
 DefaultBtAnnounce::DefaultBtAnnounce(BtContextHandle btContext,
 				     const Option* option):
 				     const Option* option):
@@ -56,20 +57,22 @@ DefaultBtAnnounce::DefaultBtAnnounce(BtContextHandle btContext,
   announceList(btContext->getAnnounceTiers()),
   announceList(btContext->getAnnounceTiers()),
   trackerNumTry(0),
   trackerNumTry(0),
   option(option),
   option(option),
+  logger(LogFactory::getInstance()),
+  _randomizer(SimpleRandomizer::getInstance()),
   btRuntime(BT_RUNTIME(btContext)),
   btRuntime(BT_RUNTIME(btContext)),
   pieceStorage(PIECE_STORAGE(btContext)),
   pieceStorage(PIECE_STORAGE(btContext)),
   peerStorage(PEER_STORAGE(btContext))
   peerStorage(PEER_STORAGE(btContext))
 {
 {
   prevAnnounceTime.setTimeInSec(0);
   prevAnnounceTime.setTimeInSec(0);
-  key = generateKey();
-  logger = LogFactory::getInstance();
+  generateKey();
 }
 }
 
 
 DefaultBtAnnounce::~DefaultBtAnnounce() {
 DefaultBtAnnounce::~DefaultBtAnnounce() {
 }
 }
 
 
-string DefaultBtAnnounce::generateKey() const {
-  return Util::randomAlpha(8);
+void DefaultBtAnnounce::generateKey()
+{
+  key = Util::randomAlpha(8, _randomizer);
 }
 }
 
 
 bool DefaultBtAnnounce::isDefaultAnnounceReady() {
 bool DefaultBtAnnounce::isDefaultAnnounceReady() {
@@ -125,7 +128,6 @@ string DefaultBtAnnounce::getAnnounceUrl() {
     "info_hash="+Util::torrentUrlencode(btContext->getInfoHash(),
     "info_hash="+Util::torrentUrlencode(btContext->getInfoHash(),
 					btContext->getInfoHashLength())+"&"+
 					btContext->getInfoHashLength())+"&"+
     "peer_id="+Util::torrentUrlencode(btContext->getPeerId(), 20)+"&"+
     "peer_id="+Util::torrentUrlencode(btContext->getPeerId(), 20)+"&"+
-    "port="+Util::itos(btRuntime->getListenPort())+"&"+
     "uploaded="+Util::llitos(stat.getSessionUploadLength())+"&"+
     "uploaded="+Util::llitos(stat.getSessionUploadLength())+"&"+
     "downloaded="+Util::llitos(stat.getSessionDownloadLength())+"&"+
     "downloaded="+Util::llitos(stat.getSessionDownloadLength())+"&"+
     "left="+Util::llitos(left)+"&"+
     "left="+Util::llitos(left)+"&"+
@@ -133,6 +135,9 @@ string DefaultBtAnnounce::getAnnounceUrl() {
     "key="+key+"&"+
     "key="+key+"&"+
     "numwant="+Util::itos(numWant)+"&"+
     "numwant="+Util::itos(numWant)+"&"+
     "no_peer_id=1";
     "no_peer_id=1";
+  if(btRuntime->getListenPort() > 0) {
+    url += string("&")+"port="+Util::itos(btRuntime->getListenPort());
+  }
   string event = announceList.getEventString();
   string event = announceList.getEventString();
   if(!event.empty()) {
   if(!event.empty()) {
     url += string("&")+"event="+event;
     url += string("&")+"event="+event;
@@ -171,7 +176,7 @@ void DefaultBtAnnounce::resetAnnounce() {
 
 
 void
 void
 DefaultBtAnnounce::processAnnounceResponse(const char* trackerResponse,
 DefaultBtAnnounce::processAnnounceResponse(const char* trackerResponse,
-						  size_t trackerResponseLength)
+					   size_t trackerResponseLength)
 {
 {
   SharedHandle<MetaEntry> entry(MetaFileUtil::bdecoding(trackerResponse,
   SharedHandle<MetaEntry> entry(MetaFileUtil::bdecoding(trackerResponse,
 							trackerResponseLength));
 							trackerResponseLength));
@@ -237,3 +242,8 @@ bool DefaultBtAnnounce::noMoreAnnounce() {
 void DefaultBtAnnounce::shuffleAnnounce() {
 void DefaultBtAnnounce::shuffleAnnounce() {
   announceList.shuffle();
   announceList.shuffle();
 }
 }
+
+void DefaultBtAnnounce::setRandomizer(const RandomizerHandle& randomizer)
+{
+  _randomizer = randomizer;
+}

+ 7 - 1
src/DefaultBtAnnounce.h

@@ -45,6 +45,9 @@
 #include "PieceStorage.h"
 #include "PieceStorage.h"
 #include "PeerStorage.h"
 #include "PeerStorage.h"
 
 
+class Randomizer;
+extern typedef SharedHandle<Randomizer> RandomizerHandle;
+
 #define DEFAULT_ANNOUNCE_INTERVAL 1800
 #define DEFAULT_ANNOUNCE_INTERVAL 1800
 
 
 class DefaultBtAnnounce : public BtAnnounce {
 class DefaultBtAnnounce : public BtAnnounce {
@@ -62,6 +65,7 @@ private:
   int32_t trackerNumTry;
   int32_t trackerNumTry;
   const Option* option;
   const Option* option;
   Logger* logger;
   Logger* logger;
+  RandomizerHandle _randomizer;
   BtRuntimeHandle btRuntime;
   BtRuntimeHandle btRuntime;
   PieceStorageHandle pieceStorage;
   PieceStorageHandle pieceStorage;
   PeerStorageHandle peerStorage;
   PeerStorageHandle peerStorage;
@@ -111,7 +115,9 @@ public:
 
 
   virtual void shuffleAnnounce();
   virtual void shuffleAnnounce();
 
 
-  string generateKey() const;  
+  void generateKey();
+
+  void setRandomizer(const RandomizerHandle& randomizer);
 };
 };
 
 
 #endif // _D_DEFAULT_BT_ANNOUNCE_H_
 #endif // _D_DEFAULT_BT_ANNOUNCE_H_

+ 9 - 2
src/DefaultBtContext.cc

@@ -43,15 +43,18 @@
 #include "MessageDigestHelper.h"
 #include "MessageDigestHelper.h"
 #include "a2netcompat.h"
 #include "a2netcompat.h"
 #include "AnnounceTier.h"
 #include "AnnounceTier.h"
+#include "SimpleRandomizer.h"
 #include <libgen.h>
 #include <libgen.h>
 
 
-DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-"), _ownerRequestGroup(0) {}
+DefaultBtContext::DefaultBtContext():_peerIdPrefix("-aria2-"),
+				     _randomizer(SimpleRandomizer::getInstance()),
+				     _ownerRequestGroup(0) {}
 
 
 DefaultBtContext::~DefaultBtContext() {}
 DefaultBtContext::~DefaultBtContext() {}
 
 
 string DefaultBtContext::generatePeerId() const {
 string DefaultBtContext::generatePeerId() const {
   string peerId = _peerIdPrefix;
   string peerId = _peerIdPrefix;
-  peerId += Util::randomAlpha(20-_peerIdPrefix.size());
+  peerId += Util::randomAlpha(20-_peerIdPrefix.size(), _randomizer);
   if(peerId.size() > 20) {
   if(peerId.size() > 20) {
     peerId.erase(20);
     peerId.erase(20);
   }
   }
@@ -342,3 +345,7 @@ ostream& operator<<(ostream& o, const DefaultBtContext& ctx)
   return o;
   return o;
 }
 }
 
 
+void DefaultBtContext::setRandomizer(const RandomizerHandle& randomizer)
+{
+  _randomizer = randomizer;
+}

+ 7 - 0
src/DefaultBtContext.h

@@ -39,6 +39,10 @@
 #include "Dictionary.h"
 #include "Dictionary.h"
 #include "Data.h"
 #include "Data.h"
 #include "List.h"
 #include "List.h"
+
+class Randomizer;
+extern typedef SharedHandle<Randomizer> RandomizerHandle;
+
 #define INFO_HASH_LENGTH 20
 #define INFO_HASH_LENGTH 20
 #define PIECE_HASH_LENGTH 20
 #define PIECE_HASH_LENGTH 20
 
 
@@ -58,6 +62,7 @@ private:
   string peerId;
   string peerId;
   string _peerIdPrefix;
   string _peerIdPrefix;
   AnnounceTiers announceTiers;
   AnnounceTiers announceTiers;
+  RandomizerHandle _randomizer;
 
 
   RequestGroup* _ownerRequestGroup;
   RequestGroup* _ownerRequestGroup;
 
 
@@ -150,6 +155,8 @@ private:
     _ownerRequestGroup = owner;
     _ownerRequestGroup = owner;
   }
   }
 
 
+  void setRandomizer(const RandomizerHandle& randomizer);
+
   friend ostream& operator<<(ostream& o, const DefaultBtContext& ctx);
   friend ostream& operator<<(ostream& o, const DefaultBtContext& ctx);
 };
 };
 
 

+ 9 - 24
src/DownloadCommand.cc

@@ -88,7 +88,7 @@ bool DownloadCommand::executeInternal() {
   int32_t BUFSIZE = 16*1024;
   int32_t BUFSIZE = 16*1024;
   char buf[BUFSIZE];
   char buf[BUFSIZE];
   int32_t bufSize;
   int32_t bufSize;
-  if(segment->getLength()-segment->getWrittenLength() < BUFSIZE) {
+  if(segment->getLength() > 0 && segment->getLength()-segment->getWrittenLength() < BUFSIZE) {
     bufSize = segment->getLength()-segment->getWrittenLength();
     bufSize = segment->getLength()-segment->getWrittenLength();
   } else {
   } else {
     bufSize = BUFSIZE;
     bufSize = BUFSIZE;
@@ -157,31 +157,16 @@ bool DownloadCommand::prepareForNextSegment() {
     */
     */
     return true;
     return true;
   } else {
   } else {
-    // Merge segment with next segment, if segment.index+1 == nextSegment.index
-
     SegmentHandle tempSegment = _segments.front();
     SegmentHandle tempSegment = _segments.front();
-    while(1) {
-      SegmentHandle nextSegment =
-	_requestGroup->getSegmentMan()->getSegment(cuid,
-						   tempSegment->getIndex()+1);
-      if(nextSegment.isNull()) {
-	break;
-      } else {
-	if(nextSegment->getWrittenLength() > 0) {
-	  return prepareForRetry(0);
-	}
-	nextSegment->updateWrittenLength(tempSegment->getOverflowLength());
-	if(nextSegment->complete()) {
-	  validatePieceHash(nextSegment);
-	  tempSegment = nextSegment;
-	} else {
-	  e->commands.push_back(this);
-	  return false;
-	}
-      }
+    SegmentHandle nextSegment =
+      _requestGroup->getSegmentMan()->getSegment(cuid,
+						 tempSegment->getIndex()+1);
+    if(!nextSegment.isNull() && nextSegment->getWrittenLength() == 0) {
+      e->commands.push_back(this);
+      return false;
+    } else {
+      return prepareForRetry(0);
     }
     }
-
-    return prepareForRetry(0);
   }
   }
 }
 }
 
 

+ 0 - 19
src/DownloadEngineFactory.cc

@@ -49,7 +49,6 @@
 #include "FileAllocationDispatcherCommand.h"
 #include "FileAllocationDispatcherCommand.h"
 #include "AutoSaveCommand.h"
 #include "AutoSaveCommand.h"
 #include "HaveEraseCommand.h"
 #include "HaveEraseCommand.h"
-#include "PeerListenCommand.h"
 
 
 DownloadEngineFactory::DownloadEngineFactory():
 DownloadEngineFactory::DownloadEngineFactory():
   _logger(LogFactory::getInstance()) {}
   _logger(LogFactory::getInstance()) {}
@@ -84,23 +83,5 @@ DownloadEngineFactory::newDownloadEngine(Option* op,
   e->commands.push_back(new AutoSaveCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
   e->commands.push_back(new AutoSaveCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
   e->commands.push_back(new HaveEraseCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), 10));
   e->commands.push_back(new HaveEraseCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get(), 10));
 
 
-  PeerListenCommand* listenCommand =
-    new PeerListenCommand(CUIDCounterSingletonHolder::instance()->newID(), e.get());
-  int32_t port;
-  int32_t listenPort = op->getAsInt(PREF_LISTEN_PORT);
-  if(listenPort == -1) {
-    port = listenCommand->bindPort(6881, 6999);
-  } else {
-    port = listenCommand->bindPort(listenPort, listenPort);
-  }
-  if(port == -1) {
-    _logger->error(_("Errors occurred while binding port.\n"));
-    delete listenCommand;
-  } else {
-    op->put(PREF_LISTEN_PORT, Util::itos(port).c_str());
-    e->commands.push_back(listenCommand);
-  }
-  //btRuntime->setListenPort(port);
-
   return e;
   return e;
 }
 }

+ 23 - 3
src/PeerListenCommand.cc

@@ -41,14 +41,26 @@
 #include "message.h"
 #include "message.h"
 #include "PeerReceiveHandshakeCommand.h"
 #include "PeerReceiveHandshakeCommand.h"
 
 
+int32_t PeerListenCommand::__numInstance = 0;
+
+PeerListenCommand* PeerListenCommand::__instance = 0;
+
 PeerListenCommand::PeerListenCommand(int32_t cuid, DownloadEngine* e):
 PeerListenCommand::PeerListenCommand(int32_t cuid, DownloadEngine* e):
   Command(cuid),
   Command(cuid),
   e(e),
   e(e),
-  _lowestSpeedLimit(20*1024) {}
+  _lowestSpeedLimit(20*1024)
+{
+  ++__numInstance;
+}
 
 
-PeerListenCommand::~PeerListenCommand() {}
+PeerListenCommand::~PeerListenCommand()
+{
+  --__numInstance;
+}
 
 
-int32_t PeerListenCommand::bindPort(int32_t portRangeStart, int32_t portRangeEnd) {
+int32_t PeerListenCommand::bindPort(int32_t portRangeStart,
+				    int32_t portRangeEnd)
+{
   if(portRangeStart > portRangeEnd) {
   if(portRangeStart > portRangeEnd) {
     return -1;
     return -1;
   }
   }
@@ -103,3 +115,11 @@ bool PeerListenCommand::execute() {
   e->commands.push_back(this);
   e->commands.push_back(this);
   return false;
   return false;
 }
 }
+
+PeerListenCommand* PeerListenCommand::getInstance(DownloadEngine* e)
+{
+  if(__numInstance == 0) {
+    __instance = new PeerListenCommand(CUIDCounterSingletonHolder::instance()->newID(), e);
+  }
+  return __instance;
+}

+ 13 - 0
src/PeerListenCommand.h

@@ -45,6 +45,11 @@ private:
   DownloadEngine* e;
   DownloadEngine* e;
   SocketHandle socket;
   SocketHandle socket;
   int32_t _lowestSpeedLimit;
   int32_t _lowestSpeedLimit;
+
+  static int32_t __numInstance;
+
+  static PeerListenCommand* __instance;
+
 public:
 public:
   PeerListenCommand(int32_t cuid, DownloadEngine* e);
   PeerListenCommand(int32_t cuid, DownloadEngine* e);
 
 
@@ -58,6 +63,14 @@ public:
   {
   {
     _lowestSpeedLimit = speed;
     _lowestSpeedLimit = speed;
   }
   }
+
+  static PeerListenCommand* getInstance(DownloadEngine* e);
+
+  static int32_t getNumInstance()
+  {
+    return __numInstance;
+  }
+  
 };
 };
 
 
 #endif // _D_PEER_LISTEN_COMMAND_H_
 #endif // _D_PEER_LISTEN_COMMAND_H_

+ 7 - 1
src/TrackerWatcherCommand.cc

@@ -82,11 +82,17 @@ bool TrackerWatcherCommand::execute() {
       btAnnounce->announceSuccess();
       btAnnounce->announceSuccess();
       btAnnounce->resetAnnounce();
       btAnnounce->resetAnnounce();
     } catch(DlAbortEx* ex) {
     } catch(DlAbortEx* ex) {
+      logger->error(EX_EXCEPTION_CAUGHT, ex);
+      delete ex;
+      btAnnounce->announceFailure();
+      btAnnounce->resetAnnounce();
+    } catch(DlRetryEx* ex) {
+      logger->error(EX_EXCEPTION_CAUGHT, ex);      
+      delete ex;
       btAnnounce->announceFailure();
       btAnnounce->announceFailure();
       if(btAnnounce->isAllAnnounceFailed()) {
       if(btAnnounce->isAllAnnounceFailed()) {
 	btAnnounce->resetAnnounce();
 	btAnnounce->resetAnnounce();
       }
       }
-      delete ex;
     }
     }
     _trackerRequestGroup = 0;
     _trackerRequestGroup = 0;
   } else if(_trackerRequestGroup->getNumCommand() == 0){
   } else if(_trackerRequestGroup->getNumCommand() == 0){

+ 3 - 3
src/Util.cc

@@ -35,7 +35,7 @@
 #include "Util.h"
 #include "Util.h"
 #include "File.h"
 #include "File.h"
 #include "message.h"
 #include "message.h"
-#include "SimpleRandomizer.h"
+#include "Randomizer.h"
 #include "a2netcompat.h"
 #include "a2netcompat.h"
 #include "a2time.h"
 #include "a2time.h"
 #include <ctype.h>
 #include <ctype.h>
@@ -522,11 +522,11 @@ int32_t Util::countBit(uint32_t n) {
     nbits[(n >> 24)&0xffu];
     nbits[(n >> 24)&0xffu];
 }
 }
 
 
-string Util::randomAlpha(int32_t length) {
+string Util::randomAlpha(int32_t length, const RandomizerHandle& randomizer) {
   static char *random_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
   static char *random_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
   string str;
   string str;
   for(int32_t i = 0; i < length; i++) {
   for(int32_t i = 0; i < length; i++) {
-    int32_t index = SimpleRandomizer::getInstance()->getRandomNumber(strlen(random_chars));
+    int32_t index = randomizer->getRandomNumber(strlen(random_chars));
     str += random_chars[index];
     str += random_chars[index];
   }
   }
   return str;
   return str;

+ 4 - 1
src/Util.h

@@ -43,6 +43,9 @@
 #include <deque>
 #include <deque>
 #include <ostream>
 #include <ostream>
 
 
+class Randomizer;
+extern typedef SharedHandle<Randomizer> RandomizerHandle;
+
 #define STRTOLL(X) strtoll(X, (char**)NULL, 10)
 #define STRTOLL(X) strtoll(X, (char**)NULL, 10)
 
 
 #define START_INDEX(OFFSET, PIECE_LENGTH) ((OFFSET)/(PIECE_LENGTH))
 #define START_INDEX(OFFSET, PIECE_LENGTH) ((OFFSET)/(PIECE_LENGTH))
@@ -112,7 +115,7 @@ public:
 
 
   static int32_t countBit(uint32_t n);
   static int32_t countBit(uint32_t n);
   
   
-  static string randomAlpha(int32_t length);
+  static string randomAlpha(int32_t length, const RandomizerHandle& randomizer);
   
   
   static string toUpper(const string& src);
   static string toUpper(const string& src);
 
 

+ 147 - 7
test/DefaultBtAnnounceTest.cc

@@ -3,6 +3,12 @@
 #include "Option.h"
 #include "Option.h"
 #include "Util.h"
 #include "Util.h"
 #include "Exception.h"
 #include "Exception.h"
+#include "MockBtContext.h"
+#include "MockPieceStorage.h"
+#include "MockPeerStorage.h"
+#include "BtRuntime.h"
+#include "AnnounceTier.h"
+#include "FixedNumberRandomizer.h"
 #include <cppunit/extensions/HelperMacros.h>
 #include <cppunit/extensions/HelperMacros.h>
 
 
 using namespace std;
 using namespace std;
@@ -11,27 +17,161 @@ class DefaultBtAnnounceTest:public CppUnit::TestFixture {
 
 
   CPPUNIT_TEST_SUITE(DefaultBtAnnounceTest);
   CPPUNIT_TEST_SUITE(DefaultBtAnnounceTest);
   CPPUNIT_TEST(testIsDefaultAnnounceReady);
   CPPUNIT_TEST(testIsDefaultAnnounceReady);
+  CPPUNIT_TEST(testGetAnnounceUrl);
+  CPPUNIT_TEST(testNoMoreAnnounce);
   CPPUNIT_TEST_SUITE_END();
   CPPUNIT_TEST_SUITE_END();
 private:
 private:
-  BtContextHandle btContext;
-  Option* option;
+  MockBtContextHandle _btContext;
+  MockPieceStorageHandle _pieceStorage;
+  MockPeerStorageHandle _peerStorage;
+  BtRuntimeHandle _btRuntime;
+  Option* _option;
 public:
 public:
-  DefaultBtAnnounceTest():btContext(0) {}
+  DefaultBtAnnounceTest():_btContext(0),
+			  _pieceStorage(0),
+			  _peerStorage(0),
+			  _btRuntime(0) {}
 
 
   void setUp() {
   void setUp() {
-    btContext = BtContextHandle(new DefaultBtContext());
-    btContext->load("test.torrent");
-    option = new Option();
+    _option = new Option();
+
+    int64_t totalLength = 4*1024*1024;
+    int32_t pieceLength = 256*1024;
+    
+    static const unsigned char infoHash[] = {  0x01, 0x23, 0x45, 0x67,
+					       0x89, 0xab, 0xcd, 0xef,
+					       0x01, 0x23, 0x45, 0x67,
+					       0x89, 0xab, 0xcd, 0xef,
+					       0x01, 0x23, 0x45, 0x67 };
+    
+    string peerId = "-aria2-ultrafastdltl";
+
+    _btContext = new MockBtContext();
+    _btContext->setInfoHash(infoHash);
+    _btContext->setTotalLength(totalLength);
+    _btContext->setPieceLength(pieceLength);
+    _btContext->setPeerId((const unsigned char*)peerId.c_str());
+
+    _pieceStorage = new MockPieceStorage();
+    _pieceStorage->setTotalLength(totalLength);
+    _pieceStorage->setCompletedLength(pieceLength*10);
+
+    _peerStorage = new MockPeerStorage();
+    TransferStat stat;
+    stat.setSessionDownloadLength(pieceLength*5);
+    stat.setSessionUploadLength(pieceLength*6);
+    _peerStorage->setStat(stat);
+
+    _btRuntime = new BtRuntime();
+    _btRuntime->setListenPort(6989);
+  }
+
+  void tearDown()
+  {
+    delete _option;
   }
   }
 
 
   void testIsDefaultAnnounceReady();
   void testIsDefaultAnnounceReady();
+  void testGetAnnounceUrl();
+  void testNoMoreAnnounce();
 };
 };
 
 
 
 
 CPPUNIT_TEST_SUITE_REGISTRATION(DefaultBtAnnounceTest);
 CPPUNIT_TEST_SUITE_REGISTRATION(DefaultBtAnnounceTest);
 
 
 void DefaultBtAnnounceTest::testIsDefaultAnnounceReady() {
 void DefaultBtAnnounceTest::testIsDefaultAnnounceReady() {
-  DefaultBtAnnounce btAnnounce(btContext, option);
+  DefaultBtAnnounce btAnnounce(_btContext, _option);
 
 
   CPPUNIT_ASSERT(btAnnounce.isDefaultAnnounceReady());
   CPPUNIT_ASSERT(btAnnounce.isDefaultAnnounceReady());
 }
 }
+
+void DefaultBtAnnounceTest::testNoMoreAnnounce()
+{
+  string trackerURI1 = "http://localhost/announce";
+  Strings uris1;
+  uris1.push_back(trackerURI1);
+  AnnounceTierHandle announceTier1 = new AnnounceTier(uris1);
+
+  string trackerURI2 = "http://backup/announce";
+  Strings uris2;
+  uris2.push_back(trackerURI2);
+  AnnounceTierHandle announceTier2 = new AnnounceTier(uris2);
+
+
+  _btContext->addAnnounceTier(announceTier1);
+  _btContext->addAnnounceTier(announceTier2);
+
+  DefaultBtAnnounce btAnnounce(_btContext, _option);
+  btAnnounce.setPieceStorage(_pieceStorage);
+  btAnnounce.setPeerStorage(_peerStorage);
+  btAnnounce.setBtRuntime(_btRuntime);
+  btAnnounce.setRandomizer(new FixedNumberRandomizer());
+  btAnnounce.generateKey();
+
+  CPPUNIT_ASSERT_EQUAL(string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started"), btAnnounce.getAnnounceUrl());
+
+  btAnnounce.announceSuccess();
+
+  CPPUNIT_ASSERT_EQUAL(string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989"), btAnnounce.getAnnounceUrl());
+
+  btAnnounce.announceFailure();
+
+  CPPUNIT_ASSERT_EQUAL(string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started"), btAnnounce.getAnnounceUrl());
+
+  btAnnounce.announceSuccess();
+
+  _pieceStorage->setAllDownloadFinished(true);
+
+  CPPUNIT_ASSERT_EQUAL(string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed"), btAnnounce.getAnnounceUrl());
+
+  btAnnounce.announceSuccess();
+
+  CPPUNIT_ASSERT_EQUAL(string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed"), btAnnounce.getAnnounceUrl());
+
+  btAnnounce.announceSuccess();
+
+  _btRuntime->setHalt(true);
+
+  CPPUNIT_ASSERT_EQUAL(string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped"), btAnnounce.getAnnounceUrl());
+
+  btAnnounce.announceSuccess();
+
+  CPPUNIT_ASSERT_EQUAL(string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped"), btAnnounce.getAnnounceUrl());
+
+  btAnnounce.announceSuccess();
+}
+
+void DefaultBtAnnounceTest::testGetAnnounceUrl()
+{
+  string trackerURI = "http://localhost/announce";
+  Strings uris;
+  uris.push_back(trackerURI);
+  AnnounceTierHandle announceTier = new AnnounceTier(uris);
+
+  _btContext->addAnnounceTier(announceTier);
+
+  DefaultBtAnnounce btAnnounce(_btContext, _option);
+  btAnnounce.setPieceStorage(_pieceStorage);
+  btAnnounce.setPeerStorage(_peerStorage);
+  btAnnounce.setBtRuntime(_btRuntime);
+  btAnnounce.setRandomizer(new FixedNumberRandomizer());
+  btAnnounce.generateKey();
+
+  CPPUNIT_ASSERT_EQUAL(string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started"), btAnnounce.getAnnounceUrl());
+
+  btAnnounce.announceSuccess();
+
+  CPPUNIT_ASSERT_EQUAL(string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989"), btAnnounce.getAnnounceUrl());
+
+  btAnnounce.announceSuccess();
+
+  _pieceStorage->setAllDownloadFinished(true);
+
+  CPPUNIT_ASSERT_EQUAL(string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed"), btAnnounce.getAnnounceUrl());
+
+  btAnnounce.announceSuccess();
+
+  _btRuntime->setHalt(true);
+
+  CPPUNIT_ASSERT_EQUAL(string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped"), btAnnounce.getAnnounceUrl());
+}

+ 3 - 1
test/DefaultBtContextTest.cc

@@ -2,6 +2,7 @@
 #include "Util.h"
 #include "Util.h"
 #include "Exception.h"
 #include "Exception.h"
 #include "AnnounceTier.h"
 #include "AnnounceTier.h"
+#include "FixedNumberRandomizer.h"
 #include <cppunit/extensions/HelperMacros.h>
 #include <cppunit/extensions/HelperMacros.h>
 
 
 using namespace std;
 using namespace std;
@@ -229,7 +230,8 @@ void DefaultBtContextTest::testGetInfoHashAsString() {
 
 
 void DefaultBtContextTest::testGetPeerId() {
 void DefaultBtContextTest::testGetPeerId() {
   DefaultBtContext btContext;
   DefaultBtContext btContext;
-  Util::torrentUrlencode(btContext.getPeerId(), 20);
+  btContext.setRandomizer(new FixedNumberRandomizer());
+  CPPUNIT_ASSERT_EQUAL(string("%2daria2%2dAAAAAAAAAAAAA"), Util::torrentUrlencode(btContext.getPeerId(), 20));
 }
 }
 
 
 void DefaultBtContextTest::testComputeFastSet()
 void DefaultBtContextTest::testComputeFastSet()

+ 17 - 2
test/MockPieceStorage.h

@@ -18,8 +18,18 @@ private:
   DiskAdaptorHandle diskAdaptor;
   DiskAdaptorHandle diskAdaptor;
   Integers pieceLengthList;
   Integers pieceLengthList;
   Pieces inFlightPieces;
   Pieces inFlightPieces;
+  bool _allDownloadFinished;
 public:
 public:
-  MockPieceStorage():diskAdaptor(0) {}
+  MockPieceStorage():totalLength(0),
+		     filteredTotalLength(0),
+		     completedLength(0),
+		     filteredCompletedLength(0),
+		     bitfieldMan(0),
+		     selectiveDownloadingMode(false),
+		     endGame(false),
+		     diskAdaptor(0),
+		     _allDownloadFinished(false) {}
+
   virtual ~MockPieceStorage() {}
   virtual ~MockPieceStorage() {}
 
 
   virtual bool hasMissingPiece(const PeerHandle& peer) {
   virtual bool hasMissingPiece(const PeerHandle& peer) {
@@ -108,7 +118,12 @@ public:
   }
   }
 
 
   virtual bool allDownloadFinished() {
   virtual bool allDownloadFinished() {
-    return false;
+    return _allDownloadFinished;
+  }
+
+  void setAllDownloadFinished(bool f)
+  {
+    _allDownloadFinished = f;
   }
   }
 
 
   virtual void initStorage() {}
   virtual void initStorage() {}

+ 3 - 1
test/UtilTest.cc

@@ -1,4 +1,5 @@
 #include "Util.h"
 #include "Util.h"
+#include "FixedNumberRandomizer.h"
 #include <string>
 #include <string>
 #include <cppunit/extensions/HelperMacros.h>
 #include <cppunit/extensions/HelperMacros.h>
 
 
@@ -240,7 +241,8 @@ public:
 };
 };
 
 
 void UtilTest::testRandomAlpha() {
 void UtilTest::testRandomAlpha() {
-  CPPUNIT_ASSERT_EQUAL((size_t)8, Util::randomAlpha(8).size());
+  string s = Util::randomAlpha(8, new FixedNumberRandomizer());
+  CPPUNIT_ASSERT_EQUAL(string("AAAAAAAA"), s);
 }
 }
 
 
 void UtilTest::testToUpper() {
 void UtilTest::testToUpper() {