From cbc0ef860b0aea00ad791a4e03e19fb1342f14e8 Mon Sep 17 00:00:00 2001 From: "Vladimir Golovnev (Glassez)" Date: Wed, 2 Mar 2022 14:16:33 +0300 Subject: [PATCH 1/2] Prevent loading resume data with inconsistent ID --- src/base/bittorrent/session.cpp | 83 ++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index c9fea0e68..449a7a91b 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -4480,53 +4480,62 @@ void Session::startUpTorrents() const lt::info_hash_t infoHash = (resumeData.ltAddTorrentParams.ti ? resumeData.ltAddTorrentParams.ti->info_hashes() : resumeData.ltAddTorrentParams.info_hashes); - if (infoHash.has_v1() && infoHash.has_v2()) + const bool isHybrid = infoHash.has_v1() && infoHash.has_v2(); + const auto torrentIDv2 = TorrentID::fromInfoHash(infoHash); + const auto torrentIDv1 = TorrentID::fromInfoHash(lt::info_hash_t(infoHash.v1)); + if (torrentID == torrentIDv2) { - const auto torrentIDv1 = TorrentID::fromInfoHash(lt::info_hash_t(infoHash.v1)); - const auto torrentIDv2 = TorrentID::fromInfoHash(infoHash); - if (torrentID == torrentIDv2) + if (isHybrid && indexedTorrents.contains(torrentIDv1)) { - if (indexedTorrents.contains(torrentIDv1)) + // if we don't have metadata, try to find it in alternative "resume data" + if (!resumeData.ltAddTorrentParams.ti) { - // if we has no metadata trying to find it in alternative "resume data" - if (!resumeData.ltAddTorrentParams.ti) - { - const std::optional loadAltResumeDataResult = startupStorage->load(torrentIDv1); - if (loadAltResumeDataResult) - { - LoadTorrentParams altResumeData = *loadAltResumeDataResult; - resumeData.ltAddTorrentParams.ti = altResumeData.ltAddTorrentParams.ti; - } - } - - // remove alternative "resume data" and skip the attempt to load it - m_resumeDataStorage->remove(torrentIDv1); - skippedIDs.insert(torrentIDv1); + const std::optional loadAltResumeDataResult = startupStorage->load(torrentIDv1); + if (loadAltResumeDataResult) + resumeData.ltAddTorrentParams.ti = loadAltResumeDataResult->ltAddTorrentParams.ti; } - } - else - { - torrentID = torrentIDv2; - needStore = true; + + // remove alternative "resume data" and skip the attempt to load it m_resumeDataStorage->remove(torrentIDv1); + skippedIDs.insert(torrentIDv1); + } + } + else if (torrentID == torrentIDv1) + { + torrentID = torrentIDv2; + needStore = true; + m_resumeDataStorage->remove(torrentIDv1); - if (indexedTorrents.contains(torrentID)) + if (indexedTorrents.contains(torrentID)) + { + skippedIDs.insert(torrentID); + + const std::optional loadPreferredResumeDataResult = startupStorage->load(torrentID); + if (loadPreferredResumeDataResult) { - skippedIDs.insert(torrentID); - - const std::optional loadPreferredResumeDataResult = startupStorage->load(torrentID); - if (loadPreferredResumeDataResult) - { - LoadTorrentParams preferredResumeData = *loadPreferredResumeDataResult; - std::shared_ptr ti = resumeData.ltAddTorrentParams.ti; - if (!preferredResumeData.ltAddTorrentParams.ti) - preferredResumeData.ltAddTorrentParams.ti = ti; - - resumeData = preferredResumeData; - } + std::shared_ptr ti = resumeData.ltAddTorrentParams.ti; + resumeData = *loadPreferredResumeDataResult; + if (!resumeData.ltAddTorrentParams.ti) + resumeData.ltAddTorrentParams.ti = ti; } } } + else + { + LogMsg(tr("Failed to resume torrent: inconsistent torrent ID is detected. Torrent: \"%1\"") + .arg(torrentID.toString()), Log::WARNING); + continue; + } +#else + const lt::sha1_hash infoHash = (resumeData.ltAddTorrentParams.ti + ? resumeData.ltAddTorrentParams.ti->info_hash() + : resumeData.ltAddTorrentParams.info_hash); + if (torrentID != TorrentID::fromInfoHash(infoHash)) + { + LogMsg(tr("Failed to resume torrent: inconsistent torrent ID is detected. Torrent: \"%1\"") + .arg(torrentID.toString()), Log::WARNING); + continue; + } #endif if (m_resumeDataStorage != startupStorage) From ce42f7c9f154d5a8e8d6e50384779f0300dca0e6 Mon Sep 17 00:00:00 2001 From: "Vladimir Golovnev (Glassez)" Date: Mon, 14 Mar 2022 12:03:54 +0300 Subject: [PATCH 2/2] Properly handle metadata download for an existing torrent --- src/base/bittorrent/torrentimpl.cpp | 35 ++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/base/bittorrent/torrentimpl.cpp b/src/base/bittorrent/torrentimpl.cpp index c53af8777..dbd36038e 100644 --- a/src/base/bittorrent/torrentimpl.cpp +++ b/src/base/bittorrent/torrentimpl.cpp @@ -287,7 +287,8 @@ TorrentImpl::TorrentImpl(Session *session, lt::session *nativeSession const std::shared_ptr currentInfo = m_nativeHandle.torrent_file(); const lt::file_storage &fileStorage = currentInfo->files(); const std::vector filePriorities = - resized(m_ltAddTorrentParams.file_priorities, fileStorage.num_files(), LT::toNative(DownloadPriority::Normal)); + resized(m_ltAddTorrentParams.file_priorities, fileStorage.num_files() + , LT::toNative(m_ltAddTorrentParams.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored)); for (int i = 0; i < filesCount; ++i) { const lt::file_index_t nativeIndex = m_torrentInfo.nativeIndexes().at(i); @@ -1491,21 +1492,19 @@ void TorrentImpl::updatePeerCount(const QString &trackerUrl, const lt::tcp::endp void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathList &fileNames) { Q_ASSERT(m_filePaths.isEmpty()); - Q_ASSERT(m_indexMap.isEmpty()); lt::add_torrent_params &p = m_ltAddTorrentParams; const std::shared_ptr metadata = std::const_pointer_cast(m_nativeHandle.torrent_file()); m_torrentInfo = TorrentInfo(*metadata); - m_indexMap.reserve(filesCount()); m_filePriorities.reserve(filesCount()); const auto nativeIndexes = m_torrentInfo.nativeIndexes(); const std::vector filePriorities = - resized(p.file_priorities, metadata->files().num_files(), LT::toNative(DownloadPriority::Normal)); + resized(p.file_priorities, metadata->files().num_files() + , LT::toNative(p.file_priorities.empty() ? DownloadPriority::Normal : DownloadPriority::Ignored)); for (int i = 0; i < fileNames.size(); ++i) { const auto nativeIndex = nativeIndexes.at(i); - m_indexMap[nativeIndex] = i; Path filePath = fileNames.at(i); p.renamed_files[nativeIndex] = filePath.toString().toStdString(); @@ -1518,10 +1517,7 @@ void TorrentImpl::endReceivedMetadataHandling(const Path &savePath, const PathLi } p.save_path = savePath.toString().toStdString(); p.ti = metadata; - - const int internalFilesCount = p.ti->files().num_files(); // including .pad files - // Use qBittorrent default priority rather than libtorrent's (4) - p.file_priorities = std::vector(internalFilesCount, LT::toNative(DownloadPriority::Normal)); + p.file_priorities = filePriorities; reload(); @@ -1563,7 +1559,8 @@ void TorrentImpl::reload() } m_nativeHandle = m_nativeSession->add_torrent(p); - m_nativeHandle.queue_position_set(queuePos); + if (queuePos >= lt::queue_position_t {}) + m_nativeHandle.queue_position_set(queuePos); } void TorrentImpl::pause() @@ -1754,6 +1751,8 @@ void TorrentImpl::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p) { if (m_maintenanceJob == MaintenanceJob::HandleMetadata) { + Q_ASSERT(m_indexMap.isEmpty()); + m_ltAddTorrentParams = p->params; m_ltAddTorrentParams.have_pieces.clear(); @@ -1761,8 +1760,21 @@ void TorrentImpl::handleSaveResumeDataAlert(const lt::save_resume_data_alert *p) TorrentInfo metadata = TorrentInfo(*m_nativeHandle.torrent_file()); + const auto nativeIndexes = metadata.nativeIndexes(); PathList filePaths = metadata.filePaths(); applyContentLayout(filePaths, m_contentLayout); + + const auto &renamedFiles = m_ltAddTorrentParams.renamed_files; + m_indexMap.reserve(filePaths.size()); + for (int i = 0; i < filePaths.size(); ++i) + { + const auto nativeIndex = nativeIndexes.at(i); + m_indexMap[nativeIndex] = i; + + if (const auto it = renamedFiles.find(nativeIndex); it != renamedFiles.cend()) + filePaths[i] = Path(it->second); + } + m_session->findIncompleteFiles(metadata, savePath(), downloadPath(), filePaths); } else @@ -1891,6 +1903,9 @@ void TorrentImpl::handleFileRenameFailedAlert(const lt::file_rename_failed_alert void TorrentImpl::handleFileCompletedAlert(const lt::file_completed_alert *p) { + if (m_maintenanceJob == MaintenanceJob::HandleMetadata) + return; + if (m_session->isAppendExtensionEnabled()) { const int fileIndex = m_indexMap.value(p->index, -1);