@ -437,11 +437,6 @@ void CNode::CloseSocketDisconnect()
@@ -437,11 +437,6 @@ void CNode::CloseSocketDisconnect()
LogPrint ( " net " , " disconnecting peer=%d \n " , id ) ;
CloseSocket ( hSocket ) ;
}
// in case this fails, we'll empty the recv buffer when the CNode is deleted
TRY_LOCK ( cs_vRecvMsg , lockRecv ) ;
if ( lockRecv )
vRecvMsg . clear ( ) ;
}
void CConnman : : ClearBanned ( )
@ -650,16 +645,18 @@ void CNode::copyStats(CNodeStats &stats)
@@ -650,16 +645,18 @@ void CNode::copyStats(CNodeStats &stats)
}
# undef X
// requires LOCK(cs_vRecvMsg)
bool CNode : : ReceiveMsgBytes ( const char * pch , unsigned int nBytes , bool & complete )
{
complete = false ;
int64_t nTimeMicros = GetTimeMicros ( ) ;
nLastRecv = nTimeMicros / 1000000 ;
nRecvBytes + = nBytes ;
while ( nBytes > 0 ) {
// get current incomplete message, or create a new one
if ( vRecvMsg . empty ( ) | |
vRecvMsg . back ( ) . complete ( ) )
vRecvMsg . push_back ( CNetMessage ( Params ( ) . MessageStart ( ) , SER_NETWORK , nRecvVersion ) ) ;
vRecvMsg . push_back ( CNetMessage ( Params ( ) . MessageStart ( ) , SER_NETWORK , INIT_PROTO_VERSION ) ) ;
CNetMessage & msg = vRecvMsg . back ( ) ;
@ -691,7 +688,7 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete
@@ -691,7 +688,7 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete
assert ( i ! = mapRecvBytesPerMsgCmd . end ( ) ) ;
i - > second + = msg . hdr . nMessageSize + CMessageHeader : : HEADER_SIZE ;
msg . nTime = GetTimeMicros ( ) ;
msg . nTime = nTimeMicros ;
complete = true ;
}
}
@ -764,7 +761,7 @@ const uint256& CNetMessage::GetMessageHash() const
@@ -764,7 +761,7 @@ const uint256& CNetMessage::GetMessageHash() const
// requires LOCK(cs_vSend)
size_t SocketSendData ( CNode * pnode )
size_t CConnman : : SocketSendData ( CNode * pnode )
{
auto it = pnode - > vSendMsg . begin ( ) ;
size_t nSentSize = 0 ;
@ -781,6 +778,7 @@ size_t SocketSendData(CNode *pnode)
@@ -781,6 +778,7 @@ size_t SocketSendData(CNode *pnode)
if ( pnode - > nSendOffset = = data . size ( ) ) {
pnode - > nSendOffset = 0 ;
pnode - > nSendSize - = data . size ( ) ;
pnode - > fPauseSend = pnode - > nSendSize > nSendBufferMaxSize ;
it + + ;
} else {
// could not send full message; stop sending more
@ -1052,8 +1050,7 @@ void CConnman::ThreadSocketHandler()
@@ -1052,8 +1050,7 @@ void CConnman::ThreadSocketHandler()
std : : vector < CNode * > vNodesCopy = vNodes ;
BOOST_FOREACH ( CNode * pnode , vNodesCopy )
{
if ( pnode - > fDisconnect | |
( pnode - > GetRefCount ( ) < = 0 & & pnode - > vRecvMsg . empty ( ) & & pnode - > nSendSize = = 0 ) )
if ( pnode - > fDisconnect )
{
// remove from vNodes
vNodes . erase ( remove ( vNodes . begin ( ) , vNodes . end ( ) , pnode ) , vNodes . end ( ) ) ;
@ -1082,16 +1079,12 @@ void CConnman::ThreadSocketHandler()
@@ -1082,16 +1079,12 @@ void CConnman::ThreadSocketHandler()
{
TRY_LOCK ( pnode - > cs_vSend , lockSend ) ;
if ( lockSend )
{
TRY_LOCK ( pnode - > cs_vRecvMsg , lockRecv ) ;
if ( lockRecv )
{
TRY_LOCK ( pnode - > cs_inventory , lockInv ) ;
if ( lockInv )
fDelete = true ;
}
}
}
if ( fDelete )
{
vNodesDisconnected . remove ( pnode ) ;
@ -1149,15 +1142,10 @@ void CConnman::ThreadSocketHandler()
@@ -1149,15 +1142,10 @@ void CConnman::ThreadSocketHandler()
// write buffer in this case before receiving more. This avoids
// needlessly queueing received data, if the remote peer is not themselves
// receiving data. This means properly utilizing TCP flow control signalling.
// * Otherwise, if there is no (complete) message in the receive buffer,
// or there is space left in the buffer, select() for receiving data.
// * (if neither of the above applies, there is certainly one message
// in the receiver buffer ready to be processed).
// Together, that means that at least one of the following is always possible,
// so we don't deadlock:
// * We send some data.
// * We wait for data to be received (and disconnect after timeout).
// * We process a message in the buffer (message handler thread).
// * Otherwise, if there is space left in the receive buffer, select() for
// receiving data.
// * Hand off all complete messages to the processor, to be handled without
// blocking here.
{
TRY_LOCK ( pnode - > cs_vSend , lockSend ) ;
if ( lockSend ) {
@ -1168,10 +1156,7 @@ void CConnman::ThreadSocketHandler()
@@ -1168,10 +1156,7 @@ void CConnman::ThreadSocketHandler()
}
}
{
TRY_LOCK ( pnode - > cs_vRecvMsg , lockRecv ) ;
if ( lockRecv & & (
pnode - > vRecvMsg . empty ( ) | | ! pnode - > vRecvMsg . front ( ) . complete ( ) | |
pnode - > GetTotalRecvSize ( ) < = GetReceiveFloodSize ( ) ) )
if ( ! pnode - > fPauseRecv )
FD_SET ( pnode - > hSocket , & fdsetRecv ) ;
}
}
@ -1230,8 +1215,6 @@ void CConnman::ThreadSocketHandler()
@@ -1230,8 +1215,6 @@ void CConnman::ThreadSocketHandler()
continue ;
if ( FD_ISSET ( pnode - > hSocket , & fdsetRecv ) | | FD_ISSET ( pnode - > hSocket , & fdsetError ) )
{
TRY_LOCK ( pnode - > cs_vRecvMsg , lockRecv ) ;
if ( lockRecv )
{
{
// typical socket buffer is 8K-64K
@ -1242,11 +1225,23 @@ void CConnman::ThreadSocketHandler()
@@ -1242,11 +1225,23 @@ void CConnman::ThreadSocketHandler()
bool notify = false ;
if ( ! pnode - > ReceiveMsgBytes ( pchBuf , nBytes , notify ) )
pnode - > CloseSocketDisconnect ( ) ;
if ( notify )
condMsgProc . notify_one ( ) ;
pnode - > nLastRecv = GetTime ( ) ;
pnode - > nRecvBytes + = nBytes ;
RecordBytesRecv ( nBytes ) ;
if ( notify ) {
size_t nSizeAdded = 0 ;
auto it ( pnode - > vRecvMsg . begin ( ) ) ;
for ( ; it ! = pnode - > vRecvMsg . end ( ) ; + + it ) {
if ( ! it - > complete ( ) )
break ;
nSizeAdded + = it - > vRecv . size ( ) + CMessageHeader : : HEADER_SIZE ;
}
{
LOCK ( pnode - > cs_vProcessMsg ) ;
pnode - > vProcessMsg . splice ( pnode - > vProcessMsg . end ( ) , pnode - > vRecvMsg , pnode - > vRecvMsg . begin ( ) , it ) ;
pnode - > nProcessQueueSize + = nSizeAdded ;
pnode - > fPauseRecv = pnode - > nProcessQueueSize > nReceiveFloodSize ;
}
WakeMessageHandler ( ) ;
}
}
else if ( nBytes = = 0 )
{
@ -1280,10 +1275,11 @@ void CConnman::ThreadSocketHandler()
@@ -1280,10 +1275,11 @@ void CConnman::ThreadSocketHandler()
TRY_LOCK ( pnode - > cs_vSend , lockSend ) ;
if ( lockSend ) {
size_t nBytes = SocketSendData ( pnode ) ;
if ( nBytes )
if ( nBytes ) {
RecordBytesSent ( nBytes ) ;
}
}
}
//
// Inactivity checking
@ -1321,8 +1317,14 @@ void CConnman::ThreadSocketHandler()
@@ -1321,8 +1317,14 @@ void CConnman::ThreadSocketHandler()
}
}
void CConnman : : WakeMessageHandler ( )
{
{
std : : lock_guard < std : : mutex > lock ( mutexMsgProc ) ;
fMsgProcWake = true ;
}
condMsgProc . notify_one ( ) ;
}
@ -1858,7 +1860,7 @@ void CConnman::ThreadMessageHandler()
@@ -1858,7 +1860,7 @@ void CConnman::ThreadMessageHandler()
}
}
bool fSleep = tru e ;
bool fMoreWork = fals e ;
BOOST_FOREACH ( CNode * pnode , vNodesCopy )
{
@ -1866,22 +1868,8 @@ void CConnman::ThreadMessageHandler()
@@ -1866,22 +1868,8 @@ void CConnman::ThreadMessageHandler()
continue ;
// Receive messages
{
TRY_LOCK ( pnode - > cs_vRecvMsg , lockRecv ) ;
if ( lockRecv )
{
if ( ! GetNodeSignals ( ) . ProcessMessages ( pnode , * this , flagInterruptMsgProc ) )
pnode - > CloseSocketDisconnect ( ) ;
if ( pnode - > nSendSize < GetSendBufferSize ( ) )
{
if ( ! pnode - > vRecvGetData . empty ( ) | | ( ! pnode - > vRecvMsg . empty ( ) & & pnode - > vRecvMsg [ 0 ] . complete ( ) ) )
{
fSleep = false ;
}
}
}
}
bool fMoreNodeWork = GetNodeSignals ( ) . ProcessMessages ( pnode , * this , flagInterruptMsgProc ) ;
fMoreWork | = ( fMoreNodeWork & & ! pnode - > fPauseSend ) ;
if ( flagInterruptMsgProc )
return ;
@ -1901,10 +1889,11 @@ void CConnman::ThreadMessageHandler()
@@ -1901,10 +1889,11 @@ void CConnman::ThreadMessageHandler()
pnode - > Release ( ) ;
}
if ( fSleep ) {
std : : unique_lock < std : : mutex > lock ( mutexMsgProc ) ;
condMsgProc . wait_until ( lock , std : : chrono : : steady_clock : : now ( ) + std : : chrono : : milliseconds ( 100 ) ) ;
if ( ! fMoreWork ) {
condMsgProc . wait_until ( lock , std : : chrono : : steady_clock : : now ( ) + std : : chrono : : milliseconds ( 100 ) , [ this ] { return fMsgProcWake ; } ) ;
}
fMsgProcWake = false ;
}
}
@ -2121,7 +2110,7 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
@@ -2121,7 +2110,7 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
nMaxFeeler = connOptions . nMaxFeeler ;
nSendBufferMaxSize = connOptions . nSendBufferMaxSize ;
nReceiveFloodSize = connOptions . nSendBufferMax Size ;
nReceiveFloodSize = connOptions . nReceiveFlood Size ;
nMaxOutboundLimit = connOptions . nMaxOutboundLimit ;
nMaxOutboundTimeframe = connOptions . nMaxOutboundTimeframe ;
@ -2182,6 +2171,11 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
@@ -2182,6 +2171,11 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
interruptNet . reset ( ) ;
flagInterruptMsgProc = false ;
{
std : : unique_lock < std : : mutex > lock ( mutexMsgProc ) ;
fMsgProcWake = false ;
}
// Send and receive from sockets, accept connections
threadSocketHandler = std : : thread ( & TraceThread < std : : function < void ( ) > > , " net " , std : : function < void ( ) > ( std : : bind ( & CConnman : : ThreadSocketHandler , this ) ) ) ;
@ -2613,6 +2607,9 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
@@ -2613,6 +2607,9 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
minFeeFilter = 0 ;
lastSentFeeFilter = 0 ;
nextSendTimeFeeFilter = 0 ;
fPauseRecv = false ;
fPauseSend = false ;
nProcessQueueSize = 0 ;
BOOST_FOREACH ( const std : : string & msg , getAllNetMessageTypes ( ) )
mapRecvBytesPerMsgCmd [ msg ] = 0 ;
@ -2692,6 +2689,8 @@ void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
@@ -2692,6 +2689,8 @@ void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
pnode - > mapSendBytesPerMsgCmd [ msg . command ] + = nTotalSize ;
pnode - > nSendSize + = nTotalSize ;
if ( pnode - > nSendSize > nSendBufferMaxSize )
pnode - > fPauseSend = true ;
pnode - > vSendMsg . push_back ( std : : move ( serializedHeader ) ) ;
if ( nMessageSize )
pnode - > vSendMsg . push_back ( std : : move ( msg . data ) ) ;