From 5f415c292ddc2ea13015a2bec42f9f6b710ed732 Mon Sep 17 00:00:00 2001 From: thalieht Date: Tue, 28 Jan 2020 21:32:15 +0200 Subject: [PATCH] Show any multiple connections from the same IP in peer list The uniqueness of peers is now determined by their IP, port and connection type (uTP etc.) instead of just their IP --- src/base/bittorrent/peeraddress.cpp | 10 +++++ src/base/bittorrent/peeraddress.h | 3 ++ src/gui/properties/peerlistwidget.cpp | 61 ++++++++++++++++++--------- src/gui/properties/peerlistwidget.h | 6 ++- 4 files changed, 59 insertions(+), 21 deletions(-) diff --git a/src/base/bittorrent/peeraddress.cpp b/src/base/bittorrent/peeraddress.cpp index b7dd5c754..a9a70f0bf 100644 --- a/src/base/bittorrent/peeraddress.cpp +++ b/src/base/bittorrent/peeraddress.cpp @@ -68,3 +68,13 @@ QString PeerAddress::toString() const : ip.toString(); return (ipStr + ':' + QString::number(port)); } + +bool BitTorrent::operator==(const BitTorrent::PeerAddress &left, const BitTorrent::PeerAddress &right) +{ + return (left.ip == right.ip) && (left.port == right.port); +} + +uint BitTorrent::qHash(const BitTorrent::PeerAddress &addr, const uint seed) +{ + return (::qHash(addr.ip, seed) ^ ::qHash(addr.port)); +} diff --git a/src/base/bittorrent/peeraddress.h b/src/base/bittorrent/peeraddress.h index 4233a6e1f..142cf048f 100644 --- a/src/base/bittorrent/peeraddress.h +++ b/src/base/bittorrent/peeraddress.h @@ -42,4 +42,7 @@ namespace BitTorrent static PeerAddress parse(const QString &address); QString toString() const; }; + + bool operator==(const PeerAddress &left, const PeerAddress &right); + uint qHash(const PeerAddress &addr, uint seed); } diff --git a/src/gui/properties/peerlistwidget.cpp b/src/gui/properties/peerlistwidget.cpp index 960a6f656..fbb70638c 100644 --- a/src/gui/properties/peerlistwidget.cpp +++ b/src/gui/properties/peerlistwidget.cpp @@ -57,6 +57,22 @@ #include "propertieswidget.h" #include "uithememanager.h" +struct PeerEndpoint +{ + BitTorrent::PeerAddress address; + QString connectionType; // matches return type of `PeerInfo::connectionType()` +}; + +bool operator==(const PeerEndpoint &left, const PeerEndpoint &right) +{ + return (left.address == right.address) && (left.connectionType == right.connectionType); +} + +uint qHash(const PeerEndpoint &peerEndpoint, const uint seed) +{ + return (qHash(peerEndpoint.address, seed) ^ ::qHash(peerEndpoint.connectionType)); +} + PeerListWidget::PeerListWidget(PropertiesWidget *parent) : QTreeView(parent) , m_properties(parent) @@ -331,42 +347,45 @@ void PeerListWidget::loadPeers(const BitTorrent::TorrentHandle *torrent) if (!torrent) return; const QVector peers = torrent->peers(); - QSet existingPeers; + QSet existingPeers; for (auto i = m_peerItems.cbegin(); i != m_peerItems.cend(); ++i) existingPeers << i.key(); for (const BitTorrent::PeerInfo &peer : peers) { - const BitTorrent::PeerAddress addr = peer.address(); - if (addr.ip.isNull()) continue; + if (peer.address().ip.isNull()) continue; - const QString peerIp = addr.ip.toString(); bool isNewPeer = false; - updatePeer(peerIp, torrent, peer, isNewPeer); - if (!isNewPeer) - existingPeers.remove(peerIp); + updatePeer(torrent, peer, isNewPeer); + if (!isNewPeer) { + const PeerEndpoint peerEndpoint {peer.address(), peer.connectionType()}; + existingPeers.remove(peerEndpoint); + } } // Remove peers that are gone - for (const QString &ip : asConst(existingPeers)) { - const QStandardItem *item = m_peerItems.take(ip); + for (const PeerEndpoint &peerEndpoint : asConst(existingPeers)) { + const QStandardItem *item = m_peerItems.take(peerEndpoint); m_listModel->removeRow(item->row()); } } -void PeerListWidget::updatePeer(const QString &ip, const BitTorrent::TorrentHandle *torrent, const BitTorrent::PeerInfo &peer, bool &isNewPeer) +void PeerListWidget::updatePeer(const BitTorrent::TorrentHandle *torrent, const BitTorrent::PeerInfo &peer, bool &isNewPeer) { - auto itemIter = m_peerItems.find(ip); + const PeerEndpoint peerEndpoint {peer.address(), peer.connectionType()}; + const QString peerIp = peerEndpoint.address.ip.toString(); + + auto itemIter = m_peerItems.find(peerEndpoint); isNewPeer = (itemIter == m_peerItems.end()); if (isNewPeer) { // new item const int row = m_listModel->rowCount(); m_listModel->insertRow(row); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), ip); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), ip, Qt::ToolTipRole); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), peerIp); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP), peerIp, Qt::ToolTipRole); m_listModel->setData(m_listModel->index(row, PeerListDelegate::PORT), peer.address().port); - m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP_HIDDEN), ip); + m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP_HIDDEN), peerIp); - itemIter = m_peerItems.insert(ip, m_listModel->item(row, PeerListDelegate::IP)); + itemIter = m_peerItems.insert(peerEndpoint, m_listModel->item(row, PeerListDelegate::IP)); } const int row = (*itemIter)->row(); @@ -386,7 +405,7 @@ void PeerListWidget::updatePeer(const QString &ip, const BitTorrent::TorrentHand m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWNLOADING_PIECE), downloadingFiles.join('\n'), Qt::ToolTipRole); if (m_resolver) - m_resolver->resolve(ip); + m_resolver->resolve(peerIp); if (m_resolveCountries) { const QIcon icon = UIThemeManager::instance()->getFlagIcon(peer.country()); @@ -400,9 +419,13 @@ void PeerListWidget::updatePeer(const QString &ip, const BitTorrent::TorrentHand void PeerListWidget::handleResolved(const QString &ip, const QString &hostname) { - QStandardItem *item = m_peerItems.value(ip, nullptr); - if (item) - item->setData(hostname, Qt::DisplayRole); + for (auto iter = m_peerItems.cbegin(); iter != m_peerItems.cend(); ++iter) { + if (iter.key().address.ip.toString() == ip) { + QStandardItem *item {iter.value()}; + item->setData(hostname, Qt::DisplayRole); + break; + } + } } void PeerListWidget::handleSortColumnChanged(const int col) diff --git a/src/gui/properties/peerlistwidget.h b/src/gui/properties/peerlistwidget.h index d8c6dbdb9..314938c75 100644 --- a/src/gui/properties/peerlistwidget.h +++ b/src/gui/properties/peerlistwidget.h @@ -38,6 +38,8 @@ class QStandardItemModel; class PeerListSortModel; class PropertiesWidget; +struct PeerEndpoint; + namespace BitTorrent { class TorrentHandle; @@ -73,7 +75,7 @@ private slots: void handleResolved(const QString &ip, const QString &hostname); private: - void updatePeer(const QString &ip, const BitTorrent::TorrentHandle *torrent, const BitTorrent::PeerInfo &peer, bool &isNewPeer); + void updatePeer(const BitTorrent::TorrentHandle *torrent, const BitTorrent::PeerInfo &peer, bool &isNewPeer); void wheelEvent(QWheelEvent *event) override; @@ -81,7 +83,7 @@ private: PeerListSortModel *m_proxyModel = nullptr; PropertiesWidget *m_properties = nullptr; Net::ReverseResolution *m_resolver = nullptr; - QHash m_peerItems; + QHash m_peerItems; bool m_resolveCountries; };