2009-11-28 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Accept BitTorrent Magnet URI in Metalink resource type bittorrent.
	Rewritten UTMetadataPostDownloadHandler. To create torrent data
	from metadata, use new metadata2Torrent() function.
	* src/BtDependency.cc
	* src/UTMetadataPostDownloadHandler.cc
	* src/bittorrent_helper.cc
	* src/bittorrent_helper.h
	* test/BittorrentHelperTest.cc
	* test/BtDependencyTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2009-11-28 09:58:49 +00:00
parent 96205abc67
commit 339795311b
7 changed files with 99 additions and 27 deletions

View File

@ -1,3 +1,15 @@
2009-11-28 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Accept BitTorrent Magnet URI in Metalink resource type bittorrent.
Rewritten UTMetadataPostDownloadHandler. To create torrent data
from metadata, use new metadata2Torrent() function.
* src/BtDependency.cc
* src/UTMetadataPostDownloadHandler.cc
* src/bittorrent_helper.cc
* src/bittorrent_helper.h
* test/BittorrentHelperTest.cc
* test/BtDependencyTest.cc
2009-11-28 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Use createRequestGroupForUri to create the download for torrent

View File

@ -71,8 +71,15 @@ bool BtDependency::resolve()
dependee->getPieceStorage()->getDiskAdaptor();
diskAdaptor->openExistingFile();
std::string content = util::toString(diskAdaptor);
if(dependee->getDownloadContext()->hasAttribute(bittorrent::BITTORRENT)) {
const BDE& attrs =
dependee->getDownloadContext()->getAttribute(bittorrent::BITTORRENT);
bittorrent::loadFromMemory
(bittorrent::metadata2Torrent(content, attrs), context, "default");
} else {
bittorrent::loadFromMemory
(content, context, File(dependee->getFirstFilePath()).getBasename());
}
if(context->getFileEntries().size() !=
_dependant->getDownloadContext()->getFileEntries().size()) {
throw DL_ABORT_EX("The number of file in torrent doesn't match to"

View File

@ -45,6 +45,7 @@
#include "a2functional.h"
#include "DiskAdaptor.h"
#include "PieceStorage.h"
#include "bencode.h"
namespace aria2 {
@ -72,35 +73,13 @@ void UTMetadataPostDownloadHandler::getNextRequestGroups
{
SharedHandle<DownloadContext> dctx = requestGroup->getDownloadContext();
const BDE& attrs = dctx->getAttribute(bittorrent::BITTORRENT);
std::string torrent =
strconcat("d4:info",
util::toString(requestGroup->getPieceStorage()->getDiskAdaptor()),
"e");
std::string metadata =
util::toString(requestGroup->getPieceStorage()->getDiskAdaptor());
std::string torrent = bittorrent::metadata2Torrent(metadata, attrs);
try {
std::deque<SharedHandle<RequestGroup> > newRgs;
createRequestGroupForBitTorrent(newRgs, requestGroup->getOption(),
std::deque<std::string>(), torrent);
if(attrs.containsKey(bittorrent::ANNOUNCE_LIST)) {
for(std::deque<SharedHandle<RequestGroup> >::const_iterator i =
newRgs.begin(); i != newRgs.end(); ++i) {
SharedHandle<DownloadContext> newDctx = (*i)->getDownloadContext();
if(!newDctx->hasAttribute(bittorrent::BITTORRENT)) {
continue;
}
BDE& newAttrs = newDctx->getAttribute(bittorrent::BITTORRENT);
if(attrs[bittorrent::INFO_HASH].s() !=
newAttrs[bittorrent::INFO_HASH].s()) {
continue;
}
assert(newAttrs[bittorrent::ANNOUNCE_LIST].isList());
if(newAttrs[bittorrent::ANNOUNCE_LIST].size() == 0) {
newAttrs[bittorrent::ANNOUNCE_LIST] =
attrs[bittorrent::ANNOUNCE_LIST];
}
break;
}
}
groups.insert(groups.end(), newRgs.begin(), newRgs.end());
} catch(RecoverableException& e) {
_logger->error("Failed to parse BitTorrent metadata.", e);

View File

@ -904,6 +904,21 @@ void loadMagnet
dctx->setAttribute(BITTORRENT, attrs);
}
std::string metadata2Torrent(const std::string& metadata, const BDE& attrs)
{
std::string torrent = "d";
if(attrs.containsKey(bittorrent::ANNOUNCE_LIST)) {
const BDE& announceList = attrs[bittorrent::ANNOUNCE_LIST];
if(announceList.size() > 0) {
torrent += "13:announce-list";
torrent += bencode::encode(announceList);
}
}
torrent +=
strconcat("4:info", metadata, "e");
return torrent;
}
} // namespace bittorrent
} // namespace aria2

View File

@ -230,6 +230,11 @@ void assertID
void generateRandomKey(unsigned char* key);
// Converts attrs into torrent data. attrs must be a BDE::dict. This
// function does not guarantee the returned string is valid torrent
// data.
std::string metadata2Torrent(const std::string& metadata, const BDE& attrs);
} // namespace bittorrent
} // namespace aria2

