Skip to content

Commit e59d2a8

Browse files
committed
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)
2 parents 28d0b3e + 7aac6db commit e59d2a8

14 files changed

+654
-56
lines changed

qa/rpc-tests/nodehandling.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,17 @@ def run_test(self):
5555
self.nodes[2].setban("192.168.0.1", "add", 1) #ban for 1 seconds
5656
self.nodes[2].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) #ban for 1000 seconds
5757
listBeforeShutdown = self.nodes[2].listbanned();
58-
assert_equal("192.168.0.1/255.255.255.255", listBeforeShutdown[2]['address']) #must be here
58+
assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address']) #must be here
5959
time.sleep(2) #make 100% sure we expired 192.168.0.1 node time
6060

6161
#stop node
6262
stop_node(self.nodes[2], 2)
6363

6464
self.nodes[2] = start_node(2, self.options.tmpdir)
6565
listAfterShutdown = self.nodes[2].listbanned();
66-
assert_equal("127.0.0.0/255.255.255.0", listAfterShutdown[0]['address'])
67-
assert_equal("127.0.0.0/255.255.255.255", listAfterShutdown[1]['address'])
68-
assert_equal("2001:4000::/ffff:e000:0:0:0:0:0:0", listAfterShutdown[2]['address'])
66+
assert_equal("127.0.0.0/24", listAfterShutdown[0]['address'])
67+
assert_equal("127.0.0.0/32", listAfterShutdown[1]['address'])
68+
assert_equal("/19" in listAfterShutdown[2]['address'], True)
6969

7070
###########################
7171
# RPC disconnectnode test #

src/Makefile.qt.include

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ QT_MOC_CPP = \
9797
qt/moc_addressbookpage.cpp \
9898
qt/moc_addresstablemodel.cpp \
9999
qt/moc_askpassphrasedialog.cpp \
100+
qt/moc_bantablemodel.cpp \
100101
qt/moc_bitcoinaddressvalidator.cpp \
101102
qt/moc_bitcoinamountfield.cpp \
102103
qt/moc_bitcoingui.cpp \
@@ -162,6 +163,7 @@ BITCOIN_QT_H = \
162163
qt/addressbookpage.h \
163164
qt/addresstablemodel.h \
164165
qt/askpassphrasedialog.h \
166+
qt/bantablemodel.h \
165167
qt/bitcoinaddressvalidator.h \
166168
qt/bitcoinamountfield.h \
167169
qt/bitcoingui.h \
@@ -260,6 +262,7 @@ RES_ICONS = \
260262
qt/res/icons/verify.png
261263

262264
BITCOIN_QT_CPP = \
265+
qt/bantablemodel.cpp \
263266
qt/bitcoinaddressvalidator.cpp \
264267
qt/bitcoinamountfield.cpp \
265268
qt/bitcoingui.cpp \

src/netbase.cpp

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,17 +1311,57 @@ bool CSubNet::Match(const CNetAddr &addr) const
13111311
return true;
13121312
}
13131313

1314+
static inline int NetmaskBits(uint8_t x)
1315+
{
1316+
switch(x) {
1317+
case 0x00: return 0; break;
1318+
case 0x80: return 1; break;
1319+
case 0xc0: return 2; break;
1320+
case 0xe0: return 3; break;
1321+
case 0xf0: return 4; break;
1322+
case 0xf8: return 5; break;
1323+
case 0xfc: return 6; break;
1324+
case 0xfe: return 7; break;
1325+
case 0xff: return 8; break;
1326+
default: return -1; break;
1327+
}
1328+
}
1329+
13141330
std::string CSubNet::ToString() const
13151331
{
1332+
/* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */
1333+
int cidr = 0;
1334+
bool valid_cidr = true;
1335+
int n = network.IsIPv4() ? 12 : 0;
1336+
for (; n < 16 && netmask[n] == 0xff; ++n)
1337+
cidr += 8;
1338+
if (n < 16) {
1339+
int bits = NetmaskBits(netmask[n]);
1340+
if (bits < 0)
1341+
valid_cidr = false;
1342+
else
1343+
cidr += bits;
1344+
++n;
1345+
}
1346+
for (; n < 16 && valid_cidr; ++n)
1347+
if (netmask[n] != 0x00)
1348+
valid_cidr = false;
1349+
1350+
/* Format output */
13161351
std::string strNetmask;
1317-
if (network.IsIPv4())
1318-
strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]);
1319-
else
1320-
strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
1321-
netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3],
1322-
netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7],
1323-
netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11],
1324-
netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]);
1352+
if (valid_cidr) {
1353+
strNetmask = strprintf("%u", cidr);
1354+
} else {
1355+
if (network.IsIPv4())
1356+
strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]);
1357+
else
1358+
strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
1359+
netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3],
1360+
netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7],
1361+
netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11],
1362+
netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]);
1363+
}
1364+
13251365
return network.ToString() + "/" + strNetmask;
13261366
}
13271367

