2010-08-24 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Added --bt-tracker and --bt-exclude-tracker option.  In
	--bt-tracker option, you can specify comma separated list of
	additional BitTorrent tracker's announce URI. These URIs are not
	affected by --bt-exclude-tracker option because they are added
	after URIs in --bt-exclude-tracker option are removed.  In
	--bt-exclude-tracker option, you can specify comma separated list
	of BitTorrent tracker's announce URI to remove. You can use
	special value '*' which matches all URIs, thus removes all
	announce URIs. When specifying '*' in shell command-line, don't
	forget to escape or quote it.
	* src/BtDependency.cc
	* src/OptionHandlerFactory.cc
	* src/UTMetadataPostDownloadHandler.cc
	* src/bittorrent_helper.cc
	* src/bittorrent_helper.h
	* src/download_helper.cc
	* src/download_helper.h
	* src/prefs.cc
	* src/prefs.h
	* src/usage_text.h
	* test/BittorrentHelperTest.cc
	* test/DownloadHelperTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2010-08-24 14:21:12 +00:00
parent a977bffbf5
commit 26bf5ab5e2
13 changed files with 256 additions and 6 deletions

View File

@ -1,3 +1,28 @@
2010-08-24 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Added --bt-tracker and --bt-exclude-tracker option. In
--bt-tracker option, you can specify comma separated list of
additional BitTorrent tracker's announce URI. These URIs are not
affected by --bt-exclude-tracker option because they are added
after URIs in --bt-exclude-tracker option are removed. In
--bt-exclude-tracker option, you can specify comma separated list
of BitTorrent tracker's announce URI to remove. You can use
special value '*' which matches all URIs, thus removes all
announce URIs. When specifying '*' in shell command-line, don't
forget to escape or quote it.
* src/BtDependency.cc
* src/OptionHandlerFactory.cc
* src/UTMetadataPostDownloadHandler.cc
* src/bittorrent_helper.cc
* src/bittorrent_helper.h
* src/download_helper.cc
* src/download_helper.h
* src/prefs.cc
* src/prefs.h
* src/usage_text.h
* test/BittorrentHelperTest.cc
* test/DownloadHelperTest.cc
2010-08-24 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net> 2010-08-24 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Code cleanup Code cleanup

View File

@ -88,9 +88,13 @@ bool BtDependency::resolve()
bittorrent::getTorrentAttrs(dependee->getDownloadContext()); bittorrent::getTorrentAttrs(dependee->getDownloadContext());
bittorrent::loadFromMemory bittorrent::loadFromMemory
(bittorrent::metadata2Torrent(content, attrs), context, "default"); (bittorrent::metadata2Torrent(content, attrs), context, "default");
// We don't call bittorrent::adjustAnnounceUri() because it
// has already been called with attrs.
} else { } else {
bittorrent::loadFromMemory bittorrent::loadFromMemory
(content, context, File(dependee->getFirstFilePath()).getBasename()); (content, context, File(dependee->getFirstFilePath()).getBasename());
bittorrent::adjustAnnounceUri(bittorrent::getTorrentAttrs(context),
dependant_->getOption());
} }
const std::vector<SharedHandle<FileEntry> >& fileEntries = const std::vector<SharedHandle<FileEntry> >& fileEntries =
context->getFileEntries(); context->getFileEntries();

View File

