@ -3716,32 +3716,49 @@ void ProcessMessage(
return ;
return ;
}
}
/** Maybe disconnect a peer and discourage future connections from its address.
*
* @ param [ in ] pnode The node to check .
* @ return True if the peer was marked for disconnection in this function
*/
bool PeerLogicValidation : : MaybeDiscourageAndDisconnect ( CNode & pnode )
bool PeerLogicValidation : : MaybeDiscourageAndDisconnect ( CNode & pnode )
{
{
AssertLockHeld ( cs_main ) ;
NodeId peer_id { pnode . GetId ( ) } ;
CNodeState & state = * State ( pnode . GetId ( ) ) ;
{
LOCK ( cs_main ) ;
CNodeState & state = * State ( peer_id ) ;
// There's nothing to do if the m_should_discourage flag isn't set
if ( ! state . m_should_discourage ) return false ;
if ( state . m_should_discourage ) {
// Reset m_should_discourage
state . m_should_discourage = false ;
state . m_should_discourage = false ;
if ( pnode . HasPermission ( PF_NOBAN ) ) {
} // cs_main
LogPrintf ( " Warning: not punishing whitelisted peer %s! \n " , pnode . addr . ToString ( ) ) ;
} else if ( pnode . m_manual_connection ) {
if ( pnode . HasPermission ( PF_NOBAN ) ) {
LogPrintf ( " Warning: not punishing manually-connected peer %s! \n " , pnode . addr . ToString ( ) ) ;
// Peer has the NOBAN permission flag - log but don't disconnect
} else if ( pnode . addr . IsLocal ( ) ) {
LogPrintf ( " Warning: not punishing noban peer %d! \n " , peer_id ) ;
// Disconnect but don't discourage this local node
return false ;
LogPrintf ( " Warning: disconnecting but not discouraging local peer %s! \n " , pnode . addr . ToString ( ) ) ;
}
pnode . fDisconnect = true ;
} else {
if ( pnode . m_manual_connection ) {
// Disconnect and discourage all nodes sharing the address
// Peer is a manual connection - log but don't disconnect
LogPrintf ( " Disconnecting and discouraging peer %s! \n " , pnode . addr . ToString ( ) ) ;
LogPrintf ( " Warning: not punishing manually connected peer %d! \n " , peer_id ) ;
if ( m_banman ) {
return false ;
m_banman - > Discourage ( pnode . addr ) ;
}
}
connman - > DisconnectNode ( pnode . addr ) ;
if ( pnode . addr . IsLocal ( ) ) {
}
// Peer is on a local address. Disconnect this peer, but don't discourage the local address
LogPrintf ( " Warning: disconnecting but not discouraging local peer %d! \n " , peer_id ) ;
pnode . fDisconnect = true ;
return true ;
return true ;
}
}
return false ;
// Normal case: Disconnect the peer and discourage all nodes sharing the address
LogPrintf ( " Disconnecting and discouraging peer %d! \n " , peer_id ) ;
if ( m_banman ) m_banman - > Discourage ( pnode . addr ) ;
connman - > DisconnectNode ( pnode . addr ) ;
return true ;
}
}
bool PeerLogicValidation : : ProcessMessages ( CNode * pfrom , std : : atomic < bool > & interruptMsgProc )
bool PeerLogicValidation : : ProcessMessages ( CNode * pfrom , std : : atomic < bool > & interruptMsgProc )
@ -3834,9 +3851,6 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
LogPrint ( BCLog : : NET , " %s(%s, %u bytes): Unknown exception caught \n " , __func__ , SanitizeString ( msg_type ) , nMessageSize ) ;
LogPrint ( BCLog : : NET , " %s(%s, %u bytes): Unknown exception caught \n " , __func__ , SanitizeString ( msg_type ) , nMessageSize ) ;
}
}
LOCK ( cs_main ) ;
MaybeDiscourageAndDisconnect ( * pfrom ) ;
return fMoreWork ;
return fMoreWork ;
}
}
@ -3999,48 +4013,49 @@ public:
bool PeerLogicValidation : : SendMessages ( CNode * pto )
bool PeerLogicValidation : : SendMessages ( CNode * pto )
{
{
const Consensus : : Params & consensusParams = Params ( ) . GetConsensus ( ) ;
const Consensus : : Params & consensusParams = Params ( ) . GetConsensus ( ) ;
{
// Don't send anything until the version handshake is complete
if ( ! pto - > fSuccessfullyConnected | | pto - > fDisconnect )
return true ;
// If we get here, the outgoing message serialization version is set and can't change.
// We must call MaybeDiscourageAndDisconnect first, to ensure that we'll
const CNetMsgMaker msgMaker ( pto - > GetSendVersion ( ) ) ;
// disconnect misbehaving peers even before the version handshake is complete.
if ( MaybeDiscourageAndDisconnect ( * pto ) ) return true ;
//
// Don't send anything until the version handshake is complete
// Message: ping
if ( ! pto - > fSuccessfullyConnected | | pto - > fDisconnect )
//
return true ;
bool pingSend = false ;
if ( pto - > fPingQueued ) {
// RPC ping request by user
pingSend = true ;
}
if ( pto - > nPingNonceSent = = 0 & & pto - > m_ping_start . load ( ) + PING_INTERVAL < GetTime < std : : chrono : : microseconds > ( ) ) {
// Ping automatically sent as a latency probe & keepalive.
pingSend = true ;
}
if ( pingSend ) {
uint64_t nonce = 0 ;
while ( nonce = = 0 ) {
GetRandBytes ( ( unsigned char * ) & nonce , sizeof ( nonce ) ) ;
}
pto - > fPingQueued = false ;
pto - > m_ping_start = GetTime < std : : chrono : : microseconds > ( ) ;
if ( pto - > nVersion > BIP0031_VERSION ) {
pto - > nPingNonceSent = nonce ;
connman - > PushMessage ( pto , msgMaker . Make ( NetMsgType : : PING , nonce ) ) ;
} else {
// Peer is too old to support ping command with nonce, pong will never arrive.
pto - > nPingNonceSent = 0 ;
connman - > PushMessage ( pto , msgMaker . Make ( NetMsgType : : PING ) ) ;
}
}
TRY_LOCK ( cs_main , lockMain ) ;
// If we get here, the outgoing message serialization version is set and can't change.
if ( ! lockMain )
const CNetMsgMaker msgMaker ( pto - > GetSendVersion ( ) ) ;
return true ;
if ( MaybeDiscourageAndDisconnect ( * pto ) ) return true ;
//
// Message: ping
//
bool pingSend = false ;
if ( pto - > fPingQueued ) {
// RPC ping request by user
pingSend = true ;
}
if ( pto - > nPingNonceSent = = 0 & & pto - > m_ping_start . load ( ) + PING_INTERVAL < GetTime < std : : chrono : : microseconds > ( ) ) {
// Ping automatically sent as a latency probe & keepalive.
pingSend = true ;
}
if ( pingSend ) {
uint64_t nonce = 0 ;
while ( nonce = = 0 ) {
GetRandBytes ( ( unsigned char * ) & nonce , sizeof ( nonce ) ) ;
}
pto - > fPingQueued = false ;
pto - > m_ping_start = GetTime < std : : chrono : : microseconds > ( ) ;
if ( pto - > nVersion > BIP0031_VERSION ) {
pto - > nPingNonceSent = nonce ;
connman - > PushMessage ( pto , msgMaker . Make ( NetMsgType : : PING , nonce ) ) ;
} else {
// Peer is too old to support ping command with nonce, pong will never arrive.
pto - > nPingNonceSent = 0 ;
connman - > PushMessage ( pto , msgMaker . Make ( NetMsgType : : PING ) ) ;
}
}
{
LOCK ( cs_main ) ;
CNodeState & state = * State ( pto - > GetId ( ) ) ;
CNodeState & state = * State ( pto - > GetId ( ) ) ;
@ -4602,7 +4617,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
pto - > m_tx_relay - > nextSendTimeFeeFilter = timeNow + GetRandInt ( MAX_FEEFILTER_CHANGE_DELAY ) * 1000000 ;
pto - > m_tx_relay - > nextSendTimeFeeFilter = timeNow + GetRandInt ( MAX_FEEFILTER_CHANGE_DELAY ) * 1000000 ;
}
}
}
}
}
} // release cs_main
return true ;
return true ;
}
}