Parcourir la source

2007-10-27 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	Added the ability to recognize url-list in a torrent file.
	The retrieved URLs are attached to the corresponding FileEntry.
	* src/DefaultBtContext.{h, cc}
	* src/FileEntry.{h, cc}
	* test/DefaultBtContextTest.cc
Tatsuhiro Tsujikawa il y a 18 ans
Parent
commit
368d53071a

+ 32 - 4
src/DefaultBtContext.cc

@@ -98,7 +98,8 @@ void DefaultBtContext::extractPieceHash(const unsigned char* hashData,
 }
 
 void DefaultBtContext::extractFileEntries(Dictionary* infoDic,
-					  const string& defaultName) {
+					  const string& defaultName,
+					  const Strings& urlList) {
   // TODO use dynamic_cast
   Data* nameData = (Data*)infoDic->get("name");
   if(nameData) {
@@ -134,9 +135,13 @@ void DefaultBtContext::extractFileEntries(Dictionary* infoDic,
       Data* lastPath = (Data*)paths.back();
       path += lastPath->toString();
 
+      Strings uris;
+      transform(urlList.begin(), urlList.end(), back_inserter(uris),
+		bind2nd(plus<string>(), "/"+name+"/"+path));
       FileEntryHandle fileEntry(new FileEntry(path,
 					      lengthData->toLLInt(),
-					      offset));
+					      offset,
+					      uris));
       fileEntries.push_back(fileEntry);
       offset += fileEntry->getLength();
     }
@@ -146,7 +151,7 @@ void DefaultBtContext::extractFileEntries(Dictionary* infoDic,
     fileMode = BtContext::SINGLE;
     Data* length = (Data*)infoDic->get("length");
     totalLength = length->toLLInt();
-    FileEntryHandle fileEntry(new FileEntry(name, totalLength, 0));
+    FileEntryHandle fileEntry(new FileEntry(name, totalLength, 0, urlList));
     fileEntries.push_back(fileEntry);
   }
 }
@@ -174,6 +179,25 @@ void DefaultBtContext::extractAnnounceList(List* announceListData) {
   }
 }
 
+Strings DefaultBtContext::extractUrlList(const MetaEntry* obj)
+{
+  Strings uris;
+  if(dynamic_cast<const List*>(obj)) {
+    const List* urlList = (const List*)obj;
+    for(MetaList::const_iterator itr = urlList->getList().begin();
+	itr != urlList->getList().end(); ++itr) {
+      Data* data = dynamic_cast<Data*>(*itr);
+      if(data) {
+	uris.push_back(data->toString());
+      }
+    }
+  } else if(dynamic_cast<const Data*>(obj)) {
+    const Data* urlData = (const Data*)obj;
+    uris.push_back(urlData->toString());
+  }
+  return uris;
+}
+
 void DefaultBtContext::load(const string& torrentFile) {
   clear();
   MetaEntry* rootEntry = MetaFileUtil::parseMetaFile(torrentFile);
@@ -199,8 +223,12 @@ void DefaultBtContext::load(const string& torrentFile) {
   extractPieceHash((unsigned char*)pieceHashData->getData(),
 		   pieceHashData->getLen(),
 		   PIECE_HASH_LENGTH);
+  // retrieve uri-list.
+  // This implemantation obeys HTTP-Seeding specification:
+  // see http://www.getright.com/seedtorrent.html
+  Strings urlList = extractUrlList(rootDic->get("url-list"));
   // retrieve file entries
-  extractFileEntries(infoDic, torrentFile);
+  extractFileEntries(infoDic, torrentFile, urlList);
   // retrieve announce
   Data* announceData = (Data*)rootDic->get("announce");
   List* announceListData = (List*)rootDic->get("announce-list");

+ 5 - 1
src/DefaultBtContext.h

@@ -66,9 +66,13 @@ private:
 			int32_t hashDataLength,
 			int32_t hashLength);
   void extractFileEntries(Dictionary* infoDic,
-			  const string& defaultName);
+			  const string& defaultName,
+			  const Strings& urlList);
   void extractAnnounce(Data* announceData);
   void extractAnnounceList(List* announceListData);
+
+  Strings extractUrlList(const MetaEntry* obj);
+
  public:
   DefaultBtContext();
   virtual ~DefaultBtContext();

+ 3 - 2
src/FileEntry.cc

@@ -39,8 +39,9 @@
 
 FileEntry::FileEntry(const string& path,
 		     int64_t length,
-		     int64_t offset):
-  path(path), length(length), offset(offset),
+		     int64_t offset,
+		     const Strings& uris):
+  path(path), _uris(uris), length(length), offset(offset),
   extracted(false), requested(true) {}
 
 FileEntry::~FileEntry() {}

+ 7 - 1
src/FileEntry.h

@@ -41,6 +41,7 @@
 class FileEntry {
 private:
   string path;
+  Strings _uris;
   int64_t length;
   int64_t offset;
   bool extracted;
@@ -48,7 +49,7 @@ private:
 public:
   FileEntry():length(0), offset(0), extracted(false), requested(false) {}
 
-  FileEntry(const string& path, int64_t length, int64_t offset);
+  FileEntry(const string& path, int64_t length, int64_t offset, const Strings& uris = Strings());
 
   ~FileEntry();
 
@@ -85,6 +86,11 @@ public:
   void setRequested(bool flag) { this->requested = flag; }
 
   void setupDir(const string& parentDir);
+
+  const Strings& getAssociatedUris() const
+  {
+    return _uris;
+  }
 };
 
 typedef SharedHandle<FileEntry> FileEntryHandle;

