From f7c196dbcf660de04b3cb89529a94435e43cace2 Mon Sep 17 00:00:00 2001 From: Christophe Dumez Date: Sat, 14 Nov 2009 13:33:55 +0000 Subject: [PATCH] - Implemented asynchronous hostname resolution in Peer list --- src/peerlistwidget.cpp | 21 +++++- src/peerlistwidget.h | 17 +++-- src/reverseresolution.h | 138 ++++++++++++++++++++++++++++++++++++++++ src/src.pro | 3 +- 4 files changed, 169 insertions(+), 10 deletions(-) create mode 100644 src/reverseresolution.h diff --git a/src/peerlistwidget.cpp b/src/peerlistwidget.cpp index 6e2d52372..aea0ae8c2 100644 --- a/src/peerlistwidget.cpp +++ b/src/peerlistwidget.cpp @@ -30,7 +30,7 @@ #include "peerlistwidget.h" #include "peerlistdelegate.h" -#include "misc.h" +#include "reverseresolution.h" #include #include #include @@ -60,12 +60,17 @@ PeerListWidget::PeerListWidget() { setItemDelegate(listDelegate); // Enable sorting setSortingEnabled(true); + // IP to Hostname resolver + resolver = new ReverseResolution(this); + connect(resolver, SIGNAL(ip_resolved(QString,QString)), this, SLOT(handleResolved(QString,QString))); + resolver->start(); } PeerListWidget::~PeerListWidget() { delete proxyModel; delete listModel; delete listDelegate; + delete resolver; } void PeerListWidget::loadPeers(QTorrentHandle &h) { @@ -98,19 +103,19 @@ QStandardItem* PeerListWidget::addPeer(QString ip, peer_info peer) { // Adding Peer to peer list listModel->insertRow(row); listModel->setData(listModel->index(row, IP), ip); + resolver->resolve(peer.ip); listModel->setData(listModel->index(row, CLIENT), misc::toQString(peer.client)); listModel->setData(listModel->index(row, PROGRESS), peer.progress); listModel->setData(listModel->index(row, DOWN_SPEED), peer.payload_down_speed); listModel->setData(listModel->index(row, UP_SPEED), peer.payload_up_speed); listModel->setData(listModel->index(row, TOT_DOWN), peer.total_download); listModel->setData(listModel->index(row, TOT_UP), peer.total_upload); - return listModel->item(row, 0); + return listModel->item(row, IP); } void PeerListWidget::updatePeer(QString ip, peer_info peer) { QStandardItem *item = peerItems.value(ip); int row = item->row(); - listModel->setData(listModel->index(row, IP), ip); listModel->setData(listModel->index(row, CLIENT), misc::toQString(peer.client)); listModel->setData(listModel->index(row, PROGRESS), peer.progress); listModel->setData(listModel->index(row, DOWN_SPEED), peer.payload_down_speed); @@ -118,3 +123,13 @@ void PeerListWidget::updatePeer(QString ip, peer_info peer) { listModel->setData(listModel->index(row, TOT_DOWN), peer.total_download); listModel->setData(listModel->index(row, TOT_UP), peer.total_upload); } + +void PeerListWidget::handleResolved(QString ip, QString hostname) { + qDebug("%s was resolved to %s", ip.toLocal8Bit().data(), hostname.toLocal8Bit().data()); + QStandardItem *item = peerItems.value(ip, 0); + if(item) { + qDebug("item was updated"); + //item->setData(hostname); + listModel->setData(listModel->indexFromItem(item), hostname); + } +} diff --git a/src/peerlistwidget.h b/src/peerlistwidget.h index 51d9ff03f..c6f3732da 100644 --- a/src/peerlistwidget.h +++ b/src/peerlistwidget.h @@ -34,28 +34,33 @@ #include #include #include "qtorrenthandle.h" +#include "misc.h" class QStandardItemModel; class QStandardItem; class QSortFilterProxyModel; class PeerListDelegate; +class ReverseResolution; class PeerListWidget : public QTreeView { + Q_OBJECT private: QStandardItemModel *listModel; PeerListDelegate *listDelegate; QSortFilterProxyModel * proxyModel; QHash peerItems; + ReverseResolution *resolver; public: - PeerListWidget(); - ~PeerListWidget(); + PeerListWidget(); + ~PeerListWidget(); - public slots: - void loadPeers(QTorrentHandle &h); - QStandardItem* addPeer(QString ip, peer_info peer); - void updatePeer(QString ip, peer_info peer); +public slots: + void loadPeers(QTorrentHandle &h); + QStandardItem* addPeer(QString ip, peer_info peer); + void updatePeer(QString ip, peer_info peer); + void handleResolved(QString ip, QString hostname); }; #endif // PEERLISTWIDGET_H diff --git a/src/reverseresolution.h b/src/reverseresolution.h new file mode 100644 index 000000000..92ff999ac --- /dev/null +++ b/src/reverseresolution.h @@ -0,0 +1,138 @@ +/* + * Bittorrent Client using Qt4 and libtorrent. + * Copyright (C) 2006 Christophe Dumez + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * Contact : chris@qbittorrent.org + */ + +#ifndef REVERSERESOLUTION_H +#define REVERSERESOLUTION_H + +#include +#include +#include +#include +#include +#include +#include "misc.h" + +#define MAX_THREADS 20 + +class ReverseResolutionST: public QThread { + Q_OBJECT + +private: + boost::asio::ip::tcp::endpoint ip; + boost::asio::ip::tcp::resolver resolver; + +public: + ReverseResolutionST(boost::asio::io_service &ios, QObject *parent=0): QThread(parent), resolver(ios) { + + } + + ~ReverseResolutionST() { + wait(); + } + + void setIP(boost::asio::ip::tcp::endpoint &_ip) { + ip = _ip; + } + +signals: + void ip_resolved(QString ip, QString hostname); + +protected: + void run() { + boost::asio::ip::tcp::resolver::iterator it = resolver.resolve(ip); + qDebug("IP was resolved"); + boost::asio::ip::tcp::endpoint endpoint = *it; + emit ip_resolved(misc::toQString(endpoint.address().to_string()), misc::toQString((*it).host_name())); + } +}; + +class ReverseResolution: public QThread { + Q_OBJECT + +private: + QQueue ips; + QMutex mut; + QWaitCondition cond; + bool stopped; + boost::asio::io_service ios; + QList subThreads; + + +public: + ReverseResolution(QObject* parent): QThread(parent), stopped(false) { + } + + ~ReverseResolution() { + stopped = true; + cond.wakeOne(); + qDeleteAll(subThreads); + wait(); + } + + void resolve(boost::asio::ip::tcp::endpoint ip) { + mut.lock(); + ips.enqueue(ip); + if(subThreads.size() < MAX_THREADS) + cond.wakeOne(); + mut.unlock(); + } + +signals: + void ip_resolved(QString ip, QString hostname); + +protected slots: + void forwardSignal(QString ip, QString hostname) { + emit ip_resolved(ip, hostname); + mut.lock(); + subThreads.removeOne(static_cast(sender())); + if(!ips.empty()) + cond.wakeOne(); + mut.unlock(); + sender()->deleteLater(); + } + +protected: + void run() { + do { + mut.lock(); + cond.wait(&mut); + if(stopped) return; + boost::asio::ip::tcp::endpoint ip = ips.dequeue(); + ReverseResolutionST *st = new ReverseResolutionST(ios); + subThreads.append(st); + mut.unlock(); + connect(st, SIGNAL(ip_resolved(QString,QString)), this, SLOT(forwardSignal(QString,QString))); + st->setIP(ip); + st->start(); + }while(!stopped); + } +}; + +#endif // REVERSERESOLUTION_H diff --git a/src/src.pro b/src/src.pro index 94e31f7e0..b46d0e37b 100644 --- a/src/src.pro +++ b/src/src.pro @@ -187,7 +187,8 @@ HEADERS += GUI.h \ TorrentFilesModel.h \ filesystemwatcher.h \ peerlistwidget.h \ - peerlistdelegate.h + peerlistdelegate.h \ + reverseresolution.h FORMS += MainWindow.ui \ options.ui \ about.ui \