src/qt/bantablemodel.cpp

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
// Copyright (c) 2011-2015 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include "bantablemodel.h"
6+
7+
#include "clientmodel.h"
8+
#include "guiconstants.h"
9+
#include "guiutil.h"
10+
11+
#include "sync.h"
12+
#include "utiltime.h"
13+
14+
#include <QDebug>
15+
#include <QList>
16+
17+
bool BannedNodeLessThan::operator()(const CCombinedBan& left, const CCombinedBan& right) const
18+
{
19+
const CCombinedBan* pLeft = &left;
20+
const CCombinedBan* pRight = &right;
21+
22+
if (order == Qt::DescendingOrder)
23+
std::swap(pLeft, pRight);
24+
25+
switch(column)
26+
{
27+
case BanTableModel::Address:
28+
return pLeft->subnet.ToString().compare(pRight->subnet.ToString()) < 0;
29+
case BanTableModel::Bantime:
30+
return pLeft->banEntry.nBanUntil < pRight->banEntry.nBanUntil;
31+
}
32+
33+
return false;
34+
}
35+
36+
// private implementation
37+
class BanTablePriv
38+
{
39+
public:
40+
/** Local cache of peer information */
41+
QList<CCombinedBan> cachedBanlist;
42+
/** Column to sort nodes by */
43+
int sortColumn;
44+
/** Order (ascending or descending) to sort nodes by */
45+
Qt::SortOrder sortOrder;
46+
47+
/** Pull a full list of banned nodes from CNode into our cache */
48+
void refreshBanlist()
49+
{
50+
banmap_t banMap;
51+
CNode::GetBanned(banMap);
52+
53+
cachedBanlist.clear();
54+
#if QT_VERSION >= 0x040700
55+
cachedBanlist.reserve(banMap.size());
56+
#endif
57+
for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++)
58+
{
59+
CCombinedBan banEntry;
60+
banEntry.subnet = (*it).first;
61+
banEntry.banEntry = (*it).second;
62+
cachedBanlist.append(banEntry);
63+
}
64+
65+
if (sortColumn >= 0)
66+
// sort cachedBanlist (use stable sort to prevent rows jumping around unneceesarily)
67+
qStableSort(cachedBanlist.begin(), cachedBanlist.end(), BannedNodeLessThan(sortColumn, sortOrder));
68+
}
69+
70+
int size() const
71+
{
72+
return cachedBanlist.size();
73+
}
74+
75+
CCombinedBan *index(int idx)
76+
{
77+
if (idx >= 0 && idx < cachedBanlist.size())
78+
return &cachedBanlist[idx];
79+
80+
return 0;
81+
}
82+
};
83+
84+
BanTableModel::BanTableModel(ClientModel *parent) :
85+
QAbstractTableModel(parent),
86+
clientModel(parent)
87+
{
88+
columns << tr("IP/Netmask") << tr("Banned Until");
89+
priv = new BanTablePriv();
90+
// default to unsorted
91+
priv->sortColumn = -1;
92+
93+
// load initial data
94+
refresh();
95+
}
96+
97+
int BanTableModel::rowCount(const QModelIndex &parent) const
98+
{
99+
Q_UNUSED(parent);
100+
return priv->size();
101+
}
102+
103+
int BanTableModel::columnCount(const QModelIndex &parent) const
104+
{
105+
Q_UNUSED(parent);
106+
return columns.length();;
107+
}
108+
109+
QVariant BanTableModel::data(const QModelIndex &index, int role) const
110+
{
111+
if(!index.isValid())
112+
return QVariant();
113+
114+
CCombinedBan *rec = static_cast<CCombinedBan*>(index.internalPointer());
115+
116+
if (role == Qt::DisplayRole) {
117+
switch(index.column())
118+
{
119+
case Address:
120+
return QString::fromStdString(rec->subnet.ToString());
121+
case Bantime:
122+
QDateTime date = QDateTime::fromMSecsSinceEpoch(0);
123+
date = date.addSecs(rec->banEntry.nBanUntil);
124+
return date.toString(Qt::SystemLocaleLongDate);
125+
}
126+
}
127+
128+
return QVariant();
129+
}
130+
131+
QVariant BanTableModel::headerData(int section, Qt::Orientation orientation, int role) const
132+
{
133+
if(orientation == Qt::Horizontal)
134+
{
135+
if(role == Qt::DisplayRole && section < columns.size())
136+
{
137+
return columns[section];
138+
}
139+
}
140+
return QVariant();
141+
}
142+
143+
Qt::ItemFlags BanTableModel::flags(const QModelIndex &index) const
144+
{
145+
if(!index.isValid())
146+
return 0;
147+
148+
Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
149+
return retval;
150+
}
151+
152+
QModelIndex BanTableModel::index(int row, int column, const QModelIndex &parent) const
153+
{
154+
Q_UNUSED(parent);
155+
CCombinedBan *data = priv->index(row);
156+
157+
if (data)
158+
return createIndex(row, column, data);
159+
return QModelIndex();
160+
}
161+
162+
void BanTableModel::refresh()
163+
{
164+
Q_EMIT layoutAboutToBeChanged();
165+
priv->refreshBanlist();
166+
Q_EMIT layoutChanged();
167+
}
168+
169+
void BanTableModel::sort(int column, Qt::SortOrder order)
170+
{
171+
priv->sortColumn = column;
172+
priv->sortOrder = order;
173+
refresh();
174+
}
175+
176+
bool BanTableModel::shouldShow()
177+
{
178+
if (priv->size() > 0)
179+
return true;
180+
return false;
181+
}