+ 52 - 0
test/DefaultBtContextTest.cc

@@ -25,6 +25,8 @@ class DefaultBtContextTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testGetInfoHashAsString);
   CPPUNIT_TEST(testGetPeerId);
   CPPUNIT_TEST(testComputeFastSet);
+  CPPUNIT_TEST(testGetFileEntries_multiFileUrlList);
+  CPPUNIT_TEST(testGetFileEntries_singleFileUrlList);
   CPPUNIT_TEST_SUITE_END();
 public:
   void setUp() {
@@ -46,6 +48,8 @@ public:
   void testGetInfoHashAsString();
   void testGetPeerId();
   void testComputeFastSet();
+  void testGetFileEntries_multiFileUrlList();
+  void testGetFileEntries_singleFileUrlList();
 };
 
 
@@ -255,3 +259,51 @@ void DefaultBtContextTest::testComputeFastSet()
   Integers ansSet2(&ans2[0], &ans2[10]);
   CPPUNIT_ASSERT(equal(fastSet.begin(), fastSet.end(), ansSet2.begin()));
 }
+
+void DefaultBtContextTest::testGetFileEntries_multiFileUrlList() {
+  DefaultBtContext btContext;
+  btContext.load("url-list-multiFile.torrent");
+  // This is multi-file torrent.
+  FileEntries fileEntries = btContext.getFileEntries();
+  // There are 2 file entries.
+  CPPUNIT_ASSERT_EQUAL((size_t)2, fileEntries.size());
+  FileEntries::iterator itr = fileEntries.begin();
+
+  FileEntryHandle fileEntry1 = *itr;
+  CPPUNIT_ASSERT_EQUAL(string("aria2/src/aria2c"),
+		       fileEntry1->getPath());
+  Strings uris1 = fileEntry1->getAssociatedUris();
+  CPPUNIT_ASSERT_EQUAL((size_t)2, uris1.size());
+  CPPUNIT_ASSERT_EQUAL(string("http://localhost/dist/aria2-test/aria2/src/aria2c"),
+		       uris1[0]);
+  CPPUNIT_ASSERT_EQUAL(string("http://mirror/dist/aria2-test/aria2/src/aria2c"),
+		       uris1[1]);
+
+  itr++;
+  FileEntryHandle fileEntry2 = *itr;
+  CPPUNIT_ASSERT_EQUAL(string("aria2-0.2.2.tar.bz2"),
+		       fileEntry2->getPath());
+  Strings uris2 = fileEntry2->getAssociatedUris();
+  CPPUNIT_ASSERT_EQUAL((size_t)2, uris2.size());
+  CPPUNIT_ASSERT_EQUAL(string("http://localhost/dist/aria2-test/aria2-0.2.2.tar.bz2"),
+		       uris2[0]);
+  CPPUNIT_ASSERT_EQUAL(string("http://mirror/dist/aria2-test/aria2-0.2.2.tar.bz2"),
+		       uris2[1]);
+}
+
+void DefaultBtContextTest::testGetFileEntries_singleFileUrlList() {
+  DefaultBtContext btContext;
+  btContext.load("url-list-singleFile.torrent");
+  // This is multi-file torrent.
+  FileEntries fileEntries = btContext.getFileEntries();
+  // There are 1 file entries.
+  CPPUNIT_ASSERT_EQUAL((size_t)1, fileEntries.size());
+
+  FileEntryHandle fileEntry1 = fileEntries.front();
+  CPPUNIT_ASSERT_EQUAL(string("aria2.tar.bz2"),
+		       fileEntry1->getPath());
+  Strings uris1 = fileEntry1->getAssociatedUris();
+  CPPUNIT_ASSERT_EQUAL((size_t)1, uris1.size());
+  CPPUNIT_ASSERT_EQUAL(string("http://localhost/dist/aria2.tar.bz2"),
+		       uris1[0]);
+}

+ 1 - 0
test/url-list-multiFile.torrent

@@ -0,0 +1 @@
+d8:url-listl21:http://localhost/dist18:http://mirror/diste8:announce36:http://aria.rednoah.com/announce.php13:announce-listll15:http://tracker1el15:http://tracker2el15:http://tracker3ee7:comment17:REDNOAH.COM RULES13:creation datei1123456789e4:infod5:filesld6:lengthi284e4:pathl5:aria23:src6:aria2ceed6:lengthi100e4:pathl19:aria2-0.2.2.tar.bz2eee4:name10:aria2-test12:piece lengthi128e6:pieces60:AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCee

+ 1 - 0
test/url-list-singleFile.torrent

@@ -0,0 +1 @@
+d8:url-list35:http://localhost/dist/aria2.tar.bz28:announce36:http://aria.rednoah.com/announce.php13:announce-listll15:http://tracker1el15:http://tracker2el15:http://tracker3ee7:comment17:REDNOAH.COM RULES13:creation datei1123456789e4:infod6:lengthi7680e4:name13:aria2.tar.bz212:piece lengthi128e6:pieces60:AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCee