Browse Source

Merge pull request #14816 from glassez/tracker-entry

Improve "tracker entries" handling
adaptive-webui-19844
Vladimir Golovnev 4 years ago committed by GitHub
parent
commit
376dedebb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      src/base/bittorrent/torrent.h
  2. 78
      src/base/bittorrent/torrentimpl.cpp
  3. 5
      src/base/bittorrent/torrentimpl.h
  4. 4
      src/base/bittorrent/trackerentry.h
  5. 13
      src/gui/properties/trackerlistwidget.cpp
  6. 7
      src/webui/api/torrentscontroller.cpp

7
src/base/bittorrent/torrent.h

@ -84,12 +84,6 @@ namespace BitTorrent
Error Error
}; };
struct TrackerInfo
{
QString lastMessage;
int numPeers = 0;
};
uint qHash(TorrentState key, uint seed); uint qHash(TorrentState key, uint seed);
class Torrent : public AbstractFileStorage class Torrent : public AbstractFileStorage
@ -211,7 +205,6 @@ namespace BitTorrent
virtual bool hasFilteredPieces() const = 0; virtual bool hasFilteredPieces() const = 0;
virtual int queuePosition() const = 0; virtual int queuePosition() const = 0;
virtual QVector<TrackerEntry> trackers() const = 0; virtual QVector<TrackerEntry> trackers() const = 0;
virtual QHash<QString, TrackerInfo> trackerInfos() const = 0;
virtual QVector<QUrl> urlSeeds() const = 0; virtual QVector<QUrl> urlSeeds() const = 0;
virtual QString error() const = 0; virtual QString error() const = 0;
virtual qlonglong totalDownload() const = 0; virtual qlonglong totalDownload() const = 0;

78
src/base/bittorrent/torrentimpl.cpp

@ -97,9 +97,11 @@ namespace
} }
#if (LIBTORRENT_VERSION_NUM >= 20000) #if (LIBTORRENT_VERSION_NUM >= 20000)
TrackerEntry fromNativeAnnouncerEntry(const lt::announce_entry &nativeEntry, const lt::info_hash_t &hashes) TrackerEntry fromNativeAnnouncerEntry(const lt::announce_entry &nativeEntry
, const lt::info_hash_t &hashes, const QMap<lt::tcp::endpoint, int> &trackerPeerCounts)
#else #else
TrackerEntry fromNativeAnnouncerEntry(const lt::announce_entry &nativeEntry) TrackerEntry fromNativeAnnouncerEntry(const lt::announce_entry &nativeEntry
, const QMap<lt::tcp::endpoint, int> &trackerPeerCounts)
#endif #endif
{ {
TrackerEntry trackerEntry {QString::fromStdString(nativeEntry.url), nativeEntry.tier}; TrackerEntry trackerEntry {QString::fromStdString(nativeEntry.url), nativeEntry.tier};
@ -107,6 +109,8 @@ namespace
int numUpdating = 0; int numUpdating = 0;
int numWorking = 0; int numWorking = 0;
int numNotWorking = 0; int numNotWorking = 0;
QString firstTrackerMessage;
QString firstErrorMessage;
#if (LIBTORRENT_VERSION_NUM >= 20000) #if (LIBTORRENT_VERSION_NUM >= 20000)
const int numEndpoints = nativeEntry.endpoints.size() * ((hashes.has_v1() && hashes.has_v2()) ? 2 : 1); const int numEndpoints = nativeEntry.endpoints.size() * ((hashes.has_v1() && hashes.has_v2()) ? 2 : 1);
trackerEntry.endpoints.reserve(numEndpoints); trackerEntry.endpoints.reserve(numEndpoints);
@ -120,9 +124,11 @@ namespace
TrackerEntry::EndpointStats trackerEndpoint; TrackerEntry::EndpointStats trackerEndpoint;
trackerEndpoint.protocolVersion = (protocolVersion == lt::protocol_version::V1) ? 1 : 2; trackerEndpoint.protocolVersion = (protocolVersion == lt::protocol_version::V1) ? 1 : 2;
trackerEndpoint.numPeers = trackerPeerCounts.value(endpoint.local_endpoint, -1);
trackerEndpoint.numSeeds = infoHash.scrape_complete; trackerEndpoint.numSeeds = infoHash.scrape_complete;
trackerEndpoint.numLeeches = infoHash.scrape_incomplete; trackerEndpoint.numLeeches = infoHash.scrape_incomplete;
trackerEndpoint.numDownloaded = infoHash.scrape_downloaded; trackerEndpoint.numDownloaded = infoHash.scrape_downloaded;
if (infoHash.updating) if (infoHash.updating)
{ {
trackerEndpoint.status = TrackerEntry::Updating; trackerEndpoint.status = TrackerEntry::Updating;
@ -142,11 +148,21 @@ namespace
{ {
trackerEndpoint.status = TrackerEntry::NotContacted; trackerEndpoint.status = TrackerEntry::NotContacted;
} }
const QString trackerMessage = QString::fromStdString(infoHash.message);
const QString errorMessage = QString::fromLocal8Bit(infoHash.last_error.message().c_str());
trackerEndpoint.message = (!trackerMessage.isEmpty() ? trackerMessage : errorMessage);
trackerEntry.endpoints.append(trackerEndpoint); trackerEntry.endpoints.append(trackerEndpoint);
trackerEntry.numPeers = std::max(trackerEntry.numPeers, trackerEndpoint.numPeers);
trackerEntry.numSeeds = std::max(trackerEntry.numSeeds, trackerEndpoint.numSeeds);
trackerEntry.numLeeches = std::max(trackerEntry.numLeeches, trackerEndpoint.numLeeches);
trackerEntry.numDownloaded = std::max(trackerEntry.numDownloaded, trackerEndpoint.numDownloaded);
trackerEntry.numSeeds = std::max(trackerEntry.numSeeds, infoHash.scrape_complete); if (firstTrackerMessage.isEmpty())
trackerEntry.numLeeches = std::max(trackerEntry.numLeeches, infoHash.scrape_incomplete); firstTrackerMessage = trackerMessage;
trackerEntry.numDownloaded = std::max(trackerEntry.numDownloaded, infoHash.scrape_downloaded); if (firstErrorMessage.isEmpty())
firstErrorMessage = errorMessage;
} }
} }
} }
@ -156,9 +172,11 @@ namespace
for (const lt::announce_endpoint &endpoint : nativeEntry.endpoints) for (const lt::announce_endpoint &endpoint : nativeEntry.endpoints)
{ {
TrackerEntry::EndpointStats trackerEndpoint; TrackerEntry::EndpointStats trackerEndpoint;
trackerEndpoint.numPeers = trackerPeerCounts.value(endpoint.local_endpoint, -1);
trackerEndpoint.numSeeds = endpoint.scrape_complete; trackerEndpoint.numSeeds = endpoint.scrape_complete;
trackerEndpoint.numLeeches = endpoint.scrape_incomplete; trackerEndpoint.numLeeches = endpoint.scrape_incomplete;
trackerEndpoint.numDownloaded = endpoint.scrape_downloaded; trackerEndpoint.numDownloaded = endpoint.scrape_downloaded;
if (endpoint.updating) if (endpoint.updating)
{ {
trackerEndpoint.status = TrackerEntry::Updating; trackerEndpoint.status = TrackerEntry::Updating;
@ -178,22 +196,40 @@ namespace
{ {
trackerEndpoint.status = TrackerEntry::NotContacted; trackerEndpoint.status = TrackerEntry::NotContacted;
} }
const QString trackerMessage = QString::fromStdString(endpoint.message);
const QString errorMessage = QString::fromLocal8Bit(endpoint.last_error.message().c_str());
trackerEndpoint.message = (!trackerMessage.isEmpty() ? trackerMessage : errorMessage);
trackerEntry.endpoints.append(trackerEndpoint); trackerEntry.endpoints.append(trackerEndpoint);
trackerEntry.numPeers = std::max(trackerEntry.numPeers, trackerEndpoint.numPeers);
trackerEntry.numSeeds = std::max(trackerEntry.numSeeds, trackerEndpoint.numSeeds);
trackerEntry.numLeeches = std::max(trackerEntry.numLeeches, trackerEndpoint.numLeeches);
trackerEntry.numDownloaded = std::max(trackerEntry.numDownloaded, trackerEndpoint.numDownloaded);
trackerEntry.numSeeds = std::max(trackerEntry.numSeeds, endpoint.scrape_complete); if (firstTrackerMessage.isEmpty())
trackerEntry.numLeeches = std::max(trackerEntry.numLeeches, endpoint.scrape_incomplete); firstTrackerMessage = trackerMessage;
trackerEntry.numDownloaded = std::max(trackerEntry.numDownloaded, endpoint.scrape_downloaded); if (firstErrorMessage.isEmpty())
firstErrorMessage = errorMessage;
} }
#endif #endif
if (numEndpoints > 0) if (numEndpoints > 0)
{ {
if (numUpdating > 0) if (numUpdating > 0)
{
trackerEntry.status = TrackerEntry::Updating; trackerEntry.status = TrackerEntry::Updating;
}
else if (numWorking > 0) else if (numWorking > 0)
{
trackerEntry.status = TrackerEntry::Working; trackerEntry.status = TrackerEntry::Working;
trackerEntry.message = firstTrackerMessage;
}
else if (numNotWorking == numEndpoints) else if (numNotWorking == numEndpoints)
{
trackerEntry.status = TrackerEntry::NotWorking; trackerEntry.status = TrackerEntry::NotWorking;
trackerEntry.message = (!firstTrackerMessage.isEmpty() ? firstTrackerMessage : firstErrorMessage);
}
} }
return trackerEntry; return trackerEntry;
@ -440,20 +476,18 @@ QVector<TrackerEntry> TorrentImpl::trackers() const
entries.reserve(nativeTrackers.size()); entries.reserve(nativeTrackers.size());
for (const lt::announce_entry &tracker : nativeTrackers) for (const lt::announce_entry &tracker : nativeTrackers)
{
const QString trackerURL = QString::fromStdString(tracker.url);
#if (LIBTORRENT_VERSION_NUM >= 20000) #if (LIBTORRENT_VERSION_NUM >= 20000)
entries << fromNativeAnnouncerEntry(tracker, m_nativeHandle.info_hashes()); entries << fromNativeAnnouncerEntry(tracker, m_nativeHandle.info_hashes(), m_trackerPeerCounts[trackerURL]);
#else #else
entries << fromNativeAnnouncerEntry(tracker); entries << fromNativeAnnouncerEntry(tracker, m_trackerPeerCounts[trackerURL]);
#endif #endif
}
return entries; return entries;
} }
QHash<QString, TrackerInfo> TorrentImpl::trackerInfos() const
{
return m_trackerInfos;
}
void TorrentImpl::addTrackers(const QVector<TrackerEntry> &trackers) void TorrentImpl::addTrackers(const QVector<TrackerEntry> &trackers)
{ {
QSet<TrackerEntry> currentTrackers; QSet<TrackerEntry> currentTrackers;
@ -1623,10 +1657,8 @@ void TorrentImpl::handleMoveStorageJobFinished(const bool hasOutstandingJob)
void TorrentImpl::handleTrackerReplyAlert(const lt::tracker_reply_alert *p) void TorrentImpl::handleTrackerReplyAlert(const lt::tracker_reply_alert *p)
{ {
const QString trackerUrl(p->tracker_url()); const QString trackerUrl = p->tracker_url();
qDebug("Received a tracker reply from %s (Num_peers = %d)", qUtf8Printable(trackerUrl), p->num_peers); m_trackerPeerCounts[trackerUrl][p->local_endpoint] = p->num_peers;
// Connection was successful now. Remove possible old errors
m_trackerInfos[trackerUrl] = {{}, p->num_peers};
m_session->handleTorrentTrackerReply(this, trackerUrl); m_session->handleTorrentTrackerReply(this, trackerUrl);
} }
@ -1634,20 +1666,12 @@ void TorrentImpl::handleTrackerReplyAlert(const lt::tracker_reply_alert *p)
void TorrentImpl::handleTrackerWarningAlert(const lt::tracker_warning_alert *p) void TorrentImpl::handleTrackerWarningAlert(const lt::tracker_warning_alert *p)
{ {
const QString trackerUrl = p->tracker_url(); const QString trackerUrl = p->tracker_url();
const QString message = p->warning_message();
// Connection was successful now but there is a warning message
m_trackerInfos[trackerUrl].lastMessage = message; // Store warning message
m_session->handleTorrentTrackerWarning(this, trackerUrl); m_session->handleTorrentTrackerWarning(this, trackerUrl);
} }
void TorrentImpl::handleTrackerErrorAlert(const lt::tracker_error_alert *p) void TorrentImpl::handleTrackerErrorAlert(const lt::tracker_error_alert *p)
{ {
const QString trackerUrl = p->tracker_url(); const QString trackerUrl = p->tracker_url();
const QString message = p->error_message();
m_trackerInfos[trackerUrl].lastMessage = message;
// Starting with libtorrent 1.2.x each tracker has multiple local endpoints from which // Starting with libtorrent 1.2.x each tracker has multiple local endpoints from which
// an announce is attempted. Some endpoints might succeed while others might fail. // an announce is attempted. Some endpoints might succeed while others might fail.

5
src/base/bittorrent/torrentimpl.h

@ -33,11 +33,13 @@
#include <libtorrent/add_torrent_params.hpp> #include <libtorrent/add_torrent_params.hpp>
#include <libtorrent/fwd.hpp> #include <libtorrent/fwd.hpp>
#include <libtorrent/socket.hpp>
#include <libtorrent/torrent_handle.hpp> #include <libtorrent/torrent_handle.hpp>
#include <libtorrent/torrent_status.hpp> #include <libtorrent/torrent_status.hpp>
#include <QDateTime> #include <QDateTime>
#include <QHash> #include <QHash>
#include <QMap>
#include <QObject> #include <QObject>
#include <QQueue> #include <QQueue>
#include <QSet> #include <QSet>
@ -154,7 +156,6 @@ namespace BitTorrent
bool hasFilteredPieces() const override; bool hasFilteredPieces() const override;
int queuePosition() const override; int queuePosition() const override;
QVector<TrackerEntry> trackers() const override; QVector<TrackerEntry> trackers() const override;
QHash<QString, TrackerInfo> trackerInfos() const override;
QVector<QUrl> urlSeeds() const override; QVector<QUrl> urlSeeds() const override;
QString error() const override; QString error() const override;
qlonglong totalDownload() const override; qlonglong totalDownload() const override;
@ -308,7 +309,7 @@ namespace BitTorrent
// we will rely on this workaround to remove empty leftover folders // we will rely on this workaround to remove empty leftover folders
QHash<lt::file_index_t, QVector<QString>> m_oldPath; QHash<lt::file_index_t, QVector<QString>> m_oldPath;
QHash<QString, TrackerInfo> m_trackerInfos; QHash<QString, QMap<lt::tcp::endpoint, int>> m_trackerPeerCounts;
// Persistent data // Persistent data
QString m_name; QString m_name;

4
src/base/bittorrent/trackerentry.h

@ -49,9 +49,11 @@ namespace BitTorrent
int protocolVersion = 1; int protocolVersion = 1;
Status status = NotContacted; Status status = NotContacted;
int numPeers = -1;
int numSeeds = -1; int numSeeds = -1;
int numLeeches = -1; int numLeeches = -1;
int numDownloaded = -1; int numDownloaded = -1;
QString message;
}; };
QString url; QString url;
@ -61,9 +63,11 @@ namespace BitTorrent
// Deprecated fields // Deprecated fields
Status status = NotContacted; Status status = NotContacted;
int numPeers = -1;
int numSeeds = -1; int numSeeds = -1;
int numLeeches = -1; int numLeeches = -1;
int numDownloaded = -1; int numDownloaded = -1;
QString message;
}; };
bool operator==(const TrackerEntry &left, const TrackerEntry &right); bool operator==(const TrackerEntry &left, const TrackerEntry &right);

13
src/gui/properties/trackerlistwidget.cpp

@ -33,7 +33,6 @@
#include <QClipboard> #include <QClipboard>
#include <QColor> #include <QColor>
#include <QDebug> #include <QDebug>
#include <QHash>
#include <QHeaderView> #include <QHeaderView>
#include <QMenu> #include <QMenu>
#include <QMessageBox> #include <QMessageBox>
@ -363,7 +362,6 @@ void TrackerListWidget::loadTrackers()
loadStickyItems(torrent); loadStickyItems(torrent);
// Load actual trackers information // Load actual trackers information
const QHash<QString, BitTorrent::TrackerInfo> trackerData = torrent->trackerInfos();
QStringList oldTrackerURLs = m_trackerItems.keys(); QStringList oldTrackerURLs = m_trackerItems.keys();
for (const BitTorrent::TrackerEntry &entry : asConst(torrent->trackers())) for (const BitTorrent::TrackerEntry &entry : asConst(torrent->trackers()))
@ -385,29 +383,26 @@ void TrackerListWidget::loadTrackers()
item->setText(COL_TIER, QString::number(entry.tier)); item->setText(COL_TIER, QString::number(entry.tier));
const BitTorrent::TrackerInfo data = trackerData.value(trackerURL);
switch (entry.status) switch (entry.status)
{ {
case BitTorrent::TrackerEntry::Working: case BitTorrent::TrackerEntry::Working:
item->setText(COL_STATUS, tr("Working")); item->setText(COL_STATUS, tr("Working"));
item->setText(COL_MSG, "");
break; break;
case BitTorrent::TrackerEntry::Updating: case BitTorrent::TrackerEntry::Updating:
item->setText(COL_STATUS, tr("Updating...")); item->setText(COL_STATUS, tr("Updating..."));
item->setText(COL_MSG, "");
break; break;
case BitTorrent::TrackerEntry::NotWorking: case BitTorrent::TrackerEntry::NotWorking:
item->setText(COL_STATUS, tr("Not working")); item->setText(COL_STATUS, tr("Not working"));
item->setText(COL_MSG, data.lastMessage.trimmed());
break; break;
case BitTorrent::TrackerEntry::NotContacted: case BitTorrent::TrackerEntry::NotContacted:
item->setText(COL_STATUS, tr("Not contacted yet")); item->setText(COL_STATUS, tr("Not contacted yet"));
item->setText(COL_MSG, "");
break; break;
} }
item->setText(COL_PEERS, QString::number(data.numPeers)); item->setText(COL_MSG, entry.message);
item->setText(COL_PEERS, ((entry.numPeers > -1)
? QString::number(entry.numPeers)
: tr("N/A")));
item->setText(COL_SEEDS, ((entry.numSeeds > -1) item->setText(COL_SEEDS, ((entry.numSeeds > -1)
? QString::number(entry.numSeeds) ? QString::number(entry.numSeeds)
: tr("N/A"))); : tr("N/A")));

