Merge pull request #11918 from thalieht/peerssameip

Show any multiple connections from the same IP in peer list
This commit is contained in:
Mike Tzou 2020-01-30 12:59:17 +08:00 committed by GitHub
commit 11bea8d393
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 21 deletions

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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<BitTorrent::PeerInfo> peers = torrent->peers();
QSet<QString> existingPeers;
QSet<PeerEndpoint> 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)

View File

@ -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<QString, QStandardItem *> m_peerItems;
QHash<PeerEndpoint, QStandardItem *> m_peerItems;
bool m_resolveCountries;
};