This adds 4 ban options to the peers tables context menu (1h, 24h, 7d, 365d). If there are active bans, a table with banned subnets will be shown.
Sync between the rpc bans and the ui bans are guaranteed over a new uiInterface
signal.
Screenshots:
This adds 4 ban options to the peers tables context menu (1h, 24h, 7d, 365d). If there are active bans, a table with banned subnets will be shown.
Sync between the rpc bans and the ui bans are guaranteed over a new uiInterface
signal.
Screenshots:
527@@ -527,6 +528,7 @@ UniValue setban(const UniValue& params, bool fHelp)
528 throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
529 }
530
531+ uiInterface.BannedListChanged();
uiInterface
?
118+ case Address:
119+ return QString::fromStdString(rec->subnet.ToString());
120+ case Bantime:
121+ //show time in users local timezone, not 64bit compatible!
122+ //TODO find a way to support 64bit timestamps
123+ boost::posix_time::ptime pt1 = boost::posix_time::from_time_t(rec->bantil);
boost::posix_time::from_time_t
is not 64bit capable. Maybe someone has a idea how to fix this.
What about QDateTime::fromTime_t()
?
QDateTime::fromTime_t(rec->bantil).toString()
didn’t test it…
QDateTime QDateTime::fromTime_t(uint seconds)
(uint!).
31+ Qt::SortOrder sortOrder;
32+
33+ /** Pull a full list of banned nodes from CNode into our cache */
34+ void refreshBanlist()
35+ {
36+ std::map<CSubNet, int64_t> banMap;
typedef
s are useful but can also make reading the code more complicate. In this case (simple map) i don’t see a usecase for a typedef.
39+ cachedBanlist.clear();
40+#if QT_VERSION >= 0x040700
41+ cachedBanlist.reserve(banMap.size());
42+#endif
43+ std::map<CSubNet, int64_t>::iterator iter;
44+ for (iter = banMap.begin(); iter != banMap.end(); ++iter) {
47+ banEntry.bantil = iter->second;
48+ cachedBanlist.append(banEntry);
49+ }
50+ }
51+
52+ int size()
int size() const
?
56+
57+ CCombinedBan *index(int idx)
58+ {
59+ if(idx >= 0 && idx < cachedBanlist.size()) {
60+ return &cachedBanlist[idx];
61+ } else {
QTableView
requests a row at index which is not in the cache QList
. Obviously it should not happen because the table size is driven by the size of the cache QList
. But I prefer keeping this.
126+ ss << pt2;
127+ return QString::fromStdString(ss.str());
128+ }
129+ } else if (role == Qt::TextAlignmentRole) {
130+ if (index.column() == Bantime)
131+ return (int)(Qt::AlignRight | Qt::AlignVCenter);
(QVariant)
which also works.
162+
163+ if (data)
164+ {
165+ return createIndex(row, column, data);
166+ }
167+ else
QModelIndex()
. I think it’s easier to read without else.
16+
17+QT_BEGIN_NAMESPACE
18+class QTimer;
19+QT_END_NAMESPACE
20+
21+struct CCombinedBan {
6+
7+#include "clientmodel.h"
8+#include "guiconstants.h"
9+#include "guiutil.h"
10+
11+#include "net.h"
312@@ -311,23 +313,66 @@ void RPCConsole::setClientModel(ClientModel *model)
313 ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH);
314 ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH);
315 ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH);
316+ ui->peerWidget->horizontalHeader()->setStretchLastSection(true);
317
318 // create context menu actions
319- QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this);
320+ QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this);
321+ QAction* banAction1h = new QAction(tr("&Ban Node for 1 hour"), this);
757+ std::string addr;
758+ int port = 0;
759+ SplitHostPort(nStr, port, addr);
760+
761+ CNode::Ban(CNetAddr(addr), bantime);
762+ bannedNode->CloseSocketDisconnect();
787@@ -699,3 +788,10 @@ void RPCConsole::clearSelectedNode()
788 ui->detailWidget->hide();
789 ui->peerHeading->setText(tr("Select a peer to view detailed information."));
790 }
791+
792+void RPCConsole::showOrHideBanTableIfRequired()
793+{
794+ bool visible = clientModel->getBanTableModel()->shouldShow();
122+ date = date.addSecs(rec->bantil);
123+ return date.toString(Qt::SystemLocaleLongDate);
124+ }
125+ } else if (role == Qt::TextAlignmentRole) {
126+ if (index.column() == Bantime)
127+ return (int)(Qt::AlignRight | Qt::AlignVCenter);
int
the right type here? I tried (QVariant)
which also works and is more the Qt style?
239@@ -226,12 +240,19 @@ static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, Ch
240 Q_ARG(int, status));
241 }
242
243+static void BannedListChanged(ClientModel *clientmodel)
244+{
245+ qDebug() << "BannedListChanged";
qDebug() << QString("%1: Requesting update for peer banlist").arg(__func__);
I intend to creat a pull to make use of that format so we have the debug logging include always the correct function name :).
7@@ -8,6 +8,7 @@
8 #include "clientmodel.h"
9 #include "guiutil.h"
10 #include "peertablemodel.h"
11+#include "bantablemodel.h"
336 // context menu signals
337- connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showMenu(const QPoint&)));
338+ connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showPeersTableContextMenu(const QPoint&)));
339 connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode()));
340
341+ //add a signal mapping to allow a dynamic argument
379@@ -335,6 +380,9 @@ void RPCConsole::setClientModel(ClientModel *model)
380 ui->startupTime->setText(model->formatClientStartupTime());
381
382 ui->networkName->setText(QString::fromStdString(Params().NetworkIDString()));
383+
384+ connect(model, SIGNAL(banListChanged()), this, SLOT(showOrHideBanTableIfRequired()));
Observations:
Edit:
There is also an issue with removing a peer from banned peers list when banned until is over:
The peer should be removed from the list, which is not working currently.
listbanned also still shows them: [ { “address”: “127.0.0.1/255.255.255.255”, “banned_untill”: 1434891295 }, { “address”: “nkf5e6b7pl4jfd4a.onion/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff”, “banned_untill”: 1434891291 }, { “address”: “t6xj6wilh4ytvcs7.onion/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff”, “banned_untill”: 1434891400 } ]
@Diapolo: for autocleaning then ban list see PR #6310
I think you point 1) is not a problem. The peer is still selected (gray) when you interact with the bantable. Point 2) and 3) are cosmetics and should not hold this PR back. Point 4) agreed.
Banning tor nodes needs testing (best first over RPC) and maybe needs more implementation. Would be good if you could see what’s missing there.
@jonasschnelli The problem are incoming Tor nodes with 127.0.0.1 blocking one connected node blocks any other incoming 127.0.0.1 node. Other connected 127.0.0.1 are not affected.
Also I’d suggest splitting of the autocleaning pull from the disk-store-pull as autocleaning is uncontroversial and also needed by this one.
I also disagree on ignoring UI or UX issues for now as often such “small” or “minor” things are just forgotton or I pick them up. I’d vote for making this pull good and not just “working okay” :).
Updated.
Added a commit that uses CIDR notation (like /32) when printing (ToString()
) CSubNet.
UI and RPC looks now like…
/x
, please pick the top commit from https://github.com/laanwj/bitcoin/tree/2015_06_cideriad
BannedListChanged
it makes it more complex and we don’t need it. We pull the list / refresh the list via timer that calls void BanTableModel::refresh()
anyway. Are you okay when I rework the signal handling to be easier?
@Diapolo: i extra added the signal to avoid a timer. For the peers list, a timer makes sense because we show recv/sent-bytes counters. The interval is 250ms (!). Poll updating through timers is a bad design IMO. Sometimes unavoidable.
Adding another timer (or use the same one) for the ban list would mean unnecessarily using CPU ticks.
Well placed signals/hocks allow a software to be extendable without creating unnecessary class coupling. I think we should not be to cautious we adding new signals.
Take a look at https://github.com/jonasschnelli/bitcoin/pull/5 IMHO this is not that bad and much easier flow-wise. We also don’t have any core signals for the normal peer list. @laanwj What do you think?
Perhaps a check could be added to verify we only pull a fresh list if the old one changed, that would reduce CPU ticks.
@Diapolo: i had a look at the PR and would prefer the current solution. Your solution would make generating a relatively static ban list every 250ms which need to go over a short locks of cs_setBanned
.
But don’t have a strong opinion on that.
bantablemodel.cpp | .h
.
The signaling approach over ClientModel is totally fine IMO. I would even say the complexity of the code is much higher with a timer than with a simple signal.
@Diapolo: Please stop improving this PR within this PR. It’s contra-productive. I can’t follow all your change requests and it might crushes down this PR. Some of your things are really cool (like the sorting). But you mix everything together and that makes it hard to read and distinct between useful and not useful changes.
Let stabilize this PR with searching and solving real problems. Once – and if – this is merge, you can PR your optimizations.
322- contextMenu = new QMenu();
323- contextMenu->addAction(disconnectAction);
324-
325- // context menu signals
326- connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showMenu(const QPoint&)));
327+ QAction* banAction1h = new QAction(tr("&Ban Node for") + " " + tr("&1 hour"), this);
I rechecked the code and during a translation for my build I came to this.
The &
is used as a shortcut when pressing ALT IMHO, so this will produce 2 shortcuts for every single menu entry. I’d suggest just removing them, because it will be hard to make them unique and still usable.
Edit: I can’t even access them on Windows… perhaps they are not wanted in context menus? What about Mac @jonasschnelli can you use these?
add ban option for peer context menu (1h, 24h, 7d, 1y).
- some code cleanups
- fix date formatting
- reduce header includes
Only use CIDR notation if the netmask can be represented as such.
- 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
- 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
- 1 (h)our
- 1 (d)ay
- 1 (w)eek
- 1 (y)ear
- this matches RPC call behaviour
Thank @luke-jr for the precise review. I think this sneaked in over a rebase because this PR started before the banlist was persisted to disk.
Just added a commit that re-implenents the DumpBanlist()
calls in case of banning/unbanning over QT.