View File

@ -61,6 +61,7 @@ class BittorrentHelperTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testMetadata);
CPPUNIT_TEST(testParseMagnet);
CPPUNIT_TEST(testParseMagnet_base32);
CPPUNIT_TEST(testMetadata2Torrent);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {
@ -102,6 +103,7 @@ public:
void testMetadata();
void testParseMagnet();
void testParseMagnet_base32();
void testMetadata2Torrent();
};
@ -734,6 +736,25 @@ void BittorrentHelperTest::testParseMagnet_base32()
util::toHex(attrs[bittorrent::INFO_HASH].s()));
}
void BittorrentHelperTest::testMetadata2Torrent()
{
std::string metadata = "METADATA";
BDE attrs = BDE::dict();
BDE announceList = BDE::list();
attrs[ANNOUNCE_LIST] = announceList;
CPPUNIT_ASSERT_EQUAL
(std::string("d4:infoMETADATAe"), metadata2Torrent(metadata, attrs));
announceList << BDE::list();
announceList[0] << std::string("http://localhost/announce");
CPPUNIT_ASSERT_EQUAL
(std::string("d"
"13:announce-list"
"ll25:http://localhost/announceee"
"4:infoMETADATA"
"e"),
metadata2Torrent(metadata, attrs));
}
} // namespace bittorrent
} // namespace aria2

View File

@ -13,6 +13,9 @@
#include "FileEntry.h"
#include "PieceSelector.h"
#include "bittorrent_helper.h"
#include "DirectDiskAdaptor.h"
#include "ByteArrayDiskWriter.h"
#include "MockPieceStorage.h"
namespace aria2 {
@ -20,6 +23,7 @@ class BtDependencyTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(BtDependencyTest);
CPPUNIT_TEST(testResolve);
CPPUNIT_TEST(testResolve_metadata);
CPPUNIT_TEST(testResolve_loadError);
CPPUNIT_TEST(testResolve_dependeeFailure);
CPPUNIT_TEST(testResolve_dependeeInProgress);
@ -64,6 +68,7 @@ public:
}
void testResolve();
void testResolve_metadata();
void testResolve_loadError();
void testResolve_dependeeFailure();
void testResolve_dependeeInProgress();
@ -93,6 +98,34 @@ void BtDependencyTest::testResolve()
CPPUNIT_ASSERT_EQUAL((size_t)1, firstFileEntry->getRemainingUris().size());
}
void BtDependencyTest::testResolve_metadata()
{
SharedHandle<RequestGroup> dependant = createDependant(_option);
SharedHandle<RequestGroup> dependee =
createDependee(_option, "metadata", 0);
SharedHandle<DirectDiskAdaptor> diskAdaptor(new DirectDiskAdaptor());
SharedHandle<ByteArrayDiskWriter> diskWriter(new ByteArrayDiskWriter());
diskAdaptor->setDiskWriter(diskWriter);
diskWriter->setString
("d4:name19:aria2-0.8.2.tar.bz26:lengthi384e12:piece lengthi128e"
"6:pieces60:AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCC"
"e");
SharedHandle<MockPieceStorage> pieceStorage(new MockPieceStorage());
pieceStorage->setDiskAdaptor(diskAdaptor);
pieceStorage->setDownloadFinished(true);
dependee->setPieceStorage(pieceStorage);
BDE attrs = BDE::dict();
dependee->getDownloadContext()->setAttribute(bittorrent::BITTORRENT, attrs);
BtDependency dep(dependant, dependee);
CPPUNIT_ASSERT(dep.resolve());
CPPUNIT_ASSERT_EQUAL
(std::string("cd41c7fdddfd034a15a04d7ff881216e01c4ceaf"),
bittorrent::getInfoHashString(dependant->getDownloadContext()));
}
void BtDependencyTest::testResolve_loadError()
{
SharedHandle<RequestGroup> dependant = createDependant(_option);