mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-12-21 08:09:35 +08:00
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
This commit is contained in:
parent
c3ce1aaa3d
commit
5f415c292d
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user