From 8958b92d91c264f426892deb60f2bd9b611c9808 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 14 Aug 2010 06:52:35 +0000 Subject: [PATCH] 2010-08-14 Tatsuhiro Tsujikawa Listen both IPv4 and IPv6 for BitTorrent protocol. * src/BtSetup.cc * src/PeerListenCommand.cc * src/PeerListenCommand.h --- ChangeLog | 7 +++++++ src/BtSetup.cc | 40 ++++++++++++++++++++++++++++++---------- src/PeerListenCommand.cc | 28 +++++++++++++++++++++------- src/PeerListenCommand.h | 6 ++++-- 4 files changed, 62 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index d70cd3d7..54f7e5ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-08-14 Tatsuhiro Tsujikawa + + Listen both IPv4 and IPv6 for BitTorrent protocol. + * src/BtSetup.cc + * src/PeerListenCommand.cc + * src/PeerListenCommand.h + 2010-08-14 Tatsuhiro Tsujikawa Added debug log diff --git a/src/BtSetup.cc b/src/BtSetup.cc index fdd467fa..0f4c25fd 100644 --- a/src/BtSetup.cc +++ b/src/BtSetup.cc @@ -83,6 +83,7 @@ #include "CheckIntegrityEntry.h" #include "ServerStatMan.h" #include "DlAbortEx.h" +#include "array_fun.h" namespace aria2 { @@ -183,19 +184,38 @@ void BtSetup::setup(std::vector& commands, } } if(PeerListenCommand::getNumInstance() == 0) { - PeerListenCommand* listenCommand = PeerListenCommand::getInstance(e); - IntSequence seq =util::parseIntRange(e->getOption()->get(PREF_LISTEN_PORT)); - uint16_t port; - if(listenCommand->bindPort(port, seq)) { - btRuntime->setListenPort(port); - // Add command to DownloadEngine directly. - e->addCommand(listenCommand); - } else { - delete listenCommand; + static int families[] = { AF_INET, AF_INET6 }; + for(size_t i = 0; i < A2_ARRAY_LEN(families); ++i) { + PeerListenCommand* listenCommand = + PeerListenCommand::getInstance(e, families[i]); + bool ret; + uint16_t port; + if(btRuntime->getListenPort()) { + IntSequence seq = + util::parseIntRange(util::uitos(btRuntime->getListenPort())); + ret = listenCommand->bindPort(port, seq); + } else { + IntSequence seq = + util::parseIntRange(e->getOption()->get(PREF_LISTEN_PORT)); + ret = listenCommand->bindPort(port, seq); + } + if(ret) { + btRuntime->setListenPort(port); + // Add command to DownloadEngine directly. + e->addCommand(listenCommand); + } else { + delete listenCommand; + } + } + if(PeerListenCommand::getNumInstance() == 0) { throw DL_ABORT_EX(_("Errors occurred while binding port.\n")); } } else { - PeerListenCommand* listenCommand = PeerListenCommand::getInstance(e); + PeerListenCommand* listenCommand = + PeerListenCommand::getInstance(e, AF_INET); + if(!listenCommand) { + listenCommand = PeerListenCommand::getInstance(e, AF_INET6); + } btRuntime->setListenPort(listenCommand->getPort()); } if(option->getAsBool(PREF_BT_ENABLE_LPD) && diff --git a/src/PeerListenCommand.cc b/src/PeerListenCommand.cc index 8786be20..a3a56bb4 100644 --- a/src/PeerListenCommand.cc +++ b/src/PeerListenCommand.cc @@ -58,9 +58,13 @@ unsigned int PeerListenCommand::numInstance_ = 0; PeerListenCommand* PeerListenCommand::instance_ = 0; -PeerListenCommand::PeerListenCommand(cuid_t cuid, DownloadEngine* e): +PeerListenCommand* PeerListenCommand::instance6_ = 0; + +PeerListenCommand::PeerListenCommand +(cuid_t cuid, DownloadEngine* e, int family): Command(cuid), e_(e), + family_(family), lowestSpeedLimit_(20*1024) { ++numInstance_; @@ -86,10 +90,11 @@ bool PeerListenCommand::bindPort(uint16_t& port, IntSequence& seq) } port = (*portItr); try { - socket_->bind(port); + socket_->bind(A2STR::NIL, port, family_); socket_->beginListen(); socket_->setNonBlockingMode(); - getLogger()->notice("BitTorrent: listening to port %d", port); + getLogger()->notice("IPv%d BitTorrent: listening to port %d", + family_ == AF_INET?4:6, port); return true; } catch(RecoverableException& ex) { getLogger()->error(MSG_BIND_FAILURE, ex, @@ -144,12 +149,21 @@ bool PeerListenCommand::execute() { return false; } -PeerListenCommand* PeerListenCommand::getInstance(DownloadEngine* e) +PeerListenCommand* PeerListenCommand::getInstance(DownloadEngine* e, int family) { - if(numInstance_ == 0) { - instance_ = new PeerListenCommand(e->newCUID(), e); + if(family == AF_INET) { + if(!instance_) { + instance_ = new PeerListenCommand(e->newCUID(), e, family); + } + return instance_; + } else if(family == AF_INET6) { + if(!instance6_) { + instance6_ = new PeerListenCommand(e->newCUID(), e, family); + } + return instance6_; + } else { + return 0; } - return instance_; } } // namespace aria2 diff --git a/src/PeerListenCommand.h b/src/PeerListenCommand.h index c64a8556..0055b726 100644 --- a/src/PeerListenCommand.h +++ b/src/PeerListenCommand.h @@ -47,6 +47,7 @@ class SocketCore; class PeerListenCommand : public Command { private: DownloadEngine* e_; + int family_; SharedHandle socket_; unsigned int lowestSpeedLimit_; @@ -54,8 +55,9 @@ private: static PeerListenCommand* instance_; + static PeerListenCommand* instance6_; public: - PeerListenCommand(cuid_t cuid, DownloadEngine* e); + PeerListenCommand(cuid_t cuid, DownloadEngine* e, int family); virtual ~PeerListenCommand(); @@ -75,7 +77,7 @@ public: lowestSpeedLimit_ = speed; } - static PeerListenCommand* getInstance(DownloadEngine* e); + static PeerListenCommand* getInstance(DownloadEngine* e, int family); static unsigned int getNumInstance() {