From 50f090884ccd29e439720aeb83fcd293fae34921 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 19 Jun 2015 13:24:34 +0200 Subject: [PATCH 01/20] [Qt] add ban functions to peers window add ban option for peer context menu (1h, 24h, 7d, 1y). --- src/qt/rpcconsole.cpp | 40 +++++++++++++++++++++++++++++++++++++++- src/qt/rpcconsole.h | 2 ++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index ec18ea8f7..2a94312be 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -352,16 +352,37 @@ void RPCConsole::setClientModel(ClientModel *model) ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH); // create context menu actions - QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this); + QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this); + QAction* banAction1h = new QAction(tr("&Ban Node for 1 hour"), this); + QAction* banAction24h = new QAction(tr("&Ban Node for 24 hours"), this); + QAction* banAction7d = new QAction(tr("&Ban Node for 7 days"), this); + QAction* banAction365d = new QAction(tr("&Ban Node for 1 year"), this); // create context menu contextMenu = new QMenu(); contextMenu->addAction(disconnectAction); + contextMenu->addAction(banAction1h); + contextMenu->addAction(banAction24h); + contextMenu->addAction(banAction7d); + contextMenu->addAction(banAction365d); // context menu signals connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showMenu(const QPoint&))); connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode())); + //add a signal mapping, use int instead of int64_t for bantime because signalmapper only supports int or objects + //int is sufficient for our case + QSignalMapper* signalMapper = new QSignalMapper(this); + signalMapper->setMapping(banAction1h, 60*60); + signalMapper->setMapping(banAction24h, 60*60*24); + signalMapper->setMapping(banAction7d, 60*60*24*7); + signalMapper->setMapping(banAction365d, 60*60*24*365); + connect(banAction1h, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(banAction24h, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(banAction7d, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(banAction365d, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(banSelectedNode(int))) ; + // connect the peerWidget selection model to our peerSelected() handler connect(ui->peerWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &))); @@ -731,6 +752,23 @@ void RPCConsole::disconnectSelectedNode() } } +void RPCConsole::banSelectedNode(int bantime) +{ + // Get currently selected peer address + QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address); + // Find possible nodes, ban it and clear the selected node + if (CNode *bannedNode = FindNode(strNode.toStdString())) { + std::string nStr = strNode.toStdString(); + std::string addr; + int port = 0; + SplitHostPort(nStr, port, addr); + + CNode::Ban(CNetAddr(addr), bantime); + bannedNode->CloseSocketDisconnect(); + clearSelectedNode(); + } +} + void RPCConsole::clearSelectedNode() { ui->peerWidget->selectionModel()->clearSelection(); diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 1409fca52..3218a635d 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -80,6 +80,8 @@ public Q_SLOTS: void peerLayoutChanged(); /** Disconnect a selected node on the Peers tab */ void disconnectSelectedNode(); + /** Ban a selected node on the Peers tab */ + void banSelectedNode(int bantime); Q_SIGNALS: // For RPC command executor From ad204df1a9077327ab1142fbc9bf41369c1a73d1 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 20 Jun 2015 20:27:03 +0200 Subject: [PATCH 02/20] [Qt] add banlist table below peers table --- src/Makefile.qt.include | 3 + src/qt/bantablemodel.cpp | 192 +++++++++++++++++++++++++++++++++++++ src/qt/bantablemodel.h | 66 +++++++++++++ src/qt/clientmodel.cpp | 13 +++ src/qt/clientmodel.h | 4 + src/qt/forms/rpcconsole.ui | 94 ++++++++++++++++-- src/qt/rpcconsole.cpp | 13 +++ 7 files changed, 375 insertions(+), 10 deletions(-) create mode 100644 src/qt/bantablemodel.cpp create mode 100644 src/qt/bantablemodel.h diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 3e8eda178..480bd9dc8 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -97,6 +97,7 @@ QT_MOC_CPP = \ qt/moc_addressbookpage.cpp \ qt/moc_addresstablemodel.cpp \ qt/moc_askpassphrasedialog.cpp \ + qt/moc_bantablemodel.cpp \ qt/moc_bitcoinaddressvalidator.cpp \ qt/moc_bitcoinamountfield.cpp \ qt/moc_bitcoingui.cpp \ @@ -162,6 +163,7 @@ BITCOIN_QT_H = \ qt/addressbookpage.h \ qt/addresstablemodel.h \ qt/askpassphrasedialog.h \ + qt/bantablemodel.h \ qt/bitcoinaddressvalidator.h \ qt/bitcoinamountfield.h \ qt/bitcoingui.h \ @@ -260,6 +262,7 @@ RES_ICONS = \ qt/res/icons/verify.png BITCOIN_QT_CPP = \ + qt/bantablemodel.cpp \ qt/bitcoinaddressvalidator.cpp \ qt/bitcoinamountfield.cpp \ qt/bitcoingui.cpp \ diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp new file mode 100644 index 000000000..3b71769ef --- /dev/null +++ b/src/qt/bantablemodel.cpp @@ -0,0 +1,192 @@ +// Copyright (c) 2011-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "bantablemodel.h" + +#include "clientmodel.h" +#include "guiconstants.h" +#include "guiutil.h" + +#include "net.h" +#include "sync.h" +#include "utiltime.h" + +#include +#include +#include + +#include +#include + +// private implementation +class BanTablePriv +{ +public: + /** Local cache of peer information */ + QList cachedBanlist; + /** Column to sort nodes by */ + int sortColumn; + /** Order (ascending or descending) to sort nodes by */ + Qt::SortOrder sortOrder; + + /** Pull a full list of banned nodes from CNode into our cache */ + void refreshBanlist() + { + std::map banMap; + CNode::GetBanned(banMap); + + cachedBanlist.clear(); +#if QT_VERSION >= 0x040700 + cachedBanlist.reserve(banMap.size()); +#endif + std::map::iterator iter; + for (iter = banMap.begin(); iter != banMap.end(); ++iter) { + CCombinedBan banEntry; + banEntry.subnet = iter->first; + banEntry.bantil = iter->second; + cachedBanlist.append(banEntry); + } + } + + int size() + { + return cachedBanlist.size(); + } + + CCombinedBan *index(int idx) + { + if(idx >= 0 && idx < cachedBanlist.size()) { + return &cachedBanlist[idx]; + } else { + return 0; + } + } +}; + +BanTableModel::BanTableModel(ClientModel *parent) : + QAbstractTableModel(parent), + clientModel(parent), + timer(0) +{ + columns << tr("IP/Netmask") << tr("Banned Until"); + priv = new BanTablePriv(); + // default to unsorted + priv->sortColumn = -1; + + // set up timer for auto refresh + timer = new QTimer(); + connect(timer, SIGNAL(timeout()), SLOT(refresh())); + timer->setInterval(MODEL_UPDATE_DELAY); + + // load initial data + refresh(); +} + +void BanTableModel::startAutoRefresh() +{ + timer->start(); +} + +void BanTableModel::stopAutoRefresh() +{ + timer->stop(); +} + +int BanTableModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return priv->size(); +} + +int BanTableModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return columns.length();; +} + +QVariant BanTableModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + CCombinedBan *rec = static_cast(index.internalPointer()); + + if (role == Qt::DisplayRole) { + switch(index.column()) + { + case Address: + return QString::fromStdString(rec->subnet.ToString()); + case Bantime: + //show time in users local timezone, not 64bit compatible! + //TODO find a way to support 64bit timestamps + boost::posix_time::ptime pt1 = boost::posix_time::from_time_t(rec->bantil); + boost::posix_time::ptime pt2 = boost::date_time::c_local_adjustor::utc_to_local(pt1); + std::stringstream ss; + ss << pt2; + return QString::fromStdString(ss.str()); + } + } else if (role == Qt::TextAlignmentRole) { + if (index.column() == Bantime) + return (int)(Qt::AlignRight | Qt::AlignVCenter); + } + + return QVariant(); +} + +QVariant BanTableModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation == Qt::Horizontal) + { + if(role == Qt::DisplayRole && section < columns.size()) + { + return columns[section]; + } + } + return QVariant(); +} + +Qt::ItemFlags BanTableModel::flags(const QModelIndex &index) const +{ + if(!index.isValid()) + return 0; + + Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled; + return retval; +} + +QModelIndex BanTableModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + CCombinedBan *data = priv->index(row); + + if (data) + { + return createIndex(row, column, data); + } + else + { + return QModelIndex(); + } +} + +void BanTableModel::refresh() +{ + emit layoutAboutToBeChanged(); + priv->refreshBanlist(); + emit layoutChanged(); +} + +void BanTableModel::sort(int column, Qt::SortOrder order) +{ + priv->sortColumn = column; + priv->sortOrder = order; + refresh(); +} + +bool BanTableModel::shouldShow() +{ + if (priv->size() > 0) + return true; + return false; +} \ No newline at end of file diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h new file mode 100644 index 000000000..ef7a26e3c --- /dev/null +++ b/src/qt/bantablemodel.h @@ -0,0 +1,66 @@ +// Copyright (c) 2011-2013 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_BANTABLEMODEL_H +#define BITCOIN_QT_BANTABLEMODEL_H + +#include "main.h" +#include "net.h" + +#include +#include + +class ClientModel; +class BanTablePriv; + +QT_BEGIN_NAMESPACE +class QTimer; +QT_END_NAMESPACE + +struct CCombinedBan { + CSubNet subnet; + int64_t bantil; +}; + +/** + Qt model providing information about connected peers, similar to the + "getpeerinfo" RPC call. Used by the rpc console UI. + */ +class BanTableModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + explicit BanTableModel(ClientModel *parent = 0); + void startAutoRefresh(); + void stopAutoRefresh(); + + enum ColumnIndex { + Address = 0, + Bantime = 1, + }; + + /** @name Methods overridden from QAbstractTableModel + @{*/ + int rowCount(const QModelIndex &parent) const; + int columnCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QModelIndex index(int row, int column, const QModelIndex &parent) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + void sort(int column, Qt::SortOrder order); + bool shouldShow(); + /*@}*/ + +public slots: + void refresh(); + +private: + ClientModel *clientModel; + QStringList columns; + BanTablePriv *priv; + QTimer *timer; +}; + +#endif // BITCOIN_QT_BANTABLEMODEL_H diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 97d671156..62c35130f 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -4,6 +4,7 @@ #include "clientmodel.h" +#include "bantablemodel.h" #include "guiconstants.h" #include "peertablemodel.h" @@ -26,6 +27,7 @@ ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : QObject(parent), optionsModel(optionsModel), peerTableModel(0), + banTableModel(0), cachedNumBlocks(0), cachedBlockDate(QDateTime()), cachedReindexing(0), @@ -33,6 +35,7 @@ ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : pollTimer(0) { peerTableModel = new PeerTableModel(this); + banTableModel = new BanTableModel(this); pollTimer = new QTimer(this); connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer())); pollTimer->start(MODEL_UPDATE_DELAY); @@ -176,6 +179,11 @@ PeerTableModel *ClientModel::getPeerTableModel() return peerTableModel; } +BanTableModel *ClientModel::getBanTableModel() +{ + return banTableModel; +} + QString ClientModel::formatFullVersion() const { return QString::fromStdString(FormatFullVersion()); @@ -206,6 +214,11 @@ QString ClientModel::formatClientStartupTime() const return QDateTime::fromTime_t(nClientStartupTime).toString(); } +void ClientModel::updateBanlist() +{ + banTableModel->refresh(); +} + // Handlers for core signals static void ShowProgress(ClientModel *clientmodel, const std::string &title, int nProgress) { diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index ca2da3dde..627bdf862 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -9,6 +9,7 @@ #include class AddressTableModel; +class BanTableModel; class OptionsModel; class PeerTableModel; class TransactionTableModel; @@ -44,6 +45,7 @@ public: OptionsModel *getOptionsModel(); PeerTableModel *getPeerTableModel(); + BanTableModel *getBanTableModel(); //! Return number of connections, default is in- and outbound (total) int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const; @@ -72,6 +74,7 @@ public: private: OptionsModel *optionsModel; PeerTableModel *peerTableModel; + BanTableModel *banTableModel; int cachedNumBlocks; QDateTime cachedBlockDate; @@ -99,6 +102,7 @@ public Q_SLOTS: void updateTimer(); void updateNumConnections(int numConnections); void updateAlert(const QString &hash, int status); + void updateBanlist(); }; #endif // BITCOIN_QT_CLIENTMODEL_H diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index e8d9a958a..39230aee6 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -713,17 +713,91 @@ - - - Qt::ScrollBarAsNeeded + + + 0 - - true - - - false - - + + + + Qt::ScrollBarAsNeeded + + + true + + + false + + + + + + + + 0 + 0 + + + + + 300 + 32 + + + + + 16777215 + 32 + + + + + 14 + + + + IBeamCursor + + + Banned peers + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Qt::ScrollBarAsNeeded + + + true + + + false + + + + diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 2a94312be..c6e70697f 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -8,6 +8,7 @@ #include "clientmodel.h" #include "guiutil.h" #include "platformstyle.h" +#include "bantablemodel.h" #include "chainparams.h" #include "rpcserver.h" @@ -351,6 +352,9 @@ void RPCConsole::setClientModel(ClientModel *model) ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH); ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH); + // set up ban table + ui->banlistWidget->setModel(model->getBanTableModel()); + // create context menu actions QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this); QAction* banAction1h = new QAction(tr("&Ban Node for 1 hour"), this); @@ -395,6 +399,12 @@ void RPCConsole::setClientModel(ClientModel *model) ui->buildDate->setText(model->formatBuildDate()); ui->startupTime->setText(model->formatClientStartupTime()); ui->networkName->setText(QString::fromStdString(Params().NetworkIDString())); + + if (!clientModel->getBanTableModel()->shouldShow()) + { + ui->banlistWidget->hide(); + ui->banHeading->hide(); + } } } @@ -766,6 +776,9 @@ void RPCConsole::banSelectedNode(int bantime) CNode::Ban(CNetAddr(addr), bantime); bannedNode->CloseSocketDisconnect(); clearSelectedNode(); + ui->banlistWidget->setVisible(true); + ui->banHeading->setVisible(true); + clientModel->updateBanlist(); } } From 5f421329508d6e86c410282c7de39d7e80b0b289 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 20 Jun 2015 20:27:28 +0200 Subject: [PATCH 03/20] [Qt] add ui signal for banlist changes --- src/qt/clientmodel.cpp | 8 ++++++++ src/rpcnet.cpp | 5 +++++ src/ui_interface.h | 3 +++ 3 files changed, 16 insertions(+) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 62c35130f..7f5dea0ef 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -243,12 +243,19 @@ static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, Ch Q_ARG(int, status)); } +static void BannedListChanged(ClientModel *clientmodel) +{ + qDebug() << "BannedListChanged"; + QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection); +} + void ClientModel::subscribeToCoreSignals() { // Connect signals to client uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); + uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this)); } void ClientModel::unsubscribeFromCoreSignals() @@ -257,4 +264,5 @@ void ClientModel::unsubscribeFromCoreSignals() uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); + uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this)); } diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 30d0ed627..482e2ac47 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -12,6 +12,7 @@ #include "protocol.h" #include "sync.h" #include "timedata.h" +#include "ui_interface.h" #include "util.h" #include "utilstrencodings.h" #include "version.h" @@ -531,6 +532,8 @@ UniValue setban(const UniValue& params, bool fHelp) } DumpBanlist(); //store banlist to disk + uiInterface.BannedListChanged(); + return NullUniValue; } @@ -577,6 +580,8 @@ UniValue clearbanned(const UniValue& params, bool fHelp) CNode::ClearBanned(); DumpBanlist(); //store banlist to disk + + uiInterface.BannedListChanged(); return NullUniValue; } diff --git a/src/ui_interface.h b/src/ui_interface.h index 32a92a4b8..e40247993 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -95,6 +95,9 @@ public: /** New block has been accepted */ boost::signals2::signal NotifyBlockTip; + + /** Banlist did change. */ + boost::signals2::signal BannedListChanged; }; extern CClientUIInterface uiInterface; From 770ca79aa02964f56610ffaf15b16297634fa065 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 20 Jun 2015 20:55:21 +0200 Subject: [PATCH 04/20] [Qt] add context menu with unban option to ban table --- src/qt/rpcconsole.cpp | 65 ++++++++++++++++++++++++++++++++++--------- src/qt/rpcconsole.h | 9 ++++-- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index c6e70697f..5658cf875 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -241,8 +241,9 @@ RPCConsole::RPCConsole(const PlatformStyle *platformStyle, QWidget *parent) : clientModel(0), historyPtr(0), cachedNodeid(-1), - contextMenu(0), platformStyle(platformStyle) + peersTableContextMenu(0), + banTableContextMenu(0) { ui->setupUi(this); GUIUtil::restoreWindowGeometry("nRPCConsoleWindow", this->size(), this); @@ -351,9 +352,7 @@ void RPCConsole::setClientModel(ClientModel *model) ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH); ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH); ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH); - - // set up ban table - ui->banlistWidget->setModel(model->getBanTableModel()); + ui->peerWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); // create context menu actions QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this); @@ -363,15 +362,15 @@ void RPCConsole::setClientModel(ClientModel *model) QAction* banAction365d = new QAction(tr("&Ban Node for 1 year"), this); // create context menu - contextMenu = new QMenu(); - contextMenu->addAction(disconnectAction); - contextMenu->addAction(banAction1h); - contextMenu->addAction(banAction24h); - contextMenu->addAction(banAction7d); - contextMenu->addAction(banAction365d); + peersTableContextMenu = new QMenu(); + peersTableContextMenu->addAction(disconnectAction); + peersTableContextMenu->addAction(banAction1h); + peersTableContextMenu->addAction(banAction24h); + peersTableContextMenu->addAction(banAction7d); + peersTableContextMenu->addAction(banAction365d); // context menu signals - connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showMenu(const QPoint&))); + connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showPeersTableContextMenu(const QPoint&))); connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode())); //add a signal mapping, use int instead of int64_t for bantime because signalmapper only supports int or objects @@ -392,6 +391,26 @@ void RPCConsole::setClientModel(ClientModel *model) this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &))); connect(model->getPeerTableModel(), SIGNAL(layoutChanged()), this, SLOT(peerLayoutChanged())); + // set up ban table + ui->banlistWidget->setModel(model->getBanTableModel()); + ui->banlistWidget->verticalHeader()->hide(); + ui->banlistWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + ui->banlistWidget->setColumnWidth(BanTableModel::Address, ADDRESS_COLUMN_WIDTH); + ui->banlistWidget->setColumnWidth(BanTableModel::Bantime, PING_COLUMN_WIDTH); + ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection); + ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu); + ui->banlistWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + + // create context menu actions + QAction* unbanAction = new QAction(tr("&Unban Node"), this); + banTableContextMenu = new QMenu(); + banTableContextMenu->addAction(unbanAction); + + // context menu signals + connect(ui->banlistWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showBanTableContextMenu(const QPoint&))); + connect(unbanAction, SIGNAL(triggered()), this, SLOT(unbanSelectedNode())); + // Provide initial values ui->clientVersion->setText(model->formatFullVersion()); ui->clientUserAgent->setText(model->formatSubVersion()); @@ -744,11 +763,18 @@ void RPCConsole::hideEvent(QHideEvent *event) clientModel->getPeerTableModel()->stopAutoRefresh(); } -void RPCConsole::showMenu(const QPoint& point) +void RPCConsole::showPeersTableContextMenu(const QPoint& point) { QModelIndex index = ui->peerWidget->indexAt(point); if (index.isValid()) - contextMenu->exec(QCursor::pos()); + peersTableContextMenu->exec(QCursor::pos()); +} + +void RPCConsole::showBanTableContextMenu(const QPoint& point) +{ + QModelIndex index = ui->banlistWidget->indexAt(point); + if (index.isValid()) + banTableContextMenu->exec(QCursor::pos()); } void RPCConsole::disconnectSelectedNode() @@ -782,6 +808,19 @@ void RPCConsole::banSelectedNode(int bantime) } } +void RPCConsole::unbanSelectedNode() +{ + // Get currently selected peer address + QString strNode = GUIUtil::getEntryData(ui->banlistWidget, 0, BanTableModel::Address); + CSubNet possibleSubnet(strNode.toStdString()); + + if (possibleSubnet.IsValid()) + { + CNode::Unban(possibleSubnet); + clientModel->updateBanlist(); + } +} + void RPCConsole::clearSelectedNode() { ui->peerWidget->selectionModel()->clearSelection(); diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 3218a635d..db1f3d433 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -61,7 +61,9 @@ private Q_SLOTS: void showEvent(QShowEvent *event); void hideEvent(QHideEvent *event); /** Show custom context menu on Peers tab */ - void showMenu(const QPoint& point); + void showPeersTableContextMenu(const QPoint& point); + /** Show custom context menu on Bans tab */ + void showBanTableContextMenu(const QPoint& point); public Q_SLOTS: void clear(); @@ -82,6 +84,8 @@ public Q_SLOTS: void disconnectSelectedNode(); /** Ban a selected node on the Peers tab */ void banSelectedNode(int bantime); + /** Unban a selected node on the Bans tab */ + void unbanSelectedNode(); Q_SIGNALS: // For RPC command executor @@ -109,9 +113,10 @@ private: QStringList history; int historyPtr; NodeId cachedNodeid; - QMenu *contextMenu; const PlatformStyle *platformStyle; RPCTimerInterface *rpcTimerInterface; + QMenu *peersTableContextMenu; + QMenu *banTableContextMenu; }; #endif // BITCOIN_QT_RPCCONSOLE_H From 6135309816208740888b25bc27ea123c1c825a04 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sat, 20 Jun 2015 21:48:10 +0200 Subject: [PATCH 05/20] [Qt] banlist, UI optimizing and better signal handling --- src/qt/clientmodel.cpp | 1 + src/qt/clientmodel.h | 1 + src/qt/forms/rpcconsole.ui | 8 +------- src/qt/rpcconsole.cpp | 32 +++++++++++++++++++------------- src/qt/rpcconsole.h | 7 ++++++- src/rpcnet.cpp | 1 - 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 7f5dea0ef..2af8226c1 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -217,6 +217,7 @@ QString ClientModel::formatClientStartupTime() const void ClientModel::updateBanlist() { banTableModel->refresh(); + emit banListChanged(); } // Handlers for core signals diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 627bdf862..6f7b2de3a 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -91,6 +91,7 @@ Q_SIGNALS: void numBlocksChanged(int count, const QDateTime& blockDate); void alertsChanged(const QString &warnings); void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); + void banListChanged(); //! Fired when a message should be reported to the user void message(const QString &title, const QString &message, unsigned int style); diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index 39230aee6..c920e6130 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -752,7 +752,7 @@ - 14 + 12 @@ -780,12 +780,6 @@ 0 - - - 16777215 - 16777215 - - Qt::ScrollBarAsNeeded diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 5658cf875..3f20f67f2 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -352,7 +352,7 @@ void RPCConsole::setClientModel(ClientModel *model) ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH); ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH); ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH); - ui->peerWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + ui->peerWidget->horizontalHeader()->setStretchLastSection(true); // create context menu actions QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this); @@ -373,8 +373,9 @@ void RPCConsole::setClientModel(ClientModel *model) connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showPeersTableContextMenu(const QPoint&))); connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode())); - //add a signal mapping, use int instead of int64_t for bantime because signalmapper only supports int or objects - //int is sufficient for our case + //add a signal mapping to allow a dynamic argument + //we need to use int (instead of int64_t) because signal mapper only supports int or objects + //this is okay because max bantime (1 Year) is smaler then int_max QSignalMapper* signalMapper = new QSignalMapper(this); signalMapper->setMapping(banAction1h, 60*60); signalMapper->setMapping(banAction24h, 60*60*24); @@ -395,14 +396,14 @@ void RPCConsole::setClientModel(ClientModel *model) ui->banlistWidget->setModel(model->getBanTableModel()); ui->banlistWidget->verticalHeader()->hide(); ui->banlistWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); - ui->banlistWidget->setColumnWidth(BanTableModel::Address, ADDRESS_COLUMN_WIDTH); - ui->banlistWidget->setColumnWidth(BanTableModel::Bantime, PING_COLUMN_WIDTH); + ui->banlistWidget->setColumnWidth(BanTableModel::Address, BANSUBNET_COLUMN_WIDTH); + ui->banlistWidget->setColumnWidth(BanTableModel::Bantime, BANTIME_COLUMN_WIDTH); ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection); ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu); - ui->banlistWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + ui->banlistWidget->horizontalHeader()->setStretchLastSection(true); - // create context menu actions + // create banlist context menu actions QAction* unbanAction = new QAction(tr("&Unban Node"), this); banTableContextMenu = new QMenu(); banTableContextMenu->addAction(unbanAction); @@ -419,11 +420,8 @@ void RPCConsole::setClientModel(ClientModel *model) ui->startupTime->setText(model->formatClientStartupTime()); ui->networkName->setText(QString::fromStdString(Params().NetworkIDString())); - if (!clientModel->getBanTableModel()->shouldShow()) - { - ui->banlistWidget->hide(); - ui->banHeading->hide(); - } + connect(model, SIGNAL(banListChanged()), this, SLOT(showOrHideBanTableIfRequired())); + showOrHideBanTableIfRequired(); } } @@ -810,7 +808,7 @@ void RPCConsole::banSelectedNode(int bantime) void RPCConsole::unbanSelectedNode() { - // Get currently selected peer address + // Get currently selected ban address QString strNode = GUIUtil::getEntryData(ui->banlistWidget, 0, BanTableModel::Address); CSubNet possibleSubnet(strNode.toStdString()); @@ -818,6 +816,7 @@ void RPCConsole::unbanSelectedNode() { CNode::Unban(possibleSubnet); clientModel->updateBanlist(); + showOrHideBanTableIfRequired(); } } @@ -828,3 +827,10 @@ void RPCConsole::clearSelectedNode() ui->detailWidget->hide(); ui->peerHeading->setText(tr("Select a peer to view detailed information.")); } + +void RPCConsole::showOrHideBanTableIfRequired() +{ + bool visible = clientModel->getBanTableModel()->shouldShow(); + ui->banlistWidget->setVisible(visible); + ui->banHeading->setVisible(visible); +} \ No newline at end of file diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index db1f3d433..9674cc527 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -64,6 +64,8 @@ private Q_SLOTS: void showPeersTableContextMenu(const QPoint& point); /** Show custom context menu on Bans tab */ void showBanTableContextMenu(const QPoint& point); + /** Hides ban table if no bans are present */ + void showOrHideBanTableIfRequired(); public Q_SLOTS: void clear(); @@ -105,7 +107,10 @@ private: { ADDRESS_COLUMN_WIDTH = 200, SUBVERSION_COLUMN_WIDTH = 100, - PING_COLUMN_WIDTH = 80 + PING_COLUMN_WIDTH = 80, + BANSUBNET_COLUMN_WIDTH = 300, + BANTIME_COLUMN_WIDTH = 150 + }; Ui::RPCConsole *ui; diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 482e2ac47..5d490c70c 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -580,7 +580,6 @@ UniValue clearbanned(const UniValue& params, bool fHelp) CNode::ClearBanned(); DumpBanlist(); //store banlist to disk - uiInterface.BannedListChanged(); return NullUniValue; From f0bcbc4c8a9918e5d240ba2736286cede76155f5 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sun, 21 Jun 2015 10:25:00 +0200 Subject: [PATCH 06/20] [Qt] bantable fix timestamp 64bit issue --- src/qt/bantablemodel.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index 3b71769ef..615574cca 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -118,13 +118,9 @@ QVariant BanTableModel::data(const QModelIndex &index, int role) const case Address: return QString::fromStdString(rec->subnet.ToString()); case Bantime: - //show time in users local timezone, not 64bit compatible! - //TODO find a way to support 64bit timestamps - boost::posix_time::ptime pt1 = boost::posix_time::from_time_t(rec->bantil); - boost::posix_time::ptime pt2 = boost::date_time::c_local_adjustor::utc_to_local(pt1); - std::stringstream ss; - ss << pt2; - return QString::fromStdString(ss.str()); + QDateTime date = QDateTime::fromMSecsSinceEpoch(0); + date = date.addSecs(rec->bantil); + return date.toString(Qt::SystemLocaleShortDate); } } else if (role == Qt::TextAlignmentRole) { if (index.column() == Bantime) From 53caec66cc43e1f16ba26e16147b77f5cfba22bb Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sun, 21 Jun 2015 10:44:48 +0200 Subject: [PATCH 07/20] [Qt] bantable overhaul - some code cleanups - fix date formatting - reduce header includes --- src/qt/bantablemodel.cpp | 12 ++++++------ src/qt/bantablemodel.h | 1 - src/qt/rpcconsole.cpp | 14 +++++++++----- src/qt/rpcconsole.h | 4 ++-- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index 615574cca..b4b100bf5 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -8,7 +8,6 @@ #include "guiconstants.h" #include "guiutil.h" -#include "net.h" #include "sync.h" #include "utiltime.h" @@ -41,15 +40,16 @@ public: cachedBanlist.reserve(banMap.size()); #endif std::map::iterator iter; - for (iter = banMap.begin(); iter != banMap.end(); ++iter) { + foreach (const PAIRTYPE(CSubNet, int64_t)& banentry, banMap) + { CCombinedBan banEntry; - banEntry.subnet = iter->first; - banEntry.bantil = iter->second; + banEntry.subnet = banentry.first; + banEntry.bantil = banentry.second; cachedBanlist.append(banEntry); } } - int size() + int size() const { return cachedBanlist.size(); } @@ -120,7 +120,7 @@ QVariant BanTableModel::data(const QModelIndex &index, int role) const case Bantime: QDateTime date = QDateTime::fromMSecsSinceEpoch(0); date = date.addSecs(rec->bantil); - return date.toString(Qt::SystemLocaleShortDate); + return date.toString(Qt::SystemLocaleLongDate); } } else if (role == Qt::TextAlignmentRole) { if (index.column() == Bantime) diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h index ef7a26e3c..8d3da4c73 100644 --- a/src/qt/bantablemodel.h +++ b/src/qt/bantablemodel.h @@ -5,7 +5,6 @@ #ifndef BITCOIN_QT_BANTABLEMODEL_H #define BITCOIN_QT_BANTABLEMODEL_H -#include "main.h" #include "net.h" #include diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 3f20f67f2..9271df953 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -356,10 +356,10 @@ void RPCConsole::setClientModel(ClientModel *model) // create context menu actions QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this); - QAction* banAction1h = new QAction(tr("&Ban Node for 1 hour"), this); - QAction* banAction24h = new QAction(tr("&Ban Node for 24 hours"), this); - QAction* banAction7d = new QAction(tr("&Ban Node for 7 days"), this); - QAction* banAction365d = new QAction(tr("&Ban Node for 1 year"), this); + QAction* banAction1h = new QAction(tr("&Ban Node for") + " " + tr("&1 hour"), this); + QAction* banAction24h = new QAction(tr("&Ban Node for") + " " + tr("&24 hours"), this); + QAction* banAction7d = new QAction(tr("&Ban Node for") + " " + tr("&7 days"), this); + QAction* banAction365d = new QAction(tr("&Ban Node for") + " " + tr("&1 year"), this); // create context menu peersTableContextMenu = new QMenu(); @@ -798,7 +798,8 @@ void RPCConsole::banSelectedNode(int bantime) SplitHostPort(nStr, port, addr); CNode::Ban(CNetAddr(addr), bantime); - bannedNode->CloseSocketDisconnect(); + bannedNode->fDisconnect = true; + clearSelectedNode(); ui->banlistWidget->setVisible(true); ui->banHeading->setVisible(true); @@ -830,6 +831,9 @@ void RPCConsole::clearSelectedNode() void RPCConsole::showOrHideBanTableIfRequired() { + if (!clientModel) + return; + bool visible = clientModel->getBanTableModel()->shouldShow(); ui->banlistWidget->setVisible(visible); ui->banHeading->setVisible(visible); diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 9674cc527..3f4d1834f 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -108,8 +108,8 @@ private: ADDRESS_COLUMN_WIDTH = 200, SUBVERSION_COLUMN_WIDTH = 100, PING_COLUMN_WIDTH = 80, - BANSUBNET_COLUMN_WIDTH = 300, - BANTIME_COLUMN_WIDTH = 150 + BANSUBNET_COLUMN_WIDTH = 250, + BANTIME_COLUMN_WIDTH = 200 }; From 607809f037950f114f64f1ee09c1486a3c66638b Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 23 Jun 2015 17:20:00 +0200 Subject: [PATCH 08/20] net: use CIDR notation in CSubNet::ToString() --- src/netbase.cpp | 20 ++++++----- src/test/netbase_tests.cpp | 74 ++++++++++++++++++++++++++++++++++++++ src/test/rpc_tests.cpp | 14 ++++---- 3 files changed, 92 insertions(+), 16 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 7a87d125c..4163b1808 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -1314,15 +1314,17 @@ bool CSubNet::Match(const CNetAddr &addr) const std::string CSubNet::ToString() const { std::string strNetmask; - if (network.IsIPv4()) - strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]); - else - strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x", - netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3], - netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7], - netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11], - netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]); - return network.ToString() + "/" + strNetmask; + int cidr = 0; + for (int n = network.IsIPv4() ? 12 : 0 ; n < 16; ++n) + { + uint8_t netmaskpart = netmask[n]; + while (netmaskpart) + { + cidr += ( netmaskpart & 0x01 ); + netmaskpart >>= 1; + } + } + return network.ToString() + strprintf("/%u", cidr); } bool CSubNet::IsValid() const diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 3f99dc98d..f0333d868 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -155,6 +155,80 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:8"))); BOOST_CHECK(!CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:9"))); BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + + CSubNet subnet = CSubNet("1.2.3.4/255.255.255.255"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32"); + subnet = CSubNet("1.2.3.4/255.255.255.254"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/31"); + subnet = CSubNet("1.2.3.4/255.255.255.252"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/30"); + subnet = CSubNet("1.2.3.4/255.255.255.248"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/29"); + subnet = CSubNet("1.2.3.4/255.255.255.240"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/28"); + subnet = CSubNet("1.2.3.4/255.255.255.224"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/27"); + subnet = CSubNet("1.2.3.4/255.255.255.192"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/26"); + subnet = CSubNet("1.2.3.4/255.255.255.128"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/25"); + subnet = CSubNet("1.2.3.4/255.255.255.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/24"); + subnet = CSubNet("1.2.3.4/255.255.254.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.2.0/23"); + subnet = CSubNet("1.2.3.4/255.255.252.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/22"); + subnet = CSubNet("1.2.3.4/255.255.248.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/21"); + subnet = CSubNet("1.2.3.4/255.255.240.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/20"); + subnet = CSubNet("1.2.3.4/255.255.224.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/19"); + subnet = CSubNet("1.2.3.4/255.255.192.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/18"); + subnet = CSubNet("1.2.3.4/255.255.128.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/17"); + subnet = CSubNet("1.2.3.4/255.255.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/16"); + subnet = CSubNet("1.2.3.4/255.254.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/15"); + subnet = CSubNet("1.2.3.4/255.252.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/14"); + subnet = CSubNet("1.2.3.4/255.248.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/13"); + subnet = CSubNet("1.2.3.4/255.240.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/12"); + subnet = CSubNet("1.2.3.4/255.224.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/11"); + subnet = CSubNet("1.2.3.4/255.192.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/10"); + subnet = CSubNet("1.2.3.4/255.128.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/9"); + subnet = CSubNet("1.2.3.4/255.0.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8"); + subnet = CSubNet("1.2.3.4/254.0.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/7"); + subnet = CSubNet("1.2.3.4/252.0.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/6"); + subnet = CSubNet("1.2.3.4/248.0.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/5"); + subnet = CSubNet("1.2.3.4/240.0.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/4"); + subnet = CSubNet("1.2.3.4/224.0.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/3"); + subnet = CSubNet("1.2.3.4/192.0.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/2"); + subnet = CSubNet("1.2.3.4/128.0.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/1"); + subnet = CSubNet("1.2.3.4/0.0.0.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0"); + + subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/128"); + subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:0000:0000:0000:0000:0000:0000:0000"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1::/16"); + subnet = CSubNet("1:2:3:4:5:6:7:8/0000:0000:0000:0000:0000:0000:0000:0000"); + BOOST_CHECK_EQUAL(subnet.ToString(), "::/0"); } BOOST_AUTO_TEST_CASE(netbase_getgroup) diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index c0476db99..1bd59497f 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -235,7 +235,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban) UniValue ar = r.get_array(); UniValue o1 = ar[0].get_obj(); UniValue adr = find_value(o1, "address"); - BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.255"); + BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/32"); BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.0 remove")));; BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); ar = r.get_array(); @@ -247,7 +247,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban) o1 = ar[0].get_obj(); adr = find_value(o1, "address"); UniValue banned_until = find_value(o1, "banned_until"); - BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0"); + BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24"); BOOST_CHECK_EQUAL(banned_until.get_int64(), 1607731200); // absolute time check BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); @@ -258,7 +258,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban) o1 = ar[0].get_obj(); adr = find_value(o1, "address"); banned_until = find_value(o1, "banned_until"); - BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0"); + BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24"); int64_t now = GetTime(); BOOST_CHECK(banned_until.get_int64() > now); BOOST_CHECK(banned_until.get_int64()-now <= 200); @@ -288,15 +288,15 @@ BOOST_AUTO_TEST_CASE(rpc_ban) ar = r.get_array(); o1 = ar[0].get_obj(); adr = find_value(o1, "address"); - BOOST_CHECK_EQUAL(adr.get_str(), "fe80::202:b3ff:fe1e:8329/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + BOOST_CHECK_EQUAL(adr.get_str(), "fe80::202:b3ff:fe1e:8329/128"); BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); - BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 2001:db8::/30 add"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 2001:db8::/ffff:fffc:0:0:0:0:0:0 add"))); BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); ar = r.get_array(); o1 = ar[0].get_obj(); adr = find_value(o1, "address"); - BOOST_CHECK_EQUAL(adr.get_str(), "2001:db8::/ffff:fffc:0:0:0:0:0:0"); + BOOST_CHECK_EQUAL(adr.get_str(), "2001:db8::/30"); BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128 add"))); @@ -304,7 +304,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban) ar = r.get_array(); o1 = ar[0].get_obj(); adr = find_value(o1, "address"); - BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128"); } BOOST_AUTO_TEST_SUITE_END() From 9e521c173586257f57764b479beb5923c33ed0eb Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Tue, 23 Jun 2015 21:10:42 +0200 Subject: [PATCH 09/20] [Qt] polish ban table --- src/qt/bantablemodel.cpp | 16 +++++----------- src/qt/clientmodel.cpp | 2 +- src/qt/rpcconsole.cpp | 20 +++++++++++--------- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index b4b100bf5..1ef120ccf 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -56,11 +56,10 @@ public: CCombinedBan *index(int idx) { - if(idx >= 0 && idx < cachedBanlist.size()) { + if (idx >= 0 && idx < cachedBanlist.size()) return &cachedBanlist[idx]; - } else { - return 0; - } + + return 0; } }; @@ -124,7 +123,7 @@ QVariant BanTableModel::data(const QModelIndex &index, int role) const } } else if (role == Qt::TextAlignmentRole) { if (index.column() == Bantime) - return (int)(Qt::AlignRight | Qt::AlignVCenter); + return (QVariant)(Qt::AlignRight | Qt::AlignVCenter); } return QVariant(); @@ -157,13 +156,8 @@ QModelIndex BanTableModel::index(int row, int column, const QModelIndex &parent) CCombinedBan *data = priv->index(row); if (data) - { return createIndex(row, column, data); - } - else - { - return QModelIndex(); - } + return QModelIndex(); } void BanTableModel::refresh() diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 2af8226c1..851e9f186 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -246,7 +246,7 @@ static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, Ch static void BannedListChanged(ClientModel *clientmodel) { - qDebug() << "BannedListChanged"; + qDebug() << QString("%1: Requesting update for peer banlist").arg(__func__); QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection); } diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 9271df953..380586f61 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -5,6 +5,7 @@ #include "rpcconsole.h" #include "ui_rpcconsole.h" +#include "bantablemodel.h" #include "clientmodel.h" #include "guiutil.h" #include "platformstyle.h" @@ -373,9 +374,9 @@ void RPCConsole::setClientModel(ClientModel *model) connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showPeersTableContextMenu(const QPoint&))); connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode())); - //add a signal mapping to allow a dynamic argument - //we need to use int (instead of int64_t) because signal mapper only supports int or objects - //this is okay because max bantime (1 Year) is smaler then int_max + // Add a signal mapping to allow dynamic context menu arguments. + // We need to use int (instead of int64_t), because signal mapper only supports + // int or objects, which is okay because max bantime (1 year) is < int_max. QSignalMapper* signalMapper = new QSignalMapper(this); signalMapper->setMapping(banAction1h, 60*60); signalMapper->setMapping(banAction24h, 60*60*24); @@ -385,7 +386,7 @@ void RPCConsole::setClientModel(ClientModel *model) connect(banAction24h, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(banAction7d, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(banAction365d, SIGNAL(triggered()), signalMapper, SLOT(map())); - connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(banSelectedNode(int))) ; + connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(banSelectedNode(int))); // connect the peerWidget selection model to our peerSelected() handler connect(ui->peerWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), @@ -403,8 +404,12 @@ void RPCConsole::setClientModel(ClientModel *model) ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu); ui->banlistWidget->horizontalHeader()->setStretchLastSection(true); + // ensure ban table is shown or hidden (if empty) + connect(model, SIGNAL(banListChanged()), this, SLOT(showOrHideBanTableIfRequired())); + showOrHideBanTableIfRequired(); + // create banlist context menu actions - QAction* unbanAction = new QAction(tr("&Unban Node"), this); + QAction* unbanAction = new QAction(tr("&Unban Node"), this); banTableContextMenu = new QMenu(); banTableContextMenu->addAction(unbanAction); @@ -419,9 +424,6 @@ void RPCConsole::setClientModel(ClientModel *model) ui->buildDate->setText(model->formatBuildDate()); ui->startupTime->setText(model->formatClientStartupTime()); ui->networkName->setText(QString::fromStdString(Params().NetworkIDString())); - - connect(model, SIGNAL(banListChanged()), this, SLOT(showOrHideBanTableIfRequired())); - showOrHideBanTableIfRequired(); } } @@ -833,7 +835,7 @@ void RPCConsole::showOrHideBanTableIfRequired() { if (!clientModel) return; - + bool visible = clientModel->getBanTableModel()->shouldShow(); ui->banlistWidget->setVisible(visible); ui->banHeading->setVisible(visible); From e2b8028e4c60708a8d49b17d9d49dda10aaecc51 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 25 Jun 2015 10:47:34 +0200 Subject: [PATCH 10/20] net: Fix CIDR notation in ToString() Only use CIDR notation if the netmask can be represented as such. --- src/netbase.cpp | 58 +++++++++++++++++++++++++++++++------- src/test/netbase_tests.cpp | 6 ++++ 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 4163b1808..c3d56d918 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -1311,20 +1311,58 @@ bool CSubNet::Match(const CNetAddr &addr) const return true; } +static inline int NetmaskBits(uint8_t x) +{ + switch(x) { + case 0x00: return 0; break; + case 0x80: return 1; break; + case 0xc0: return 2; break; + case 0xe0: return 3; break; + case 0xf0: return 4; break; + case 0xf8: return 5; break; + case 0xfc: return 6; break; + case 0xfe: return 7; break; + case 0xff: return 8; break; + default: return -1; break; + } +} + std::string CSubNet::ToString() const { - std::string strNetmask; + /* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */ int cidr = 0; - for (int n = network.IsIPv4() ? 12 : 0 ; n < 16; ++n) - { - uint8_t netmaskpart = netmask[n]; - while (netmaskpart) - { - cidr += ( netmaskpart & 0x01 ); - netmaskpart >>= 1; - } + bool valid_cidr = true; + int n = network.IsIPv4() ? 12 : 0; + for (; n < 16 && netmask[n] == 0xff; ++n) + cidr += 8; + if (n < 16) { + int bits = NetmaskBits(netmask[n]); + if (bits < 0) + valid_cidr = false; + else + cidr += bits; + ++n; } - return network.ToString() + strprintf("/%u", cidr); + for (; n < 16 && valid_cidr; ++n) + if (netmask[n] != 0x00) + valid_cidr = false; + + /* Format output */ + std::string strNetmask; + if (valid_cidr) { + strNetmask = strprintf("%u", cidr); + } else { + if (network.IsIPv4()) + strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]); + else + strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x", + netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3], + netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7], + netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11], + netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]); + } + + return network.ToString() + "/" + strNetmask; } bool CSubNet::IsValid() const diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index f0333d868..8e853cc28 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -229,6 +229,12 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_CHECK_EQUAL(subnet.ToString(), "1::/16"); subnet = CSubNet("1:2:3:4:5:6:7:8/0000:0000:0000:0000:0000:0000:0000:0000"); BOOST_CHECK_EQUAL(subnet.ToString(), "::/0"); + subnet = CSubNet("1.2.3.4/255.255.232.0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/255.255.232.0"); + subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f"); + subnet = CSubNet("1:2:3:4:5:6:7:8/fff:ffff:ffff:ffff:ffff:ffff:ffff:fff0"); + BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:0/fff:ffff:ffff:ffff:ffff:ffff:ffff:fff0"); } BOOST_AUTO_TEST_CASE(netbase_getgroup) From 43c1f5b8d7accc158dfd6b270cb9bfd0cd900a3e Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 26 Jun 2015 10:21:13 +0200 Subject: [PATCH 11/20] [Qt] remove unused timer-code from banlistmodel.cpp --- src/qt/bantablemodel.cpp | 19 +------------------ src/qt/bantablemodel.h | 5 ----- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index 1ef120ccf..ee40cdbf5 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -13,7 +13,6 @@ #include #include -#include #include #include @@ -65,33 +64,17 @@ public: BanTableModel::BanTableModel(ClientModel *parent) : QAbstractTableModel(parent), - clientModel(parent), - timer(0) + clientModel(parent) { columns << tr("IP/Netmask") << tr("Banned Until"); priv = new BanTablePriv(); // default to unsorted priv->sortColumn = -1; - // set up timer for auto refresh - timer = new QTimer(); - connect(timer, SIGNAL(timeout()), SLOT(refresh())); - timer->setInterval(MODEL_UPDATE_DELAY); - // load initial data refresh(); } -void BanTableModel::startAutoRefresh() -{ - timer->start(); -} - -void BanTableModel::stopAutoRefresh() -{ - timer->stop(); -} - int BanTableModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h index 8d3da4c73..c0f0813f2 100644 --- a/src/qt/bantablemodel.h +++ b/src/qt/bantablemodel.h @@ -13,10 +13,6 @@ class ClientModel; class BanTablePriv; -QT_BEGIN_NAMESPACE -class QTimer; -QT_END_NAMESPACE - struct CCombinedBan { CSubNet subnet; int64_t bantil; @@ -59,7 +55,6 @@ private: ClientModel *clientModel; QStringList columns; BanTablePriv *priv; - QTimer *timer; }; #endif // BITCOIN_QT_BANTABLEMODEL_H From cdd72cd5fbc2b287559f7230d1616339e9ff2d6d Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Fri, 26 Jun 2015 10:23:51 +0200 Subject: [PATCH 12/20] [Qt] simplify ban list signal handling - remove banListChanged signal from client model - directly call clientModel->getBanTableModel()->refresh() without the way over clientModel->updateBanlist() - also fix clearing peer detail window, when selecting (clicking) peers in the ban list --- src/qt/clientmodel.cpp | 1 - src/qt/clientmodel.h | 1 - src/qt/rpcconsole.cpp | 32 +++++++++++++++++++------------- src/qt/rpcconsole.h | 4 ++-- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 851e9f186..0900a35cc 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -217,7 +217,6 @@ QString ClientModel::formatClientStartupTime() const void ClientModel::updateBanlist() { banTableModel->refresh(); - emit banListChanged(); } // Handlers for core signals diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 6f7b2de3a..627bdf862 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -91,7 +91,6 @@ Q_SIGNALS: void numBlocksChanged(int count, const QDateTime& blockDate); void alertsChanged(const QString &warnings); void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); - void banListChanged(); //! Fired when a message should be reported to the user void message(const QString &title, const QString &message, unsigned int style); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 380586f61..1b82aada4 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -331,8 +331,7 @@ void RPCConsole::setClientModel(ClientModel *model) { clientModel = model; ui->trafficGraph->setClientModel(model); - if(model) - { + if (model && clientModel->getPeerTableModel() && clientModel->getBanTableModel()) { // Keep up to date with client setNumConnections(model->getNumConnections()); connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); @@ -404,19 +403,23 @@ void RPCConsole::setClientModel(ClientModel *model) ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu); ui->banlistWidget->horizontalHeader()->setStretchLastSection(true); - // ensure ban table is shown or hidden (if empty) - connect(model, SIGNAL(banListChanged()), this, SLOT(showOrHideBanTableIfRequired())); - showOrHideBanTableIfRequired(); - - // create banlist context menu actions + // create ban table context menu action QAction* unbanAction = new QAction(tr("&Unban Node"), this); + + // create ban table context menu banTableContextMenu = new QMenu(); banTableContextMenu->addAction(unbanAction); - // context menu signals + // ban table context menu signals connect(ui->banlistWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showBanTableContextMenu(const QPoint&))); connect(unbanAction, SIGNAL(triggered()), this, SLOT(unbanSelectedNode())); + // ban table signal handling - clear peer details when clicking a peer in the ban table + connect(ui->banlistWidget, SIGNAL(clicked(const QModelIndex&)), this, SLOT(clearSelectedNode())); + // ban table signal handling - ensure ban table is shown or hidden (if empty) + connect(model->getBanTableModel(), SIGNAL(layoutChanged()), this, SLOT(showOrHideBanTableIfRequired())); + showOrHideBanTableIfRequired(); + // Provide initial values ui->clientVersion->setText(model->formatFullVersion()); ui->clientUserAgent->setText(model->formatSubVersion()); @@ -790,6 +793,9 @@ void RPCConsole::disconnectSelectedNode() void RPCConsole::banSelectedNode(int bantime) { + if (!clientModel) + return; + // Get currently selected peer address QString strNode = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::Address); // Find possible nodes, ban it and clear the selected node @@ -803,14 +809,15 @@ void RPCConsole::banSelectedNode(int bantime) bannedNode->fDisconnect = true; clearSelectedNode(); - ui->banlistWidget->setVisible(true); - ui->banHeading->setVisible(true); - clientModel->updateBanlist(); + clientModel->getBanTableModel()->refresh(); } } void RPCConsole::unbanSelectedNode() { + if (!clientModel) + return; + // Get currently selected ban address QString strNode = GUIUtil::getEntryData(ui->banlistWidget, 0, BanTableModel::Address); CSubNet possibleSubnet(strNode.toStdString()); @@ -818,8 +825,7 @@ void RPCConsole::unbanSelectedNode() if (possibleSubnet.IsValid()) { CNode::Unban(possibleSubnet); - clientModel->updateBanlist(); - showOrHideBanTableIfRequired(); + clientModel->getBanTableModel()->refresh(); } } diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 3f4d1834f..d5a769ae7 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -66,6 +66,8 @@ private Q_SLOTS: void showBanTableContextMenu(const QPoint& point); /** Hides ban table if no bans are present */ void showOrHideBanTableIfRequired(); + /** clear the selected node */ + void clearSelectedNode(); public Q_SLOTS: void clear(); @@ -100,8 +102,6 @@ private: void setTrafficGraphRange(int mins); /** show detailed information on ui about selected node */ void updateNodeDetail(const CNodeCombinedStats *stats); - /** clear the selected node */ - void clearSelectedNode(); enum ColumnWidths { From 51654deff2661732c5e2a2aa8ac1f632f5880f45 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Fri, 26 Jun 2015 14:55:52 +0200 Subject: [PATCH 13/20] [Qt] bantable polish - add missing NULL pointer checks - add better comments and reorder some code in rpcconsole.cpp - remove unneeded leftovers in bantable.cpp - update bantable column sizes to prevent cutting of banned until --- src/qt/bantablemodel.cpp | 6 ------ src/qt/rpcconsole.cpp | 39 ++++++++++++++++++++------------------- src/qt/rpcconsole.h | 4 ++-- 3 files changed, 22 insertions(+), 27 deletions(-) diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index ee40cdbf5..6074cd2f0 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -14,8 +14,6 @@ #include #include -#include -#include // private implementation class BanTablePriv @@ -38,7 +36,6 @@ public: #if QT_VERSION >= 0x040700 cachedBanlist.reserve(banMap.size()); #endif - std::map::iterator iter; foreach (const PAIRTYPE(CSubNet, int64_t)& banentry, banMap) { CCombinedBan banEntry; @@ -104,9 +101,6 @@ QVariant BanTableModel::data(const QModelIndex &index, int role) const date = date.addSecs(rec->bantil); return date.toString(Qt::SystemLocaleLongDate); } - } else if (role == Qt::TextAlignmentRole) { - if (index.column() == Bantime) - return (QVariant)(Qt::AlignRight | Qt::AlignVCenter); } return QVariant(); diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 1b82aada4..c417ec3f3 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -354,14 +354,14 @@ void RPCConsole::setClientModel(ClientModel *model) ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH); ui->peerWidget->horizontalHeader()->setStretchLastSection(true); - // create context menu actions - QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this); - QAction* banAction1h = new QAction(tr("&Ban Node for") + " " + tr("&1 hour"), this); - QAction* banAction24h = new QAction(tr("&Ban Node for") + " " + tr("&24 hours"), this); - QAction* banAction7d = new QAction(tr("&Ban Node for") + " " + tr("&7 days"), this); - QAction* banAction365d = new QAction(tr("&Ban Node for") + " " + tr("&1 year"), this); + // create peer table context menu actions + QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this); + QAction* banAction1h = new QAction(tr("&Ban Node for") + " " + tr("&1 hour"), this); + QAction* banAction24h = new QAction(tr("&Ban Node for") + " " + tr("&24 hours"), this); + QAction* banAction7d = new QAction(tr("&Ban Node for") + " " + tr("&7 days"), this); + QAction* banAction365d = new QAction(tr("&Ban Node for") + " " + tr("&1 year"), this); - // create context menu + // create peer table context menu peersTableContextMenu = new QMenu(); peersTableContextMenu->addAction(disconnectAction); peersTableContextMenu->addAction(banAction1h); @@ -369,10 +369,6 @@ void RPCConsole::setClientModel(ClientModel *model) peersTableContextMenu->addAction(banAction7d); peersTableContextMenu->addAction(banAction365d); - // context menu signals - connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showPeersTableContextMenu(const QPoint&))); - connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode())); - // Add a signal mapping to allow dynamic context menu arguments. // We need to use int (instead of int64_t), because signal mapper only supports // int or objects, which is okay because max bantime (1 year) is < int_max. @@ -387,20 +383,25 @@ void RPCConsole::setClientModel(ClientModel *model) connect(banAction365d, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(banSelectedNode(int))); - // connect the peerWidget selection model to our peerSelected() handler + // peer table context menu signals + connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showPeersTableContextMenu(const QPoint&))); + connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode())); + + // peer table signal handling - update peer details when selecting new node connect(ui->peerWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), - this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &))); + this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &))); + // peer table signal handling - update peer details when new nodes are added to the model connect(model->getPeerTableModel(), SIGNAL(layoutChanged()), this, SLOT(peerLayoutChanged())); // set up ban table ui->banlistWidget->setModel(model->getBanTableModel()); ui->banlistWidget->verticalHeader()->hide(); ui->banlistWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); - ui->banlistWidget->setColumnWidth(BanTableModel::Address, BANSUBNET_COLUMN_WIDTH); - ui->banlistWidget->setColumnWidth(BanTableModel::Bantime, BANTIME_COLUMN_WIDTH); ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection); ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu); + ui->banlistWidget->setColumnWidth(BanTableModel::Address, BANSUBNET_COLUMN_WIDTH); + ui->banlistWidget->setColumnWidth(BanTableModel::Bantime, BANTIME_COLUMN_WIDTH); ui->banlistWidget->horizontalHeader()->setStretchLastSection(true); // create ban table context menu action @@ -629,7 +630,7 @@ void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelecti { Q_UNUSED(deselected); - if (!clientModel || selected.indexes().isEmpty()) + if (!clientModel || !clientModel->getPeerTableModel() || selected.indexes().isEmpty()) return; const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.indexes().first().row()); @@ -639,7 +640,7 @@ void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelecti void RPCConsole::peerLayoutChanged() { - if (!clientModel) + if (!clientModel || !clientModel->getPeerTableModel()) return; const CNodeCombinedStats *stats = NULL; @@ -748,7 +749,7 @@ void RPCConsole::showEvent(QShowEvent *event) { QWidget::showEvent(event); - if (!clientModel) + if (!clientModel || !clientModel->getPeerTableModel()) return; // start PeerTableModel auto refresh @@ -759,7 +760,7 @@ void RPCConsole::hideEvent(QHideEvent *event) { QWidget::hideEvent(event); - if (!clientModel) + if (!clientModel || !clientModel->getPeerTableModel()) return; // stop PeerTableModel auto refresh diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index d5a769ae7..b86f77678 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -108,8 +108,8 @@ private: ADDRESS_COLUMN_WIDTH = 200, SUBVERSION_COLUMN_WIDTH = 100, PING_COLUMN_WIDTH = 80, - BANSUBNET_COLUMN_WIDTH = 250, - BANTIME_COLUMN_WIDTH = 200 + BANSUBNET_COLUMN_WIDTH = 200, + BANTIME_COLUMN_WIDTH = 250 }; From 65abe91ce4c3c9b26afa5d1af38bd1bfe81546c4 Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Fri, 26 Jun 2015 14:58:15 +0200 Subject: [PATCH 14/20] [Qt] add sorting for bantable --- src/qt/bantablemodel.cpp | 22 ++++++++++++++++++++++ src/qt/bantablemodel.h | 14 +++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index 6074cd2f0..04840b052 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -14,6 +14,24 @@ #include #include +bool BannedNodeLessThan::operator()(const CCombinedBan& left, const CCombinedBan& right) const +{ + const CCombinedBan* pLeft = &left; + const CCombinedBan* pRight = &right; + + if (order == Qt::DescendingOrder) + std::swap(pLeft, pRight); + + switch(column) + { + case BanTableModel::Address: + return pLeft->subnet.ToString().compare(pRight->subnet.ToString()) < 0; + case BanTableModel::Bantime: + return pLeft->bantil < pRight->bantil; + } + + return false; +} // private implementation class BanTablePriv @@ -43,6 +61,10 @@ public: banEntry.bantil = banentry.second; cachedBanlist.append(banEntry); } + + if (sortColumn >= 0) + // sort cachedBanlist (use stable sort to prevent rows jumping around unneceesarily) + qStableSort(cachedBanlist.begin(), cachedBanlist.end(), BannedNodeLessThan(sortColumn, sortOrder)); } int size() const diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h index c0f0813f2..ec93ed101 100644 --- a/src/qt/bantablemodel.h +++ b/src/qt/bantablemodel.h @@ -18,6 +18,18 @@ struct CCombinedBan { int64_t bantil; }; +class BannedNodeLessThan +{ +public: + BannedNodeLessThan(int nColumn, Qt::SortOrder fOrder) : + column(nColumn), order(fOrder) {} + bool operator()(const CCombinedBan& left, const CCombinedBan& right) const; + +private: + int column; + Qt::SortOrder order; +}; + /** Qt model providing information about connected peers, similar to the "getpeerinfo" RPC call. Used by the rpc console UI. @@ -33,7 +45,7 @@ public: enum ColumnIndex { Address = 0, - Bantime = 1, + Bantime = 1 }; /** @name Methods overridden from QAbstractTableModel From b1189cfa105da414d8645f7284c16a443a710cfe Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 3 Jul 2015 08:35:14 +0200 Subject: [PATCH 15/20] [Qt] adapt QT ban option to banlist.dat changes --- src/qt/bantablemodel.cpp | 10 +++++----- src/qt/bantablemodel.h | 2 +- src/qt/forms/rpcconsole.ui | 2 +- src/qt/rpcconsole.cpp | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index 04840b052..42542371e 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -27,7 +27,7 @@ bool BannedNodeLessThan::operator()(const CCombinedBan& left, const CCombinedBan case BanTableModel::Address: return pLeft->subnet.ToString().compare(pRight->subnet.ToString()) < 0; case BanTableModel::Bantime: - return pLeft->bantil < pRight->bantil; + return pLeft->banEntry.nBanUntil < pRight->banEntry.nBanUntil; } return false; @@ -47,18 +47,18 @@ public: /** Pull a full list of banned nodes from CNode into our cache */ void refreshBanlist() { - std::map banMap; + banmap_t banMap; CNode::GetBanned(banMap); cachedBanlist.clear(); #if QT_VERSION >= 0x040700 cachedBanlist.reserve(banMap.size()); #endif - foreach (const PAIRTYPE(CSubNet, int64_t)& banentry, banMap) + foreach (const PAIRTYPE(CSubNet, CBanEntry)& banentry, banMap) { CCombinedBan banEntry; banEntry.subnet = banentry.first; - banEntry.bantil = banentry.second; + banEntry.banEntry = banentry.second; cachedBanlist.append(banEntry); } @@ -120,7 +120,7 @@ QVariant BanTableModel::data(const QModelIndex &index, int role) const return QString::fromStdString(rec->subnet.ToString()); case Bantime: QDateTime date = QDateTime::fromMSecsSinceEpoch(0); - date = date.addSecs(rec->bantil); + date = date.addSecs(rec->banEntry.nBanUntil); return date.toString(Qt::SystemLocaleLongDate); } } diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h index ec93ed101..09eb468fb 100644 --- a/src/qt/bantablemodel.h +++ b/src/qt/bantablemodel.h @@ -15,7 +15,7 @@ class BanTablePriv; struct CCombinedBan { CSubNet subnet; - int64_t bantil; + CBanEntry banEntry; }; class BannedNodeLessThan diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index c920e6130..4117da57f 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -768,7 +768,7 @@ true - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + Qt::NoTextInteraction diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index c417ec3f3..b224d8918 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -356,10 +356,10 @@ void RPCConsole::setClientModel(ClientModel *model) // create peer table context menu actions QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this); - QAction* banAction1h = new QAction(tr("&Ban Node for") + " " + tr("&1 hour"), this); - QAction* banAction24h = new QAction(tr("&Ban Node for") + " " + tr("&24 hours"), this); - QAction* banAction7d = new QAction(tr("&Ban Node for") + " " + tr("&7 days"), this); - QAction* banAction365d = new QAction(tr("&Ban Node for") + " " + tr("&1 year"), this); + QAction* banAction1h = new QAction(tr("Ban Node for") + " " + tr("1 hour"), this); + QAction* banAction24h = new QAction(tr("Ban Node for") + " " + tr("24 hours"), this); + QAction* banAction7d = new QAction(tr("Ban Node for") + " " + tr("7 days"), this); + QAction* banAction365d = new QAction(tr("Ban Node for") + " " + tr("1 year"), this); // create peer table context menu peersTableContextMenu = new QMenu(); @@ -806,7 +806,7 @@ void RPCConsole::banSelectedNode(int bantime) int port = 0; SplitHostPort(nStr, port, addr); - CNode::Ban(CNetAddr(addr), bantime); + CNode::Ban(CNetAddr(addr), BanReasonManuallyAdded, bantime); bannedNode->fDisconnect = true; clearSelectedNode(); From be8929265f0aa10c071e3efbfd20bfb4754ca543 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 3 Jul 2015 08:55:22 +0200 Subject: [PATCH 16/20] [Qt] reenabling hotkeys for ban context menu, use different words - 1 (h)our - 1 (d)ay - 1 (w)eek - 1 (y)ear --- src/qt/rpcconsole.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index b224d8918..ae89ccf12 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -356,10 +356,10 @@ void RPCConsole::setClientModel(ClientModel *model) // create peer table context menu actions QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this); - QAction* banAction1h = new QAction(tr("Ban Node for") + " " + tr("1 hour"), this); - QAction* banAction24h = new QAction(tr("Ban Node for") + " " + tr("24 hours"), this); - QAction* banAction7d = new QAction(tr("Ban Node for") + " " + tr("7 days"), this); - QAction* banAction365d = new QAction(tr("Ban Node for") + " " + tr("1 year"), this); + QAction* banAction1h = new QAction(tr("Ban Node for") + " " + tr("1 &hour"), this); + QAction* banAction24h = new QAction(tr("Ban Node for") + " " + tr("1 &day"), this); + QAction* banAction7d = new QAction(tr("Ban Node for") + " " + tr("1 &week"), this); + QAction* banAction365d = new QAction(tr("Ban Node for") + " " + tr("1 &year"), this); // create peer table context menu peersTableContextMenu = new QMenu(); From 4ed05101f32c629008f7f962eb988e8078863fed Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Fri, 3 Jul 2015 09:00:47 +0200 Subject: [PATCH 17/20] [Qt] call DumpBanlist() when baning unbaning nodes - this matches RPC call behaviour --- src/qt/rpcconsole.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index ae89ccf12..4dc976028 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -807,6 +807,7 @@ void RPCConsole::banSelectedNode(int bantime) SplitHostPort(nStr, port, addr); CNode::Ban(CNetAddr(addr), BanReasonManuallyAdded, bantime); + DumpBanlist(); // store banlist to disk bannedNode->fDisconnect = true; clearSelectedNode(); @@ -826,6 +827,7 @@ void RPCConsole::unbanSelectedNode() if (possibleSubnet.IsValid()) { CNode::Unban(possibleSubnet); + DumpBanlist(); // store banlist to disk clientModel->getBanTableModel()->refresh(); } } From 07f70b2dde26ef2b8857642043b149ff23f59a5c Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sun, 5 Jul 2015 15:44:22 +0200 Subject: [PATCH 18/20] [QA] fix netbase tests because of new CSubNet::ToString() output --- qa/rpc-tests/nodehandling.py | 8 ++++---- src/test/netbase_tests.cpp | 6 ++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/qa/rpc-tests/nodehandling.py b/qa/rpc-tests/nodehandling.py index d89cfcf59..e383a3a12 100755 --- a/qa/rpc-tests/nodehandling.py +++ b/qa/rpc-tests/nodehandling.py @@ -55,7 +55,7 @@ class NodeHandlingTest (BitcoinTestFramework): self.nodes[2].setban("192.168.0.1", "add", 1) #ban for 1 seconds self.nodes[2].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) #ban for 1000 seconds listBeforeShutdown = self.nodes[2].listbanned(); - assert_equal("192.168.0.1/255.255.255.255", listBeforeShutdown[2]['address']) #must be here + assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address']) #must be here time.sleep(2) #make 100% sure we expired 192.168.0.1 node time #stop node @@ -63,9 +63,9 @@ class NodeHandlingTest (BitcoinTestFramework): self.nodes[2] = start_node(2, self.options.tmpdir) listAfterShutdown = self.nodes[2].listbanned(); - assert_equal("127.0.0.0/255.255.255.0", listAfterShutdown[0]['address']) - assert_equal("127.0.0.0/255.255.255.255", listAfterShutdown[1]['address']) - assert_equal("2001:4000::/ffff:e000:0:0:0:0:0:0", listAfterShutdown[2]['address']) + assert_equal("127.0.0.0/24", listAfterShutdown[0]['address']) + assert_equal("127.0.0.0/32", listAfterShutdown[1]['address']) + assert_equal("/19" in listAfterShutdown[2]['address'], True) ########################### # RPC disconnectnode test # diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 8e853cc28..b1ef0ed24 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -149,12 +149,12 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).IsValid()); BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).Match(CNetAddr("127.0.0.1"))); BOOST_CHECK(!CSubNet(CNetAddr("127.0.0.1")).Match(CNetAddr("127.0.0.2"))); - BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).ToString() == "127.0.0.1/255.255.255.255"); + BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).ToString() == "127.0.0.1/32"); BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).IsValid()); BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:8"))); BOOST_CHECK(!CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:9"))); - BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/128"); CSubNet subnet = CSubNet("1.2.3.4/255.255.255.255"); BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32"); @@ -233,8 +233,6 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/255.255.232.0"); subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f"); BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f"); - subnet = CSubNet("1:2:3:4:5:6:7:8/fff:ffff:ffff:ffff:ffff:ffff:ffff:fff0"); - BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:0/fff:ffff:ffff:ffff:ffff:ffff:ffff:fff0"); } BOOST_AUTO_TEST_CASE(netbase_getgroup) From 7f90ea78cb68c60408df85d5c653257dbc9160fe Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 29 Jul 2015 14:34:14 +0200 Subject: [PATCH 19/20] [QA] adabt QT_NO_KEYWORDS for QT ban implementation --- src/qt/bantablemodel.cpp | 10 +++++----- src/qt/bantablemodel.h | 2 +- src/qt/rpcconsole.cpp | 5 ++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index 42542371e..33792af5b 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -54,11 +54,11 @@ public: #if QT_VERSION >= 0x040700 cachedBanlist.reserve(banMap.size()); #endif - foreach (const PAIRTYPE(CSubNet, CBanEntry)& banentry, banMap) + for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++) { CCombinedBan banEntry; - banEntry.subnet = banentry.first; - banEntry.banEntry = banentry.second; + banEntry.subnet = (*it).first; + banEntry.banEntry = (*it).second; cachedBanlist.append(banEntry); } @@ -161,9 +161,9 @@ QModelIndex BanTableModel::index(int row, int column, const QModelIndex &parent) void BanTableModel::refresh() { - emit layoutAboutToBeChanged(); + Q_EMIT layoutAboutToBeChanged(); priv->refreshBanlist(); - emit layoutChanged(); + Q_EMIT layoutChanged(); } void BanTableModel::sort(int column, Qt::SortOrder order) diff --git a/src/qt/bantablemodel.h b/src/qt/bantablemodel.h index 09eb468fb..c21dd04e3 100644 --- a/src/qt/bantablemodel.h +++ b/src/qt/bantablemodel.h @@ -60,7 +60,7 @@ public: bool shouldShow(); /*@}*/ -public slots: +public Q_SLOTS: void refresh(); private: diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 4dc976028..b3c28eab8 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -242,7 +243,7 @@ RPCConsole::RPCConsole(const PlatformStyle *platformStyle, QWidget *parent) : clientModel(0), historyPtr(0), cachedNodeid(-1), - platformStyle(platformStyle) + platformStyle(platformStyle), peersTableContextMenu(0), banTableContextMenu(0) { @@ -807,7 +808,6 @@ void RPCConsole::banSelectedNode(int bantime) SplitHostPort(nStr, port, addr); CNode::Ban(CNetAddr(addr), BanReasonManuallyAdded, bantime); - DumpBanlist(); // store banlist to disk bannedNode->fDisconnect = true; clearSelectedNode(); @@ -827,7 +827,6 @@ void RPCConsole::unbanSelectedNode() if (possibleSubnet.IsValid()) { CNode::Unban(possibleSubnet); - DumpBanlist(); // store banlist to disk clientModel->getBanTableModel()->refresh(); } } From 7aac6db6eb6b54da62d5eaafe7f14585ea1ea34d Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Sun, 20 Sep 2015 10:42:35 +0200 Subject: [PATCH 20/20] [QT] dump banlist to disk in case of ban/unban over QT --- src/qt/rpcconsole.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index b3c28eab8..9603a26c6 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -809,6 +809,7 @@ void RPCConsole::banSelectedNode(int bantime) CNode::Ban(CNetAddr(addr), BanReasonManuallyAdded, bantime); bannedNode->fDisconnect = true; + DumpBanlist(); clearSelectedNode(); clientModel->getBanTableModel()->refresh(); @@ -827,6 +828,7 @@ void RPCConsole::unbanSelectedNode() if (possibleSubnet.IsValid()) { CNode::Unban(possibleSubnet); + DumpBanlist(); clientModel->getBanTableModel()->refresh(); } }