Merge pull request #6315
7aac6db
[QT] dump banlist to disk in case of ban/unban over QT (Jonas Schnelli)7f90ea7
[QA] adabt QT_NO_KEYWORDS for QT ban implementation (Jonas Schnelli)07f70b2
[QA] fix netbase tests because of new CSubNet::ToString() output (Jonas Schnelli)4ed0510
[Qt] call DumpBanlist() when baning unbaning nodes (Philip Kaufmann)be89292
[Qt] reenabling hotkeys for ban context menu, use different words (Jonas Schnelli)b1189cf
[Qt] adapt QT ban option to banlist.dat changes (Jonas Schnelli)65abe91
[Qt] add sorting for bantable (Philip Kaufmann)51654de
[Qt] bantable polish (Philip Kaufmann)cdd72cd
[Qt] simplify ban list signal handling (Philip Kaufmann)43c1f5b
[Qt] remove unused timer-code from banlistmodel.cpp (Jonas Schnelli)e2b8028
net: Fix CIDR notation in ToString() (Wladimir J. van der Laan)9e521c1
[Qt] polish ban table (Philip Kaufmann)607809f
net: use CIDR notation in CSubNet::ToString() (Jonas Schnelli)53caec6
[Qt] bantable overhaul (Jonas Schnelli)f0bcbc4
[Qt] bantable fix timestamp 64bit issue (Jonas Schnelli)6135309
[Qt] banlist, UI optimizing and better signal handling (Jonas Schnelli)770ca79
[Qt] add context menu with unban option to ban table (Jonas Schnelli)5f42132
[Qt] add ui signal for banlist changes (Jonas Schnelli)ad204df
[Qt] add banlist table below peers table (Jonas Schnelli)50f0908
[Qt] add ban functions to peers window (Jonas Schnelli)
This commit is contained in:
commit
e59d2a80f9
@ -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 #
|
||||
|
@ -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 \
|
||||
|
@ -1311,17 +1311,57 @@ 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
|
||||
{
|
||||
/* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */
|
||||
int cidr = 0;
|
||||
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;
|
||||
}
|
||||
for (; n < 16 && valid_cidr; ++n)
|
||||
if (netmask[n] != 0x00)
|
||||
valid_cidr = false;
|
||||
|
||||
/* Format output */
|
||||
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]);
|
||||
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;
|
||||
}
|
||||
|
||||
|
181
src/qt/bantablemodel.cpp
Normal file
181
src/qt/bantablemodel.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
// 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 "sync.h"
|
||||
#include "utiltime.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QList>
|
||||
|
||||
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->banEntry.nBanUntil < pRight->banEntry.nBanUntil;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// private implementation
|
||||
class BanTablePriv
|
||||
{
|
||||
public:
|
||||
/** Local cache of peer information */
|
||||
QList<CCombinedBan> 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()
|
||||
{
|
||||
banmap_t banMap;
|
||||
CNode::GetBanned(banMap);
|
||||
|
||||
cachedBanlist.clear();
|
||||
#if QT_VERSION >= 0x040700
|
||||
cachedBanlist.reserve(banMap.size());
|
||||
#endif
|
||||
for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++)
|
||||
{
|
||||
CCombinedBan banEntry;
|
||||
banEntry.subnet = (*it).first;
|
||||
banEntry.banEntry = (*it).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
|
||||
{
|
||||
return cachedBanlist.size();
|
||||
}
|
||||
|
||||
CCombinedBan *index(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx < cachedBanlist.size())
|
||||
return &cachedBanlist[idx];
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
BanTableModel::BanTableModel(ClientModel *parent) :
|
||||
QAbstractTableModel(parent),
|
||||
clientModel(parent)
|
||||
{
|
||||
columns << tr("IP/Netmask") << tr("Banned Until");
|
||||
priv = new BanTablePriv();
|
||||
// default to unsorted
|
||||
priv->sortColumn = -1;
|
||||
|
||||
// load initial data
|
||||
refresh();
|
||||
}
|
||||
|
||||
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<CCombinedBan*>(index.internalPointer());
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch(index.column())
|
||||
{
|
||||
case Address:
|
||||
return QString::fromStdString(rec->subnet.ToString());
|
||||
case Bantime:
|
||||
QDateTime date = QDateTime::fromMSecsSinceEpoch(0);
|
||||
date = date.addSecs(rec->banEntry.nBanUntil);
|
||||
return date.toString(Qt::SystemLocaleLongDate);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
void BanTableModel::refresh()
|
||||
{
|
||||
Q_EMIT layoutAboutToBeChanged();
|
||||
priv->refreshBanlist();
|
||||
Q_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;
|
||||
}
|
72
src/qt/bantablemodel.h
Normal file
72
src/qt/bantablemodel.h
Normal file
@ -0,0 +1,72 @@
|
||||
// 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 "net.h"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QStringList>
|
||||
|
||||
class ClientModel;
|
||||
class BanTablePriv;
|
||||
|
||||
struct CCombinedBan {
|
||||
CSubNet subnet;
|
||||
CBanEntry banEntry;
|
||||
};
|
||||
|
||||
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.
|
||||
*/
|
||||
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 Q_SLOTS:
|
||||
void refresh();
|
||||
|
||||
private:
|
||||
ClientModel *clientModel;
|
||||
QStringList columns;
|
||||
BanTablePriv *priv;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_QT_BANTABLEMODEL_H
|
@ -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)
|
||||
{
|
||||
@ -230,12 +243,19 @@ static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, Ch
|
||||
Q_ARG(int, status));
|
||||
}
|
||||
|
||||
static void BannedListChanged(ClientModel *clientmodel)
|
||||
{
|
||||
qDebug() << QString("%1: Requesting update for peer banlist").arg(__func__);
|
||||
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()
|
||||
@ -244,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));
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <QDateTime>
|
||||
|
||||
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
|
||||
|
@ -713,17 +713,85 @@
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0" rowspan="2">
|
||||
<widget class="QTableView" name="peerWidget">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_101">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<item>
|
||||
<widget class="QTableView" name="peerWidget">
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="banHeading">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Banned peers</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::NoTextInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="banlistWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="peerHeading">
|
||||
|
@ -5,9 +5,11 @@
|
||||
#include "rpcconsole.h"
|
||||
#include "ui_rpcconsole.h"
|
||||
|
||||
#include "bantablemodel.h"
|
||||
#include "clientmodel.h"
|
||||
#include "guiutil.h"
|
||||
#include "platformstyle.h"
|
||||
#include "bantablemodel.h"
|
||||
|
||||
#include "chainparams.h"
|
||||
#include "rpcserver.h"
|
||||
@ -25,6 +27,7 @@
|
||||
#include <QKeyEvent>
|
||||
#include <QMenu>
|
||||
#include <QScrollBar>
|
||||
#include <QSignalMapper>
|
||||
#include <QThread>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
@ -240,8 +243,9 @@ RPCConsole::RPCConsole(const PlatformStyle *platformStyle, QWidget *parent) :
|
||||
clientModel(0),
|
||||
historyPtr(0),
|
||||
cachedNodeid(-1),
|
||||
contextMenu(0),
|
||||
platformStyle(platformStyle)
|
||||
platformStyle(platformStyle),
|
||||
peersTableContextMenu(0),
|
||||
banTableContextMenu(0)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
GUIUtil::restoreWindowGeometry("nRPCConsoleWindow", this->size(), this);
|
||||
@ -328,8 +332,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)));
|
||||
@ -350,23 +353,75 @@ 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()->setStretchLastSection(true);
|
||||
|
||||
// create context menu actions
|
||||
// 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("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 context menu
|
||||
contextMenu = new QMenu();
|
||||
contextMenu->addAction(disconnectAction);
|
||||
// create peer table context menu
|
||||
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&)));
|
||||
// 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);
|
||||
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)));
|
||||
|
||||
// peer table context menu signals
|
||||
connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showPeersTableContextMenu(const QPoint&)));
|
||||
connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode()));
|
||||
|
||||
// connect the peerWidget selection model to our peerSelected() handler
|
||||
// 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->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
|
||||
QAction* unbanAction = new QAction(tr("&Unban Node"), this);
|
||||
|
||||
// create ban table context menu
|
||||
banTableContextMenu = new QMenu();
|
||||
banTableContextMenu->addAction(unbanAction);
|
||||
|
||||
// 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());
|
||||
@ -576,7 +631,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());
|
||||
@ -586,7 +641,7 @@ void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelecti
|
||||
|
||||
void RPCConsole::peerLayoutChanged()
|
||||
{
|
||||
if (!clientModel)
|
||||
if (!clientModel || !clientModel->getPeerTableModel())
|
||||
return;
|
||||
|
||||
const CNodeCombinedStats *stats = NULL;
|
||||
@ -695,7 +750,7 @@ void RPCConsole::showEvent(QShowEvent *event)
|
||||
{
|
||||
QWidget::showEvent(event);
|
||||
|
||||
if (!clientModel)
|
||||
if (!clientModel || !clientModel->getPeerTableModel())
|
||||
return;
|
||||
|
||||
// start PeerTableModel auto refresh
|
||||
@ -706,18 +761,25 @@ void RPCConsole::hideEvent(QHideEvent *event)
|
||||
{
|
||||
QWidget::hideEvent(event);
|
||||
|
||||
if (!clientModel)
|
||||
if (!clientModel || !clientModel->getPeerTableModel())
|
||||
return;
|
||||
|
||||
// stop PeerTableModel auto refresh
|
||||
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()
|
||||
@ -731,6 +793,46 @@ 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
|
||||
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), BanReasonManuallyAdded, bantime);
|
||||
bannedNode->fDisconnect = true;
|
||||
DumpBanlist();
|
||||
|
||||
clearSelectedNode();
|
||||
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());
|
||||
|
||||
if (possibleSubnet.IsValid())
|
||||
{
|
||||
CNode::Unban(possibleSubnet);
|
||||
DumpBanlist();
|
||||
clientModel->getBanTableModel()->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void RPCConsole::clearSelectedNode()
|
||||
{
|
||||
ui->peerWidget->selectionModel()->clearSelection();
|
||||
@ -738,3 +840,13 @@ void RPCConsole::clearSelectedNode()
|
||||
ui->detailWidget->hide();
|
||||
ui->peerHeading->setText(tr("Select a peer to view detailed information."));
|
||||
}
|
||||
|
||||
void RPCConsole::showOrHideBanTableIfRequired()
|
||||
{
|
||||
if (!clientModel)
|
||||
return;
|
||||
|
||||
bool visible = clientModel->getBanTableModel()->shouldShow();
|
||||
ui->banlistWidget->setVisible(visible);
|
||||
ui->banHeading->setVisible(visible);
|
||||
}
|
@ -61,7 +61,13 @@ 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);
|
||||
/** Hides ban table if no bans are present */
|
||||
void showOrHideBanTableIfRequired();
|
||||
/** clear the selected node */
|
||||
void clearSelectedNode();
|
||||
|
||||
public Q_SLOTS:
|
||||
void clear();
|
||||
@ -80,6 +86,10 @@ 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);
|
||||
/** Unban a selected node on the Bans tab */
|
||||
void unbanSelectedNode();
|
||||
|
||||
Q_SIGNALS:
|
||||
// For RPC command executor
|
||||
@ -92,14 +102,15 @@ 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
|
||||
{
|
||||
ADDRESS_COLUMN_WIDTH = 200,
|
||||
SUBVERSION_COLUMN_WIDTH = 100,
|
||||
PING_COLUMN_WIDTH = 80
|
||||
PING_COLUMN_WIDTH = 80,
|
||||
BANSUBNET_COLUMN_WIDTH = 200,
|
||||
BANTIME_COLUMN_WIDTH = 250
|
||||
|
||||
};
|
||||
|
||||
Ui::RPCConsole *ui;
|
||||
@ -107,9 +118,10 @@ private:
|
||||
QStringList history;
|
||||
int historyPtr;
|
||||
NodeId cachedNodeid;
|
||||
QMenu *contextMenu;
|
||||
const PlatformStyle *platformStyle;
|
||||
RPCTimerInterface *rpcTimerInterface;
|
||||
QMenu *peersTableContextMenu;
|
||||
QMenu *banTableContextMenu;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_QT_RPCCONSOLE_H
|
||||
|
@ -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,7 @@ UniValue clearbanned(const UniValue& params, bool fHelp)
|
||||
|
||||
CNode::ClearBanned();
|
||||
DumpBanlist(); //store banlist to disk
|
||||
uiInterface.BannedListChanged();
|
||||
|
||||
return NullUniValue;
|
||||
}
|
||||
|
@ -149,12 +149,90 @@ 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");
|
||||
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");
|
||||
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");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(netbase_getgroup)
|
||||
|
@ -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()
|
||||
|
@ -95,6 +95,9 @@ public:
|
||||
|
||||
/** New block has been accepted */
|
||||
boost::signals2::signal<void (const uint256& hash)> NotifyBlockTip;
|
||||
|
||||
/** Banlist did change. */
|
||||
boost::signals2::signal<void (void)> BannedListChanged;
|
||||
};
|
||||
|
||||
extern CClientUIInterface uiInterface;
|
||||
|
Loading…
Reference in New Issue
Block a user