@@ -374,9 +374,12 @@ class GetinfoRequestHandler: public BaseRequestHandler
374
374
class NetinfoRequestHandler : public BaseRequestHandler
375
375
{
376
376
private:
377
+ static constexpr int8_t NET_I2P{3 }; // pos of "i2p" in m_networks
377
378
static constexpr uint8_t MAX_DETAIL_LEVEL{4 };
378
- static constexpr std::array m_networks{" ipv4" , " ipv6" , " onion" };
379
- std::array<std::array<uint16_t , m_networks.size() + 2 >, 3 > m_counts{{{}}}; // !< Peer counts by (in/out/total, networks/total/block-relay)
379
+ static constexpr std::array m_networks{" ipv4" , " ipv6" , " onion" , " i2p" };
380
+ std::array<std::array<uint16_t , m_networks.size() + 1 >, 3 > m_counts{{{}}}; // !< Peer counts by (in/out/total, networks/total)
381
+ uint8_t m_block_relay_peers_count{0 };
382
+ uint8_t m_manual_peers_count{0 };
380
383
int8_t NetworkStringToId (const std::string& str) const
381
384
{
382
385
for (size_t i = 0 ; i < m_networks.size (); ++i) {
@@ -390,12 +393,14 @@ class NetinfoRequestHandler : public BaseRequestHandler
390
393
bool IsAddressSelected () const { return m_details_level == 2 || m_details_level == 4 ; }
391
394
bool IsVersionSelected () const { return m_details_level == 3 || m_details_level == 4 ; }
392
395
bool m_is_asmap_on{false };
396
+ bool m_is_i2p_on{false };
393
397
size_t m_max_addr_length{0 };
394
398
size_t m_max_age_length{4 };
395
399
size_t m_max_id_length{2 };
396
400
struct Peer {
397
401
std::string addr;
398
402
std::string sub_version;
403
+ std::string conn_type;
399
404
std::string network;
400
405
std::string age;
401
406
double min_ping;
@@ -425,6 +430,14 @@ class NetinfoRequestHandler : public BaseRequestHandler
425
430
const double milliseconds{round (1000 * seconds)};
426
431
return milliseconds > 999999 ? " -" : ToString (milliseconds);
427
432
}
433
+ std::string ConnectionTypeForNetinfo (const std::string& conn_type) const
434
+ {
435
+ if (conn_type == " outbound-full-relay" ) return " full" ;
436
+ if (conn_type == " block-relay-only" ) return " block" ;
437
+ if (conn_type == " manual" || conn_type == " feeler" ) return conn_type;
438
+ if (conn_type == " addr-fetch" ) return " addr" ;
439
+ return " " ;
440
+ }
428
441
const UniValue NetinfoHelp ()
429
442
{
430
443
return std::string{
@@ -453,6 +466,9 @@ class NetinfoRequestHandler : public BaseRequestHandler
453
466
" type Type of peer connection\n "
454
467
" \" full\" - full relay, the default\n "
455
468
" \" block\" - block relay; like full relay but does not relay transactions or addresses\n "
469
+ " \" manual\" - peer we manually added using RPC addnode or the -addnode/-connect config options\n "
470
+ " \" feeler\" - short-lived connection for testing addresses\n "
471
+ " \" addr\" - address fetch; short-lived connection for requesting addresses\n "
456
472
" net Network the peer connected through (\" ipv4\" , \" ipv6\" , \" onion\" , \" i2p\" , or \" cjdns\" )\n "
457
473
" mping Minimum observed ping time, in milliseconds (ms)\n "
458
474
" ping Last observed ping time, in milliseconds (ms)\n "
@@ -467,7 +483,7 @@ class NetinfoRequestHandler : public BaseRequestHandler
467
483
" address IP address and port of the peer\n "
468
484
" version Peer version and subversion concatenated, e.g. \" 70016/Satoshi:21.0.0/\"\n\n "
469
485
" * The connection counts table displays the number of peers by direction, network, and the totals\n "
470
- " for each, as well as a column for block relay peers.\n\n "
486
+ " for each, as well as two special outbound columns for block relay peers and manual peers.\n\n "
471
487
" * The local addresses table lists each local address broadcast by the node, the port, and the score.\n\n "
472
488
" Examples:\n\n "
473
489
" Connection counts and local addresses only\n "
@@ -524,16 +540,16 @@ class NetinfoRequestHandler : public BaseRequestHandler
524
540
const std::string network{peer[" network" ].get_str ()};
525
541
const int8_t network_id{NetworkStringToId (network)};
526
542
if (network_id == UNKNOWN_NETWORK) continue ;
543
+ m_is_i2p_on |= (network_id == NET_I2P);
527
544
const bool is_outbound{!peer[" inbound" ].get_bool ()};
528
545
const bool is_block_relay{peer[" relaytxes" ].isNull () ? false : !peer[" relaytxes" ].get_bool ()};
546
+ const std::string conn_type{peer[" connection_type" ].get_str ()};
529
547
++m_counts.at (is_outbound).at (network_id); // in/out by network
530
548
++m_counts.at (is_outbound).at (m_networks.size ()); // in/out overall
531
549
++m_counts.at (2 ).at (network_id); // total by network
532
550
++m_counts.at (2 ).at (m_networks.size ()); // total overall
533
- if (is_block_relay) {
534
- ++m_counts.at (is_outbound).at (m_networks.size () + 1 ); // in/out block-relay
535
- ++m_counts.at (2 ).at (m_networks.size () + 1 ); // total block-relay
536
- }
551
+ if (is_block_relay) ++m_block_relay_peers_count;
552
+ if (conn_type == " manual" ) ++m_manual_peers_count;
537
553
if (DetailsRequested ()) {
538
554
// Push data for this peer to the peers vector.
539
555
const int peer_id{peer[" id" ].get_int ()};
@@ -549,7 +565,7 @@ class NetinfoRequestHandler : public BaseRequestHandler
549
565
const std::string addr{peer[" addr" ].get_str ()};
550
566
const std::string age{conn_time == 0 ? " " : ToString ((m_time_now - conn_time) / 60 )};
551
567
const std::string sub_version{peer[" subver" ].get_str ()};
552
- m_peers.push_back ({addr, sub_version, network, age, min_ping, ping, last_blck, last_recv, last_send, last_trxn, peer_id, mapped_as, version, is_block_relay, is_outbound});
568
+ m_peers.push_back ({addr, sub_version, conn_type, network, age, min_ping, ping, last_blck, last_recv, last_send, last_trxn, peer_id, mapped_as, version, is_block_relay, is_outbound});
553
569
m_max_addr_length = std::max (addr.length () + 1 , m_max_addr_length);
554
570
m_max_age_length = std::max (age.length (), m_max_age_length);
555
571
m_max_id_length = std::max (ToString (peer_id).length (), m_max_id_length);
@@ -563,15 +579,15 @@ class NetinfoRequestHandler : public BaseRequestHandler
563
579
// Report detailed peer connections list sorted by direction and minimum ping time.
564
580
if (DetailsRequested () && !m_peers.empty ()) {
565
581
std::sort (m_peers.begin (), m_peers.end ());
566
- result += strprintf (" <-> relay net mping ping send recv txn blk %*s " , m_max_age_length, " age" );
582
+ result += strprintf (" <-> type net mping ping send recv txn blk %*s " , m_max_age_length, " age" );
567
583
if (m_is_asmap_on) result += " asmap " ;
568
584
result += strprintf (" %*s %-*s%s\n " , m_max_id_length, " id" , IsAddressSelected () ? m_max_addr_length : 0 , IsAddressSelected () ? " address" : " " , IsVersionSelected () ? " version" : " " );
569
585
for (const Peer& peer : m_peers) {
570
586
std::string version{ToString (peer.version ) + peer.sub_version };
571
587
result += strprintf (
572
- " %3s %5s %5s%7s%7s%5s%5s%5s%5s %*s%*i %*s %-*s%s\n " ,
588
+ " %3s %6s %5s%7s%7s%5s%5s%5s%5s %*s%*i %*s %-*s%s\n " ,
573
589
peer.is_outbound ? " out" : " in" ,
574
- peer.is_block_relay ? " block " : " full " ,
590
+ ConnectionTypeForNetinfo ( peer.conn_type ) ,
575
591
peer.network ,
576
592
PingTimeToString (peer.min_ping ),
577
593
PingTimeToString (peer.ping ),
@@ -589,18 +605,27 @@ class NetinfoRequestHandler : public BaseRequestHandler
589
605
IsAddressSelected () ? peer.addr : " " ,
590
606
IsVersionSelected () && version != " 0" ? version : " " );
591
607
}
592
- result += strprintf (" ms ms sec sec min min %*s\n\n " , m_max_age_length, " min" );
608
+ result += strprintf (" ms ms sec sec min min %*s\n\n " , m_max_age_length, " min" );
593
609
}
594
610
595
611
// Report peer connection totals by type.
596
- result += " ipv4 ipv6 onion total block-relay\n " ;
612
+ result += " ipv4 ipv6 onion" ;
613
+ if (m_is_i2p_on) result += " i2p" ;
614
+ result += " total block" ;
615
+ if (m_manual_peers_count) result += " manual" ;
597
616
const std::array rows{" in" , " out" , " total" };
598
617
for (uint8_t i = 0 ; i < 3 ; ++i) {
599
- result += strprintf (" %-5s %5i %5i %5i %5i %5i\n " , rows.at (i), m_counts.at (i).at (0 ), m_counts.at (i).at (1 ), m_counts.at (i).at (2 ), m_counts.at (i).at (m_networks.size ()), m_counts.at (i).at (m_networks.size () + 1 ));
618
+ result += strprintf (" \n %-5s %5i %5i %5i" , rows.at (i), m_counts.at (i).at (0 ), m_counts.at (i).at (1 ), m_counts.at (i).at (2 )); // ipv4/ipv6/onion peers counts
619
+ if (m_is_i2p_on) result += strprintf (" %5i" , m_counts.at (i).at (3 )); // i2p peers count
620
+ result += strprintf (" %5i" , m_counts.at (i).at (m_networks.size ())); // total peers count
621
+ if (i == 1 ) { // the outbound row has two extra columns for block relay and manual peer counts
622
+ result += strprintf (" %5i" , m_block_relay_peers_count);
623
+ if (m_manual_peers_count) result += strprintf (" %5i" , m_manual_peers_count);
624
+ }
600
625
}
601
626
602
627
// Report local addresses, ports, and scores.
603
- result += " \n Local addresses" ;
628
+ result += " \n\ n Local addresses" ;
604
629
const std::vector<UniValue>& local_addrs{networkinfo[" localaddresses" ].getValues ()};
605
630
if (local_addrs.empty ()) {
606
631
result += " : n/a\n " ;
0 commit comments