7
src/webui/api/torrentscontroller.cpp

@ -453,18 +453,15 @@ void TorrentsController::trackersAction()
QJsonArray trackerList = getStickyTrackers(torrent); QJsonArray trackerList = getStickyTrackers(torrent);
QHash<QString, BitTorrent::TrackerInfo> trackersData = torrent->trackerInfos();
for (const BitTorrent::TrackerEntry &tracker : asConst(torrent->trackers())) for (const BitTorrent::TrackerEntry &tracker : asConst(torrent->trackers()))
{ {
const BitTorrent::TrackerInfo data = trackersData.value(tracker.url);
trackerList << QJsonObject trackerList << QJsonObject
{ {
{KEY_TRACKER_URL, tracker.url}, {KEY_TRACKER_URL, tracker.url},
{KEY_TRACKER_TIER, tracker.tier}, {KEY_TRACKER_TIER, tracker.tier},
{KEY_TRACKER_STATUS, static_cast<int>(tracker.status)}, {KEY_TRACKER_STATUS, static_cast<int>(tracker.status)},
{KEY_TRACKER_PEERS_COUNT, data.numPeers}, {KEY_TRACKER_MSG, tracker.message},
{KEY_TRACKER_MSG, data.lastMessage.trimmed()}, {KEY_TRACKER_PEERS_COUNT, tracker.numPeers},
{KEY_TRACKER_SEEDS_COUNT, tracker.numSeeds}, {KEY_TRACKER_SEEDS_COUNT, tracker.numSeeds},
{KEY_TRACKER_LEECHES_COUNT, tracker.numLeeches}, {KEY_TRACKER_LEECHES_COUNT, tracker.numLeeches},
{KEY_TRACKER_DOWNLOADED_COUNT, tracker.numDownloaded} {KEY_TRACKER_DOWNLOADED_COUNT, tracker.numDownloaded}

Loading…
Cancel
Save