Sfoglia il codice sorgente

Add --bt-load-saved-metadata option

Before getting torrent metadata from DHT when downloading with magnet
link, first try to read file saved by --bt-save-metadata option. If it
is successful, then skip downloading metadata from DHT.  By default,
this feature is turned off.
Tatsuhiro Tsujikawa 8 anni fa
parent
commit
9deb4210b2
5 ha cambiato i file con 58 aggiunte e 5 eliminazioni
  1. 10 0
      src/OptionHandlerFactory.cc
  2. 36 5
      src/download_helper.cc
  3. 2 0
      src/prefs.cc
  4. 2 0
      src/prefs.h
  5. 8 0
      src/usage_text.h

+ 10 - 0
src/OptionHandlerFactory.cc

@@ -1527,6 +1527,16 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     op->setChangeOptionForReserved(true);
     handlers.push_back(op);
   }
+  {
+    OptionHandler* op(new BooleanOptionHandler(
+        PREF_BT_LOAD_SAVED_METADATA, TEXT_BT_LOAD_SAVED_METADATA, A2_V_FALSE,
+        OptionHandler::OPT_ARG));
+    op->addTag(TAG_BITTORRENT);
+    op->setInitialOption(true);
+    op->setChangeGlobalOption(true);
+    op->setChangeOptionForReserved(true);
+    handlers.push_back(op);
+  }
   {
     OptionHandler* op(new DefaultOptionHandler(
         PREF_BT_LPD_INTERFACE, TEXT_BT_LPD_INTERFACE, NO_DEFAULT_VALUE,

+ 36 - 5
src/download_helper.cc

@@ -237,23 +237,54 @@ std::shared_ptr<RequestGroup>
 createBtMagnetRequestGroup(const std::string& magnetLink,
                            const std::shared_ptr<Option>& optionTemplate)
 {
-  auto option = util::copy(optionTemplate);
-  auto gid = getGID(option);
-  auto rg = std::make_shared<RequestGroup>(gid, option);
   auto dctx = std::make_shared<DownloadContext>(METADATA_PIECE_SIZE, 0);
 
   // We only know info hash. Total Length is unknown at this moment.
   dctx->markTotalLengthIsUnknown();
-  rg->setFileAllocationEnabled(false);
-  rg->setPreLocalFileCheckEnabled(false);
+
   bittorrent::loadMagnet(magnetLink, dctx);
   auto torrentAttrs = bittorrent::getTorrentAttrs(dctx);
+
+  if (optionTemplate->getAsBool(PREF_BT_LOAD_SAVED_METADATA)) {
+    // Try to read .torrent file saved by aria2 (see
+    // UTMetadataPostDownloadHandler and --bt-save-metadata option).
+    auto torrentFilename =
+        util::applyDir(optionTemplate->get(PREF_DIR),
+                       util::toHex(torrentAttrs->infoHash) + ".torrent");
+
+    bittorrent::ValueBaseBencodeParser parser;
+    auto torrent = parseFile(parser, torrentFilename);
+    if (torrent) {
+      auto rg = createBtRequestGroup(torrentFilename, optionTemplate, {},
+                                     torrent.get());
+      const auto& actualInfoHash =
+          bittorrent::getTorrentAttrs(rg->getDownloadContext())->infoHash;
+
+      if (torrentAttrs->infoHash == actualInfoHash) {
+        A2_LOG_NOTICE(fmt("BitTorrent metadata was loaded from %s",
+                          torrentFilename.c_str()));
+        rg->setMetadataInfo(createMetadataInfo(rg->getGroupId(), magnetLink));
+        return rg;
+      }
+
+      A2_LOG_WARN(
+          fmt("BitTorrent metadata loaded from %s has unexpected infohash %s\n",
+              torrentFilename.c_str(), util::toHex(actualInfoHash).c_str()));
+    }
+  }
+
+  auto option = util::copy(optionTemplate);
   bittorrent::adjustAnnounceUri(torrentAttrs, option);
   // torrentAttrs->name may contain "/", but we use basename of
   // FileEntry::getPath() to print out in-memory download entry.
   // Since "/" is treated as separator, we replace it with "-".
   dctx->getFirstFileEntry()->setPath(
       util::replace(torrentAttrs->name, "/", "-"));
+
+  auto gid = getGID(option);
+  auto rg = std::make_shared<RequestGroup>(gid, option);
+  rg->setFileAllocationEnabled(false);
+  rg->setPreLocalFileCheckEnabled(false);
   rg->setDownloadContext(dctx);
   rg->clearPostDownloadHandler();
   rg->addPostDownloadHandler(

+ 2 - 0
src/prefs.cc

@@ -563,6 +563,8 @@ PrefPtr PREF_BT_FORCE_ENCRYPTION = makePref("bt-force-encryption");
 // values: true | false
 PrefPtr PREF_BT_ENABLE_HOOK_AFTER_HASH_CHECK =
     makePref("bt-enable-hook-after-hash-check");
+// values: true | false
+PrefPtr PREF_BT_LOAD_SAVED_METADATA = makePref("bt-load-saved-metadata");
 
 /**
  * Metalink related preferences

+ 2 - 0
src/prefs.h

@@ -514,6 +514,8 @@ extern PrefPtr PREF_BT_DETACH_SEED_ONLY;
 extern PrefPtr PREF_BT_FORCE_ENCRYPTION;
 // values: true | false
 extern PrefPtr PREF_BT_ENABLE_HOOK_AFTER_HASH_CHECK;
+// values: true | false
+extern PrefPtr PREF_BT_LOAD_SAVED_METADATA;
 
 /**
  * Metalink related preferences

+ 8 - 0
src/usage_text.h

@@ -1117,4 +1117,12 @@
     "                              number of unfinished download result to keep. If\n" \
     "                              that is undesirable, turn this option off.")
 
+#define TEXT_BT_LOAD_SAVED_METADATA \
+  _(" --bt-load-saved-metadata[=true|false]\n" \
+    "                              Before getting torrent metadata from DHT when\n" \
+    "                              downloading with magnet link, first try to read\n" \
+    "                              file saved by --bt-save-metadata option. If it is\n" \
+    "                              successful, then skip downloading metadata from\n" \
+    "                              DHT.")
+
 // clang-format on