src/qt/bantablemodel.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright (c) 2011-2013 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_QT_BANTABLEMODEL_H
6+
#define BITCOIN_QT_BANTABLEMODEL_H
7+
8+
#include "net.h"
9+
10+
#include <QAbstractTableModel>
11+
#include <QStringList>
12+
13+
class ClientModel;
14+
class BanTablePriv;
15+
16+
struct CCombinedBan {
17+
CSubNet subnet;
18+
CBanEntry banEntry;
19+
};
20+
21+
class BannedNodeLessThan
22+
{
23+
public:
24+
BannedNodeLessThan(int nColumn, Qt::SortOrder fOrder) :
25+
column(nColumn), order(fOrder) {}
26+
bool operator()(const CCombinedBan& left, const CCombinedBan& right) const;
27+
28+
private:
29+
int column;
30+
Qt::SortOrder order;
31+
};
32+
33+
/**
34+
Qt model providing information about connected peers, similar to the
35+
"getpeerinfo" RPC call. Used by the rpc console UI.
36+
*/
37+
class BanTableModel : public QAbstractTableModel
38+
{
39+
Q_OBJECT
40+
41+
public:
42+
explicit BanTableModel(ClientModel *parent = 0);
43+
void startAutoRefresh();
44+
void stopAutoRefresh();
45+
46+
enum ColumnIndex {
47+
Address = 0,
48+
Bantime = 1
49+
};
50+
51+
/** @name Methods overridden from QAbstractTableModel
52+
@{*/
53+
int rowCount(const QModelIndex &parent) const;
54+
int columnCount(const QModelIndex &parent) const;
55+
QVariant data(const QModelIndex &index, int role) const;
56+
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
57+
QModelIndex index(int row, int column, const QModelIndex &parent) const;
58+
Qt::ItemFlags flags(const QModelIndex &index) const;
59+
void sort(int column, Qt::SortOrder order);
60+
bool shouldShow();
61+
/*@}*/
62+
63+
public Q_SLOTS:
64+
void refresh();
65+
66+
private:
67+
ClientModel *clientModel;
68+
QStringList columns;
69+
BanTablePriv *priv;
70+
};
71+
72+
#endif // BITCOIN_QT_BANTABLEMODEL_H

0 commit comments

Comments
 (0)