@ -1145,6 +1145,16 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
op->addTag(TAG_BITTORRENT); op->addTag(TAG_BITTORRENT);
handlers.push_back(op); handlers.push_back(op);
} }
{
SharedHandle<DefaultOptionHandler> op(new DefaultOptionHandler
(PREF_BT_EXCLUDE_TRACKER,
TEXT_BT_EXCLUDE_TRACKER,
NO_DESCRIPTION,
"URI,... "
"or *"));
op->addTag(TAG_BITTORRENT);
handlers.push_back(op);
}
{ {
SharedHandle<OptionHandler> op(new DefaultOptionHandler SharedHandle<OptionHandler> op(new DefaultOptionHandler
(PREF_BT_EXTERNAL_IP, (PREF_BT_EXTERNAL_IP,
@ -1288,6 +1298,15 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
op->hide(); op->hide();
handlers.push_back(op); handlers.push_back(op);
} }
{
SharedHandle<DefaultOptionHandler> op(new DefaultOptionHandler
(PREF_BT_TRACKER,
TEXT_BT_TRACKER,
NO_DESCRIPTION,
"URI,..."));
op->addTag(TAG_BITTORRENT);
handlers.push_back(op);
}
{ {
SharedHandle<NumberOptionHandler> op(new NumberOptionHandler SharedHandle<NumberOptionHandler> op(new NumberOptionHandler
(PREF_BT_TRACKER_CONNECT_TIMEOUT, (PREF_BT_TRACKER_CONNECT_TIMEOUT,

View File

@ -93,8 +93,10 @@ void UTMetadataPostDownloadHandler::getNextRequestGroups
} }
if(!requestGroup->getOption()->getAsBool(PREF_BT_METADATA_ONLY)) { if(!requestGroup->getOption()->getAsBool(PREF_BT_METADATA_ONLY)) {
std::vector<SharedHandle<RequestGroup> > newRgs; std::vector<SharedHandle<RequestGroup> > newRgs;
// Don't adjust announce URI because it has been done when
// RequestGroup is created with magnet URI.
createRequestGroupForBitTorrent(newRgs, requestGroup->getOption(), createRequestGroupForBitTorrent(newRgs, requestGroup->getOption(),
std::vector<std::string>(), torrent); std::vector<std::string>(), torrent, false);
requestGroup->followedBy(newRgs.begin(), newRgs.end()); requestGroup->followedBy(newRgs.begin(), newRgs.end());
if(!requestGroup->getMetadataInfo().isNull()) { if(!requestGroup->getMetadataInfo().isNull()) {
setMetadataInfo(newRgs.begin(), newRgs.end(), setMetadataInfo(newRgs.begin(), newRgs.end(),

View File

@ -55,6 +55,8 @@
#include "bencode2.h" #include "bencode2.h"
#include "TorrentAttribute.h" #include "TorrentAttribute.h"
#include "SocketCore.h" #include "SocketCore.h"
#include "Option.h"
#include "prefs.h"
namespace aria2 { namespace aria2 {
@ -1005,6 +1007,60 @@ int getCompactLength(int family)
} }
} }
void removeAnnounceUri
(const SharedHandle<TorrentAttribute>& attrs,
const std::vector<std::string>& uris)
{
if(uris.empty()) {
return;
}
if(std::find(uris.begin(), uris.end(), "*") == uris.end()) {
for(std::vector<std::vector<std::string> >::iterator i =
attrs->announceList.begin(); i != attrs->announceList.end();) {
for(std::vector<std::string>::iterator j =(*i).begin();j != (*i).end();) {
if(std::find(uris.begin(), uris.end(), *j) == uris.end()) {
++j;
} else {
j = (*i).erase(j);
}
}
if((*i).empty()) {
i = attrs->announceList.erase(i);
} else {
++i;
}
}
} else {
attrs->announceList.clear();
}
}
void addAnnounceUri
(const SharedHandle<TorrentAttribute>& attrs,
const std::vector<std::string>& uris)
{
for(std::vector<std::string>::const_iterator i = uris.begin(),
eoi = uris.end(); i != eoi; ++i) {
std::vector<std::string> tier;
tier.push_back(*i);
attrs->announceList.push_back(tier);
}
}
void adjustAnnounceUri
(const SharedHandle<TorrentAttribute>& attrs,
const SharedHandle<Option>& option)
{
std::vector<std::string> excludeUris;
std::vector<std::string> addUris;
util::split(option->get(PREF_BT_EXCLUDE_TRACKER),
std::back_inserter(excludeUris), A2STR::COMMA_C, true);
util::split(option->get(PREF_BT_TRACKER),
std::back_inserter(addUris), A2STR::COMMA_C, true);
removeAnnounceUri(attrs, excludeUris);
addAnnounceUri(attrs, addUris);
}
} // namespace bittorrent } // namespace bittorrent
} // namespace aria2 } // namespace aria2

View File

@ -52,6 +52,7 @@ namespace aria2 {
class DownloadContext; class DownloadContext;
class Randomizer; class Randomizer;
class Option;
namespace bittorrent { namespace bittorrent {
@ -222,6 +223,27 @@ std::string metadata2Torrent
// Constructs BitTorrent Magnet URI using attrs. // Constructs BitTorrent Magnet URI using attrs.
std::string torrent2Magnet(const SharedHandle<TorrentAttribute>& attrs); std::string torrent2Magnet(const SharedHandle<TorrentAttribute>& attrs);
// Removes announce URI in uris from attrs. If uris contains '*', all
// announce URIs are removed.
void removeAnnounceUri
(const SharedHandle<TorrentAttribute>& attrs,
const std::vector<std::string>& uris);
// Adds announce URI in uris to attrs. Each URI in uris creates its
// own tier.
void addAnnounceUri
(const SharedHandle<TorrentAttribute>& attrs,
const std::vector<std::string>& uris);
// This helper function uses 2 option values: PREF_BT_TRACKER and
// PREF_BT_EXCLUDE_TRACKER. First, the value of
// PREF_BT_EXCLUDE_TRACKER is converted to std::vector<std::string>
// and call removeAnnounceUri(). Then the value of PREF_BT_TRACKER is
// converted to std::vector<std::string> and call addAnnounceUri().
void adjustAnnounceUri
(const SharedHandle<TorrentAttribute>& attrs,
const SharedHandle<Option>& option);
template<typename OutputIterator> template<typename OutputIterator>
void extractPeer(const ValueBase* peerData, int family, OutputIterator dest) void extractPeer(const ValueBase* peerData, int family, OutputIterator dest)
{ {

View File

@ -240,7 +240,8 @@ SharedHandle<RequestGroup>
createBtRequestGroup(const std::string& torrentFilePath, createBtRequestGroup(const std::string& torrentFilePath,
const SharedHandle<Option>& option, const SharedHandle<Option>& option,
const std::vector<std::string>& auxUris, const std::vector<std::string>& auxUris,
const std::string& torrentData = "") const std::string& torrentData = "",
bool adjustAnnounceUri = true)
{ {
SharedHandle<RequestGroup> rg(new RequestGroup(option)); SharedHandle<RequestGroup> rg(new RequestGroup(option));
SharedHandle<DownloadContext> dctx(new DownloadContext()); SharedHandle<DownloadContext> dctx(new DownloadContext());
@ -254,6 +255,9 @@ createBtRequestGroup(const std::string& torrentFilePath,
// exception // exception
rg->setMetadataInfo(createMetadataInfoDataOnly()); rg->setMetadataInfo(createMetadataInfoDataOnly());
} }
if(adjustAnnounceUri) {
bittorrent::adjustAnnounceUri(bittorrent::getTorrentAttrs(dctx), option);
}
dctx->setFileFilter(util::parseIntRange(option->get(PREF_SELECT_FILE))); dctx->setFileFilter(util::parseIntRange(option->get(PREF_SELECT_FILE)));
std::istringstream indexOutIn(option->get(PREF_INDEX_OUT)); std::istringstream indexOutIn(option->get(PREF_INDEX_OUT));
std::map<size_t, std::string> indexPathMap = std::map<size_t, std::string> indexPathMap =
@ -288,6 +292,7 @@ createBtMagnetRequestGroup(const std::string& magnetLink,
bittorrent::loadMagnet(magnetLink, dctx); bittorrent::loadMagnet(magnetLink, dctx);
SharedHandle<TorrentAttribute> torrentAttrs = SharedHandle<TorrentAttribute> torrentAttrs =
bittorrent::getTorrentAttrs(dctx); bittorrent::getTorrentAttrs(dctx);
bittorrent::adjustAnnounceUri(torrentAttrs, rg->getOption());
dctx->getFirstFileEntry()->setPath(torrentAttrs->name); dctx->getFirstFileEntry()->setPath(torrentAttrs->name);
rg->setDownloadContext(dctx); rg->setDownloadContext(dctx);
rg->clearPostDownloadHandler(); rg->clearPostDownloadHandler();
@ -304,7 +309,8 @@ void createRequestGroupForBitTorrent
(std::vector<SharedHandle<RequestGroup> >& result, (std::vector<SharedHandle<RequestGroup> >& result,
const SharedHandle<Option>& option, const SharedHandle<Option>& option,
const std::vector<std::string>& uris, const std::vector<std::string>& uris,
const std::string& torrentData) const std::string& torrentData,
bool adjustAnnounceUri)
{ {
std::vector<std::string> nargs; std::vector<std::string> nargs;
if(option->get(PREF_PARAMETERIZED_URI) == V_TRUE) { if(option->get(PREF_PARAMETERIZED_URI) == V_TRUE) {
@ -316,7 +322,7 @@ void createRequestGroupForBitTorrent
size_t numSplit = option->getAsInt(PREF_SPLIT); size_t numSplit = option->getAsInt(PREF_SPLIT);
SharedHandle<RequestGroup> rg = SharedHandle<RequestGroup> rg =
createBtRequestGroup(option->get(PREF_TORRENT_FILE), option, nargs, createBtRequestGroup(option->get(PREF_TORRENT_FILE), option, nargs,
torrentData); torrentData, adjustAnnounceUri);
rg->setNumConcurrentCommand(numSplit); rg->setNumConcurrentCommand(numSplit);
result.push_back(rg); result.push_back(rg);
} }

View File

@ -55,13 +55,16 @@ const std::set<std::string>& listRequestOptions();
#ifdef ENABLE_BITTORRENT #ifdef ENABLE_BITTORRENT
// Create RequestGroup object using torrent file specified by // Create RequestGroup object using torrent file specified by
// torrent-file option. If non-empty torrentData is specified, then // torrent-file option. If non-empty torrentData is specified, then
// it is used as a content of torrent file instead. In this function, // it is used as a content of torrent file instead. If
// adjustAnnounceUri is true, announce URIs are adjusted using
// bittorrent::adjustAnnounceUri(). In this function,
// force-sequential is ignored. // force-sequential is ignored.
void createRequestGroupForBitTorrent void createRequestGroupForBitTorrent
(std::vector<SharedHandle<RequestGroup> >& result, (std::vector<SharedHandle<RequestGroup> >& result,
const SharedHandle<Option>& option, const SharedHandle<Option>& option,
const std::vector<std::string>& uris, const std::vector<std::string>& uris,
const std::string& torrentData = ""); const std::string& torrentData = "",
bool adjustAnnounceUri = true);
#endif // ENABLE_BITTORRENT #endif // ENABLE_BITTORRENT
#ifdef ENABLE_METALINK #ifdef ENABLE_METALINK

View File

@ -374,6 +374,10 @@ const std::string PREF_BT_TRACKER_CONNECT_TIMEOUT("bt-tracker-connect-timeout");
const std::string PREF_DHT_MESSAGE_TIMEOUT("dht-message-timeout"); const std::string PREF_DHT_MESSAGE_TIMEOUT("dht-message-timeout");
// values: string // values: string
const std::string PREF_ON_BT_DOWNLOAD_COMPLETE("on-bt-download-complete"); const std::string PREF_ON_BT_DOWNLOAD_COMPLETE("on-bt-download-complete");
// values: string
const std::string PREF_BT_TRACKER("bt-tracker");
// values: string
const std::string PREF_BT_EXCLUDE_TRACKER("bt-exclude-tracker");
/** /**
* Metalink related preferences * Metalink related preferences

View File

@ -378,6 +378,10 @@ extern const std::string PREF_BT_TRACKER_CONNECT_TIMEOUT;
extern const std::string PREF_DHT_MESSAGE_TIMEOUT; extern const std::string PREF_DHT_MESSAGE_TIMEOUT;
// values: string // values: string
extern const std::string PREF_ON_BT_DOWNLOAD_COMPLETE; extern const std::string PREF_ON_BT_DOWNLOAD_COMPLETE;
// values: string
extern const std::string PREF_BT_TRACKER;
// values: string
extern const std::string PREF_BT_EXCLUDE_TRACKER;
/** /**
* Metalink related preferences * Metalink related preferences

View File

@ -728,3 +728,16 @@
" network.") " network.")
#define TEXT_DHT_FILE_PATH6 \ #define TEXT_DHT_FILE_PATH6 \
_(" --dht-file-path6=PATH Change the IPv6 DHT routing table file to PATH.") _(" --dht-file-path6=PATH Change the IPv6 DHT routing table file to PATH.")
#define TEXT_BT_TRACKER \
_(" --bt-tracker=URI[,...] Comma separated list of additional BitTorrent\n" \
" tracker's announce URI. These URIs are not\n" \
" affected by --bt-exclude-tracker option because\n" \
" they are added after URIs in --bt-exclude-tracker\n" \
" option are removed.")
#define TEXT_BT_EXCLUDE_TRACKER \
_(" --bt-exclude-tracker=URI[,...] Comma separated list of BitTorrent tracker's\n" \
" announce URI to remove. You can use special value\n" \
" '*' which matches all URIs, thus removes all\n" \
" announce URIs. When specifying '*' in shell\n" \
" command-line, don't forget to escape or quote it.\n" \
" See also --bt-tracker option.")

View File

@ -17,6 +17,8 @@
#include "bencode2.h" #include "bencode2.h"
#include "TestUtil.h" #include "TestUtil.h"
#include "base32.h" #include "base32.h"
#include "Option.h"
#include "prefs.h"
namespace aria2 { namespace aria2 {
@ -67,6 +69,9 @@ class BittorrentHelperTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testExtract2PeersFromList); CPPUNIT_TEST(testExtract2PeersFromList);
CPPUNIT_TEST(testPackcompact); CPPUNIT_TEST(testPackcompact);
CPPUNIT_TEST(testUnpackcompact); CPPUNIT_TEST(testUnpackcompact);
CPPUNIT_TEST(testRemoveAnnounceUri);
CPPUNIT_TEST(testAddAnnounceUri);
CPPUNIT_TEST(testAdjustAnnounceUri);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
public: public:
void setUp() { void setUp() {
@ -114,6 +119,9 @@ public:
void testExtract2PeersFromList(); void testExtract2PeersFromList();
void testPackcompact(); void testPackcompact();
void testUnpackcompact(); void testUnpackcompact();
void testRemoveAnnounceUri();
void testAddAnnounceUri();
void testAdjustAnnounceUri();
}; };
@ -852,6 +860,82 @@ void BittorrentHelperTest::testUnpackcompact()
CPPUNIT_ASSERT_EQUAL((uint16_t)6881, p.second); CPPUNIT_ASSERT_EQUAL((uint16_t)6881, p.second);
} }
void BittorrentHelperTest::testRemoveAnnounceUri()
{
SharedHandle<TorrentAttribute> attrs(new TorrentAttribute());
std::vector<std::string> tier1;
tier1.push_back("http://host1/announce");
std::vector<std::string> tier2;
tier2.push_back("http://host2/announce");
tier2.push_back("http://host3/announce");
attrs->announceList.push_back(tier1);
attrs->announceList.push_back(tier2);
std::vector<std::string> removeUris;
removeUris.push_back(tier1[0]);
removeUris.push_back(tier2[0]);
removeAnnounceUri(attrs, removeUris);
CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->announceList.size());
CPPUNIT_ASSERT_EQUAL(std::string("http://host3/announce"),
attrs->announceList[0][0]);
removeUris.clear();
removeUris.push_back("*");
removeAnnounceUri(attrs, removeUris);
CPPUNIT_ASSERT(attrs->announceList.empty());
}
void BittorrentHelperTest::testAddAnnounceUri()
{
SharedHandle<TorrentAttribute> attrs(new TorrentAttribute());
std::vector<std::string> addUris;
addUris.push_back("http://host1/announce");
addUris.push_back("http://host2/announce");
addAnnounceUri(attrs, addUris);
CPPUNIT_ASSERT_EQUAL((size_t)2, attrs->announceList.size());
CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->announceList[0].size());
CPPUNIT_ASSERT_EQUAL(std::string("http://host1/announce"),
attrs->announceList[0][0]);
CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->announceList[1].size());
CPPUNIT_ASSERT_EQUAL(std::string("http://host2/announce"),
attrs->announceList[1][0]);
}
void BittorrentHelperTest::testAdjustAnnounceUri()
{
SharedHandle<TorrentAttribute> attrs(new TorrentAttribute());
std::vector<std::string> tier1;
tier1.push_back("http://host1/announce");
std::vector<std::string> tier2;
tier2.push_back("http://host2/announce");
tier2.push_back("http://host3/announce");
attrs->announceList.push_back(tier1);
attrs->announceList.push_back(tier2);
SharedHandle<Option> option(new Option());
option->put(PREF_BT_TRACKER, "http://host1/announce,http://host4/announce");
option->put(PREF_BT_EXCLUDE_TRACKER,
"http://host1/announce,http://host2/announce");
adjustAnnounceUri(attrs, option);
CPPUNIT_ASSERT_EQUAL((size_t)3, attrs->announceList.size());
CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->announceList[0].size());
CPPUNIT_ASSERT_EQUAL(std::string("http://host3/announce"),
attrs->announceList[0][0]);
CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->announceList[1].size());
CPPUNIT_ASSERT_EQUAL(std::string("http://host1/announce"),
attrs->announceList[1][0]);
CPPUNIT_ASSERT_EQUAL((size_t)1, attrs->announceList[2].size());
CPPUNIT_ASSERT_EQUAL(std::string("http://host4/announce"),
attrs->announceList[2][0]);
}
} // namespace bittorrent } // namespace bittorrent
} // namespace aria2 } // namespace aria2

View File

@ -13,6 +13,9 @@
#include "prefs.h" #include "prefs.h"
#include "Exception.h" #include "Exception.h"
#include "util.h" #include "util.h"
#ifdef ENABLE_BITTORRENT
# include "bittorrent_helper.h"
#endif // ENABLE_BITTORRENT
namespace aria2 { namespace aria2 {
@ -326,6 +329,7 @@ void DownloadHelperTest::testCreateRequestGroupForBitTorrent()
option_->put(PREF_TORRENT_FILE, "test.torrent"); option_->put(PREF_TORRENT_FILE, "test.torrent");
option_->put(PREF_DIR, "/tmp"); option_->put(PREF_DIR, "/tmp");
option_->put(PREF_OUT, "file.out"); option_->put(PREF_OUT, "file.out");
option_->put(PREF_BT_EXCLUDE_TRACKER, "http://tracker1");
{ {
std::vector<SharedHandle<RequestGroup> > result; std::vector<SharedHandle<RequestGroup> > result;
@ -343,6 +347,10 @@ void DownloadHelperTest::testCreateRequestGroupForBitTorrent()
CPPUNIT_ASSERT_EQUAL(array[i]+"/aria2-test/aria2/src/aria2c", uris[i]); CPPUNIT_ASSERT_EQUAL(array[i]+"/aria2-test/aria2/src/aria2c", uris[i]);
} }
CPPUNIT_ASSERT_EQUAL((unsigned int)5, group->getNumConcurrentCommand()); CPPUNIT_ASSERT_EQUAL((unsigned int)5, group->getNumConcurrentCommand());
SharedHandle<TorrentAttribute> attrs =
bittorrent::getTorrentAttrs(group->getDownloadContext());
// http://tracker1 was deleted.
CPPUNIT_ASSERT_EQUAL((size_t)2, attrs->announceList.size());
} }
{ {
// no URIs are given // no URIs are given