Network peer updates

-Added a new port_filter setting to the 3 network_page tables which allows showing only results from peers on the selected port
-Added a new hide_protocols setting to the 3 network_page tables which allows hiding results from peers on the selected protocols
-Added a Port column to the data table on the Network page Connections tab
-The data table on the Network page Connections tab is now sortable
-The peer sync now refreshes data for peers that existed since last sync
-Adding and updating peers now displays the port # in the log output
-The /ext/getnetworkpeers api is now sorted by ip4/ip6, address and port which also means all data on the Network page is sorted this way by default as well
-The /ext/getnetworkpeers api no longer requires the internal argument for calls originating from the Network page
-The Network page now only makes a single call to the /ext/getnetworkpeers api instead of 3 calls
-The find_peer and drop_peer functions now requiresa port to distinguish between multiple connections to the same peer on different ports
This commit is contained in:
Joe Uhren
2022-07-01 21:11:57 -06:00
parent fb5ce795fa
commit 8fa337f6f9
6 changed files with 245 additions and 151 deletions
+15 -15
View File
@@ -505,13 +505,6 @@ app.use('/ext/getsummary', function(req, res) {
app.use('/ext/getnetworkpeers', function(req, res) {
// check if the getnetworkpeers api is enabled or else check the headers to see if it matches an internal ajax request from the explorer itself (TODO: come up with a more secure method of whitelisting ajax calls from the explorer)
if ((settings.api_page.enabled == true && settings.api_page.public_apis.ext.getnetworkpeers.enabled == true) || (req.headers['x-requested-with'] != null && req.headers['x-requested-with'].toLowerCase() == 'xmlhttprequest' && req.headers.referer != null && req.headers.accept.indexOf('text/javascript') > -1 && req.headers.accept.indexOf('application/json') > -1)) {
var internal = false;
// split url suffix by forward slash and remove blank entries
var split = req.url.split('/').filter(function(v) { return v; });
// check if this is an internal request
if (split.length > 0 && split[0].indexOf('internal') > -1)
internal = true;
// get list of peers
db.get_peers(function(peers) {
// loop through peers list and remove the mongo _id and __v keys
@@ -520,14 +513,21 @@ app.use('/ext/getnetworkpeers', function(req, res) {
delete peers[i]['_doc']['__v'];
}
// check if this is an internal request
if (internal) {
// display data formatted for internal datatable
res.json({"data": peers});
} else {
// display data in more readable format for public api
res.json(peers);
}
// sort ip6 addresses to the bottom
peers.sort(function(a, b) {
var address1 = a.address.indexOf(':') > -1;
var address2 = b.address.indexOf(':') > -1;
if (address1 < address2)
return -1;
else if (address1 > address2)
return 1;
else
return 0;
});
// return peer data
res.json(peers);
});
} else
res.end('This method is disabled');
+5 -5
View File
@@ -1242,8 +1242,8 @@ module.exports = {
});
},
find_peer: function(address, cb) {
Peers.findOne({address: address}, function(err, peer) {
find_peer: function(address, port, cb) {
Peers.findOne({address: address, port: port}, function(err, peer) {
if (err)
return cb(null);
else {
@@ -1255,8 +1255,8 @@ module.exports = {
});
},
drop_peer: function(address, cb) {
Peers.deleteOne({address: address}, function(err) {
drop_peer: function(address, port, cb) {
Peers.deleteOne({address: address, port: port}, function(err) {
if (err) {
console.log(err);
return cb();
@@ -1276,7 +1276,7 @@ module.exports = {
},
get_peers: function(cb) {
Peers.find({}, function(err, peers) {
Peers.find().sort({address: 1, port: 1}).exec(function (err, peers) {
if (err)
return cb([]);
else
+24 -3
View File
@@ -618,7 +618,14 @@ exports.network_page = {
// page_length_options: An array of page length options that determine how many items/records to display in the table at any given time
"page_length_options": [ 10, 25, 50, 75, 100 ],
// items_per_page: The default amount of items/records to display in the table at any given time
"items_per_page": 10
"items_per_page": 10,
// port_filter: Specify a port number to only allow showing peers on the selected port.
// Set this value to 0 to show all peers on any port.
"port_filter": 0,
// hide_protocols: An array of protocol numbers that will be filtered out of the table results
// If a peer connects to the explorer wallet with one of these protocol numbers, that record will not be displayed in this table
// Add as many protocol values as necessary in the following format: [ 0, 70803, 70819 ]
"hide_protocols": [ ]
},
// addnodes_table: a collection of settings that pertain to the add nodes table on the network page
// Table data is populated via the /ext/getnetworkpeers api
@@ -626,7 +633,14 @@ exports.network_page = {
// page_length_options: An array of page length options that determine how many items/records to display in the table at any given time
"page_length_options": [ 10, 25, 50, 75, 100 ],
// items_per_page: The default amount of items/records to display in the table at any given time
"items_per_page": 10
"items_per_page": 10,
// port_filter: Specify a port number to only allow showing peers on the selected port.
// Set this value to 0 to show all peers on any port.
"port_filter": 0,
// hide_protocols: An array of protocol numbers that will be filtered out of the table results
// If a peer connects to the explorer wallet with one of these protocol numbers, that record will not be displayed in this table
// Add as many protocol values as necessary in the following format: [ 0, 70803, 70819 ]
"hide_protocols": [ ]
},
// onetry_table: a collection of settings that pertain to the one try table on the network page
// Table data is populated via the /ext/getnetworkpeers api
@@ -634,7 +648,14 @@ exports.network_page = {
// page_length_options: An array of page length options that determine how many items/records to display in the table at any given time
"page_length_options": [ 10, 25, 50, 75, 100 ],
// items_per_page: The default amount of items/records to display in the table at any given time
"items_per_page": 10
"items_per_page": 10,
// port_filter: Specify a port number to only allow showing peers on the selected port.
// Set this value to 0 to show all peers on any port.
"port_filter": 0,
// hide_protocols: An array of protocol numbers that will be filtered out of the table results
// If a peer connects to the explorer wallet with one of these protocol numbers, that record will not be displayed in this table
// Add as many protocol values as necessary in the following format: [ 0, 70803, 70819 ]
"hide_protocols": [ ]
}
};
+18 -5
View File
@@ -436,7 +436,7 @@ if (lib.is_locked([database]) == false) {
address = address.replace("[", "").replace("]", "");
}
db.find_peer(address, function(peer) {
db.find_peer(address, port, function(peer) {
if (peer) {
if ((peer['port'] != null && (isNaN(peer['port']) || peer['port'].length < 2)) || peer['country'].length < 1 || peer['country_code'].length < 1) {
db.drop_peers(function() {
@@ -445,9 +445,22 @@ if (lib.is_locked([database]) == false) {
});
}
// peer already exists
console.log('Updated peer %s [%s/%s]', address, (i + 1).toString(), body.length.toString());
loop.next();
// peer already exists and should be refreshed
// drop peer
db.drop_peer(address, port, function() {
// re-add the peer to refresh the data and extend the expiry date
db.create_peer({
address: address,
port: port,
protocol: peer.protocol,
version: peer.version,
country: peer.country,
country_code: peer.country_code
}, function() {
console.log('Updated peer %s:%s [%s/%s]', address, port.toString(), (i + 1).toString(), body.length.toString());
loop.next();
});
});
} else {
const rateLimitLib = require('../lib/ratelimit');
const rateLimit = new rateLimitLib.RateLimit(1, 2000, false);
@@ -471,7 +484,7 @@ if (lib.is_locked([database]) == false) {
country: geo.country_name,
country_code: geo.country_code
}, function() {
console.log('Added new peer %s [%s/%s]', address, (i + 1).toString(), body.length.toString());
console.log('Added new peer %s:%s [%s/%s]', address, port.toString(), (i + 1).toString(), body.length.toString());
loop.next();
});
}
+24 -3
View File
@@ -702,7 +702,14 @@
// page_length_options: An array of page length options that determine how many items/records to display in the table at any given time
"page_length_options": [ 10, 25, 50, 75, 100 ],
// items_per_page: The default amount of items/records to display in the table at any given time
"items_per_page": 10
"items_per_page": 10,
// port_filter: Specify a port number to only allow showing peers on the selected port.
// Set this value to 0 to show all peers on any port.
"port_filter": 0,
// hide_protocols: An array of protocol numbers that will be filtered out of the table results
// If a peer connects to the explorer wallet with one of these protocol numbers, that record will not be displayed in this table
// Add as many protocol values as necessary in the following format: [ 0, 70803, 70819 ]
"hide_protocols": [ ]
},
// addnodes_table: a collection of settings that pertain to the add nodes table on the network page
// Table data is populated via the /ext/getnetworkpeers api
@@ -710,7 +717,14 @@
// page_length_options: An array of page length options that determine how many items/records to display in the table at any given time
"page_length_options": [ 10, 25, 50, 75, 100 ],
// items_per_page: The default amount of items/records to display in the table at any given time
"items_per_page": 10
"items_per_page": 10,
// port_filter: Specify a port number to only allow showing peers on the selected port.
// Set this value to 0 to show all peers on any port.
"port_filter": 0,
// hide_protocols: An array of protocol numbers that will be filtered out of the table results
// If a peer connects to the explorer wallet with one of these protocol numbers, that record will not be displayed in this table
// Add as many protocol values as necessary in the following format: [ 0, 70803, 70819 ]
"hide_protocols": [ ]
},
// onetry_table: a collection of settings that pertain to the one try table on the network page
// Table data is populated via the /ext/getnetworkpeers api
@@ -718,7 +732,14 @@
// page_length_options: An array of page length options that determine how many items/records to display in the table at any given time
"page_length_options": [ 10, 25, 50, 75, 100 ],
// items_per_page: The default amount of items/records to display in the table at any given time
"items_per_page": 10
"items_per_page": 10,
// port_filter: Specify a port number to only allow showing peers on the selected port.
// Set this value to 0 to show all peers on any port.
"port_filter": 0,
// hide_protocols: An array of protocol numbers that will be filtered out of the table results
// If a peer connects to the explorer wallet with one of these protocol numbers, that record will not be displayed in this table
// Add as many protocol values as necessary in the following format: [ 0, 70803, 70819 ]
"hide_protocols": [ ]
}
},
+159 -120
View File
@@ -19,128 +19,166 @@ block content
return lengthMenuOpts;
}
$(document).ready(function() {
var setting_txPerPage = parseInt("#{settings.network_page.connections_table.items_per_page}");
$('#connections-table').dataTable({
autoWidth: true,
searching: false,
ordering: false,
responsive: true,
lengthChange: true,
processing: true,
iDisplayLength: setting_txPerPage,
lengthMenu: generateLengthMenu(setting_txPerPage, !{JSON.stringify(settings.network_page.connections_table.page_length_options)}),
scrollX: true,
language: {
paginate: {
previous: '<',
next: '>'
}
},
ajax: {
url: '/ext/getnetworkpeers/internal',
dataSrc: function (json) {
return json.data;
}
},
rowCallback: function (row, data, index) {
var flagBlock = '';
if (data['country_code'].length > 1) {
flagBlock = '<div class="margin-left-5 flag-icon flag-icon-'+data['country_code'].toLowerCase()+'"></div>';
}
$("td:eq(0)", row).html(data['address']).addClass('breakWord');
$("td:eq(1)", row).html(data['protocol']);
$("td:eq(2)", row).html(data['version']);
$("td:eq(3)", row).html(data['country']+flagBlock);
},
fnDrawCallback: function(settings) {
fixDataTableColumns();
fixFooterHeightAndPosition();
},
columns: [
{ data: 'address', width: '25%' },
{ data: 'protocol', width: '25%' },
{ data: 'version', width:'25%' },
{ data: 'country', width: '25%'}
]
$.ajax({
method: 'GET',
url: '/ext/getnetworkpeers/internal',
dataType: 'json'
}).done(function(peers) {
var setting_txPerPage = parseInt("#{settings.network_page.connections_table.items_per_page}");
var setting_con_port_filter = "#{settings.network_page.connections_table.port_filter}";
var setting_con_hide_protocols = !{JSON.stringify(settings.network_page.connections_table.hide_protocols)};
var connectionRows = peers;
if (setting_con_port_filter == null || setting_con_port_filter == '')
setting_con_port_filter = '0';
if (setting_con_port_filter != '0')
connectionRows = connectionRows.filter(v => v.port == setting_con_port_filter);
setting_con_hide_protocols.forEach(function (protocol) {
connectionRows = connectionRows.filter(v => v.protocol != protocol);
});
$('#connections-table').dataTable({
autoWidth: true,
searching: false,
ordering: true,
order: [],
responsive: true,
lengthChange: true,
processing: true,
iDisplayLength: setting_txPerPage,
lengthMenu: generateLengthMenu(setting_txPerPage, !{JSON.stringify(settings.network_page.connections_table.page_length_options)}),
scrollX: true,
language: {
paginate: {
previous: '<',
next: '>'
}
},
data: connectionRows,
rowCallback: function (row, data, index) {
var flagBlock = '';
if (data['country_code'].length > 1) {
flagBlock = '<div class="margin-left-5 flag-icon flag-icon-'+data['country_code'].toLowerCase()+'"></div>';
}
$("td:eq(0)", row).html(data['address']).addClass('breakWord');
$("td:eq(1)", row).html(data['port']);
$("td:eq(2)", row).html(data['protocol']);
$("td:eq(3)", row).html(data['version']);
$("td:eq(4)", row).html(data['country']+flagBlock);
},
fnDrawCallback: function(settings) {
fixDataTableColumns();
fixFooterHeightAndPosition();
},
columns: [
{ data: 'address', width: '20%' },
{ data: 'port', width: '20%' },
{ data: 'protocol', width: '20%' },
{ data: 'version', width:'20%' },
{ data: 'country', width: '20%'}
]
});
setting_txPerPage = parseInt("#{settings.network_page.addnodes_table.items_per_page}");
var addNodeRows = [];
var setting_add_port_filter = "#{settings.network_page.addnodes_table.port_filter}";
var setting_add_hide_protocols = !{JSON.stringify(settings.network_page.addnodes_table.hide_protocols)};
var addNodePeers = peers;
if (setting_add_port_filter == null || setting_add_port_filter == '')
setting_add_port_filter = '0';
if (setting_add_port_filter != '0')
addNodePeers = addNodePeers.filter(v => v.port == setting_add_port_filter);
setting_add_hide_protocols.forEach(function (protocol) {
addNodePeers = addNodePeers.filter(v => v.protocol != protocol);
});
for (var i=0; i < addNodePeers.length; i++)
addNodeRows.push({'nodes': 'addnode=' + (addNodePeers[i]['address'] != null && addNodePeers[i]['address'].indexOf(':') > -1 ? '[' + addNodePeers[i]['address'] + ']' : addNodePeers[i]['address']) + (addNodePeers[i]['port'] == null ? '' : ':' + addNodePeers[i]['port'])});
$('#addnodes-table').dataTable({
autoWidth: true,
searching: false,
ordering: false,
responsive: true,
lengthChange: true,
processing: true,
iDisplayLength: setting_txPerPage,
lengthMenu: generateLengthMenu(setting_txPerPage, !{JSON.stringify(settings.network_page.addnodes_table.page_length_options)}),
scrollX: true,
language: {
paginate: {
previous: '<',
next: '>'
}
},
data: addNodeRows,
fnDrawCallback: function(settings) {
fixDataTableColumns();
fixFooterHeightAndPosition();
},
columns: [
{data: 'nodes', width: '100%'}
],
columnDefs: [
{targets: '_all', className: 'text-start'}
]
});
setting_txPerPage = parseInt("#{settings.network_page.onetry_table.items_per_page}");
var oneTryRows = [];
var setting_one_port_filter = "#{settings.network_page.onetry_table.port_filter}";
var setting_one_hide_protocols = !{JSON.stringify(settings.network_page.onetry_table.hide_protocols)};
if (setting_one_port_filter == null || setting_one_port_filter == '')
setting_one_port_filter = '0';
if (setting_one_port_filter != '0')
peers = peers.filter(v => v.port == setting_one_port_filter);
setting_one_hide_protocols.forEach(function (protocol) {
peers = peers.filter(v => v.protocol != protocol);
});
for (var i=0; i < peers.length; i++)
oneTryRows.push({'nodes': 'addnode ' + (peers[i]['address'] != null && peers[i]['address'].indexOf(':') > -1 ? '[' + peers[i]['address'] + ']' : peers[i]['address']) + (peers[i]['port'] == null ? '' : ':' + peers[i]['port']) + ' onetry'});
$('#onetry-table').dataTable({
autoWidth: true,
searching: false,
ordering: false,
responsive: true,
lengthChange: true,
processing: true,
iDisplayLength: setting_txPerPage,
lengthMenu: generateLengthMenu(setting_txPerPage, !{JSON.stringify(settings.network_page.onetry_table.page_length_options)}),
scrollX: true,
language: {
paginate: {
previous: '<',
next: '>'
}
},
data: oneTryRows,
fnDrawCallback: function(settings) {
fixDataTableColumns();
fixFooterHeightAndPosition();
},
columns: [
{data: 'nodes', width: '100%'}
],
columnDefs: [
{targets: '_all', className: 'text-start'}
]
});
});
setting_txPerPage = parseInt("#{settings.network_page.addnodes_table.items_per_page}");
$('#addnodes-table').dataTable({
autoWidth: true,
searching: false,
ordering: false,
responsive: true,
lengthChange: true,
processing: true,
iDisplayLength: setting_txPerPage,
lengthMenu: generateLengthMenu(setting_txPerPage, !{JSON.stringify(settings.network_page.addnodes_table.page_length_options)}),
scrollX: true,
language: {
paginate: {
previous: '<',
next: '>'
}
},
ajax: {
url: '/ext/getnetworkpeers/internal',
dataSrc: function (json) {
var rows = [];
for (var i=0; i<json.data.length; i++)
rows.push({'nodes': 'addnode=' + (json.data[i]['address'] != null && json.data[i]['address'].indexOf(':') > -1 ? '[' + json.data[i]['address'] + ']' : json.data[i]['address']) + (json.data[i]['port'] == null ? '' : ':' + json.data[i]['port'])});
return rows;
}
},
fnDrawCallback: function(settings) {
fixDataTableColumns();
fixFooterHeightAndPosition();
},
columns: [
{data: 'nodes', width: '100%'}
],
columnDefs: [
{targets: '_all', className: 'text-start'}
]
});
setting_txPerPage = parseInt("#{settings.network_page.onetry_table.items_per_page}");
$('#onetry-table').dataTable({
autoWidth: true,
searching: false,
ordering: false,
responsive: true,
lengthChange: true,
processing: true,
iDisplayLength: setting_txPerPage,
lengthMenu: generateLengthMenu(setting_txPerPage, !{JSON.stringify(settings.network_page.onetry_table.page_length_options)}),
scrollX: true,
language: {
paginate: {
previous: '<',
next: '>'
}
},
ajax: {
url: '/ext/getnetworkpeers/internal',
dataSrc: function (json) {
var rows = [];
for (var i=0; i<json.data.length; i++)
rows.push({'nodes': 'addnode ' + (json.data[i]['address'] != null && json.data[i]['address'].indexOf(':') > -1 ? '[' + json.data[i]['address'] + ']' : json.data[i]['address']) + (json.data[i]['port'] == null ? '' : ':' + json.data[i]['port']) + ' onetry'});
return rows;
}
},
fnDrawCallback: function(settings) {
fixDataTableColumns();
fixFooterHeightAndPosition();
},
columns: [
{data: 'nodes', width: '100%'}
],
columnDefs: [
{targets: '_all', className: 'text-start'}
]
});
$('a[data-bs-toggle="tab"]').on('shown.bs.tab', function (e) {
fixDataTableColumns();
fixFooterHeightAndPosition();
@@ -204,6 +242,7 @@ block content
thead
tr(class=theadClasses)
th.text-center #{settings.locale.net_address}
th.text-center='Port'
th.text-center #{settings.locale.net_protocol}
th.text-center #{settings.locale.net_subversion}
th.text-center #{settings.locale.net_country}