diff --git a/src/base/net/reverseresolution.cpp b/src/base/net/reverseresolution.cpp index 89ebf1c6f..4d63923b0 100644 --- a/src/base/net/reverseresolution.cpp +++ b/src/base/net/reverseresolution.cpp @@ -28,19 +28,19 @@ #include "reverseresolution.h" -#include +#include #include #include -const int CACHE_SIZE = 500; +const int CACHE_SIZE = 2048; using namespace Net; namespace { - bool isUsefulHostName(const QString &hostname, const QString &ip) + bool isUsefulHostName(const QString &hostname, const QHostAddress &ip) { - return (!hostname.isEmpty() && (hostname != ip)); + return (!hostname.isEmpty() && (hostname != ip.toString())); } } @@ -52,37 +52,36 @@ ReverseResolution::ReverseResolution(QObject *parent) ReverseResolution::~ReverseResolution() { - qDebug("Deleting host name resolver..."); + // abort on-going lookups instead of waiting them + for (auto iter = m_lookups.cbegin(); iter != m_lookups.cend(); ++iter) + QHostInfo::abortHostLookup(iter.key()); } -void ReverseResolution::resolve(const QString &ip) +void ReverseResolution::resolve(const QHostAddress &ip) { - if (m_cache.contains(ip)) { - const QString &hostname = *m_cache.object(ip); - qDebug() << "Resolved host name using cache: " << ip << " -> " << hostname; - if (isUsefulHostName(hostname, ip)) - emit ipResolved(ip, hostname); - } - else { - // Actually resolve the ip - m_lookups.insert(QHostInfo::lookupHost(ip, this, &ReverseResolution::hostResolved), ip); + const QString *hostname = m_cache.object(ip); + if (hostname) { + emit ipResolved(ip, *hostname); + return; } + + // do reverse lookup: IP -> hostname + const int lookupId = QHostInfo::lookupHost(ip.toString(), this, &ReverseResolution::hostResolved); + m_lookups.insert(lookupId, ip); } void ReverseResolution::hostResolved(const QHostInfo &host) { - const QString ip = m_lookups.take(host.lookupId()); - Q_ASSERT(!ip.isNull()); + const QHostAddress ip = m_lookups.take(host.lookupId()); if (host.error() != QHostInfo::NoError) { - qDebug() << "DNS Reverse resolution error: " << host.errorString(); + emit ipResolved(ip, {}); return; } - const QString hostname = host.hostName(); - - qDebug() << Q_FUNC_INFO << ip << QString("->") << hostname; + const QString hostname = isUsefulHostName(host.hostName(), ip) + ? host.hostName() + : QString(); m_cache.insert(ip, new QString(hostname)); - if (isUsefulHostName(hostname, ip)) - emit ipResolved(ip, hostname); + emit ipResolved(ip, hostname); } diff --git a/src/base/net/reverseresolution.h b/src/base/net/reverseresolution.h index 30ffbe14b..875cc2b56 100644 --- a/src/base/net/reverseresolution.h +++ b/src/base/net/reverseresolution.h @@ -32,6 +32,7 @@ #include #include +class QHostAddress; class QHostInfo; class QString; @@ -46,17 +47,17 @@ namespace Net explicit ReverseResolution(QObject *parent = nullptr); ~ReverseResolution(); - void resolve(const QString &ip); + void resolve(const QHostAddress &ip); signals: - void ipResolved(const QString &ip, const QString &hostname); + void ipResolved(const QHostAddress &ip, const QString &hostname); private slots: void hostResolved(const QHostInfo &host); private: - QHash m_lookups; - QCache m_cache; + QHash m_lookups; // + QCache m_cache; // }; } diff --git a/src/gui/properties/peerlistwidget.cpp b/src/gui/properties/peerlistwidget.cpp index fbb70638c..4b3107d66 100644 --- a/src/gui/properties/peerlistwidget.cpp +++ b/src/gui/properties/peerlistwidget.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -327,6 +328,7 @@ void PeerListWidget::copySelectedPeers() void PeerListWidget::clear() { m_peerItems.clear(); + m_itemsByIP.clear(); const int nbrows = m_listModel->rowCount(); if (nbrows > 0) m_listModel->removeRows(0, nbrows); @@ -364,7 +366,13 @@ void PeerListWidget::loadPeers(const BitTorrent::TorrentHandle *torrent) // Remove peers that are gone for (const PeerEndpoint &peerEndpoint : asConst(existingPeers)) { - const QStandardItem *item = m_peerItems.take(peerEndpoint); + QStandardItem *item = m_peerItems.take(peerEndpoint); + + QSet &items = m_itemsByIP[peerEndpoint.address.ip]; + items.remove(item); + if (items.isEmpty()) + m_itemsByIP.remove(peerEndpoint.address.ip); + m_listModel->removeRow(item->row()); } } @@ -386,6 +394,7 @@ void PeerListWidget::updatePeer(const BitTorrent::TorrentHandle *torrent, const m_listModel->setData(m_listModel->index(row, PeerListDelegate::IP_HIDDEN), peerIp); itemIter = m_peerItems.insert(peerEndpoint, m_listModel->item(row, PeerListDelegate::IP)); + m_itemsByIP[peerEndpoint.address.ip].insert(itemIter.value()); } const int row = (*itemIter)->row(); @@ -405,7 +414,7 @@ void PeerListWidget::updatePeer(const BitTorrent::TorrentHandle *torrent, const m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWNLOADING_PIECE), downloadingFiles.join('\n'), Qt::ToolTipRole); if (m_resolver) - m_resolver->resolve(peerIp); + m_resolver->resolve(peerEndpoint.address.ip); if (m_resolveCountries) { const QIcon icon = UIThemeManager::instance()->getFlagIcon(peer.country()); @@ -417,15 +426,14 @@ void PeerListWidget::updatePeer(const BitTorrent::TorrentHandle *torrent, const } } -void PeerListWidget::handleResolved(const QString &ip, const QString &hostname) +void PeerListWidget::handleResolved(const QHostAddress &ip, const QString &hostname) const { - 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; - } - } + if (hostname.isEmpty()) + return; + + const QSet items = m_itemsByIP.value(ip); + for (QStandardItem *item : items) + item->setData(hostname, Qt::DisplayRole); } void PeerListWidget::handleSortColumnChanged(const int col) diff --git a/src/gui/properties/peerlistwidget.h b/src/gui/properties/peerlistwidget.h index 314938c75..ca05acc82 100644 --- a/src/gui/properties/peerlistwidget.h +++ b/src/gui/properties/peerlistwidget.h @@ -30,8 +30,10 @@ #define PEERLISTWIDGET_H #include +#include #include +class QHostAddress; class QStandardItem; class QStandardItemModel; @@ -72,7 +74,7 @@ private slots: void banSelectedPeers(); void copySelectedPeers(); void handleSortColumnChanged(int col); - void handleResolved(const QString &ip, const QString &hostname); + void handleResolved(const QHostAddress &ip, const QString &hostname) const; private: void updatePeer(const BitTorrent::TorrentHandle *torrent, const BitTorrent::PeerInfo &peer, bool &isNewPeer); @@ -84,6 +86,7 @@ private: PropertiesWidget *m_properties = nullptr; Net::ReverseResolution *m_resolver = nullptr; QHash m_peerItems; + QHash> m_itemsByIP; // must be kept in sync with `m_peerItems` bool m_resolveCountries; };