| 4646 | } |
| 4647 | |
| 4648 | bool PeerManagerImpl::SendMessages(CNode* pto) |
| 4649 | { |
| 4650 | PeerRef peer = GetPeerRef(pto->GetId()); |
| 4651 | if (!peer) return false; |
| 4652 | const Consensus::Params& consensusParams = m_chainparams.GetConsensus(); |
| 4653 | |
| 4654 | // We must call MaybeDiscourageAndDisconnect first, to ensure that we'll |
| 4655 | // disconnect misbehaving peers even before the version handshake is complete. |
| 4656 | if (MaybeDiscourageAndDisconnect(*pto, *peer)) return true; |
| 4657 | |
| 4658 | // Initiate version handshake for outbound connections |
| 4659 | if (!pto->IsInboundConn() && WITH_LOCK(peer->m_msgproc_mutex, return !peer->m_outbound_version_message_sent)) { |
| 4660 | LOCK(peer->m_msgproc_mutex); |
| 4661 | PushNodeVersion(*pto); |
| 4662 | peer->m_outbound_version_message_sent = true; |
| 4663 | } |
| 4664 | |
| 4665 | // Don't send anything until the version handshake is complete |
| 4666 | if (!pto->fSuccessfullyConnected || pto->fDisconnect) |
| 4667 | return true; |
| 4668 | |
| 4669 | // If we get here, the outgoing message serialization version is set and can't change. |
| 4670 | const CNetMsgMaker msgMaker(pto->GetCommonVersion()); |
| 4671 | |
| 4672 | const auto current_time{GetTime<std::chrono::microseconds>()}; |
| 4673 | |
| 4674 | if (pto->IsAddrFetchConn() && current_time - pto->m_connected > 10 * AVG_ADDRESS_BROADCAST_INTERVAL) { |
| 4675 | LogPrint(BCLog::NET, "addrfetch connection timeout; disconnecting peer=%d\n", pto->GetId()); |
| 4676 | pto->fDisconnect = true; |
| 4677 | return true; |
| 4678 | } |
| 4679 | |
| 4680 | MaybeSendPing(*pto, *peer, current_time); |
| 4681 | |
| 4682 | // MaybeSendPing may have marked peer for disconnection |
| 4683 | if (pto->fDisconnect) return true; |
| 4684 | |
| 4685 | MaybeSendAddr(*pto, *peer, current_time); |
| 4686 | |
| 4687 | { |
| 4688 | LOCK(cs_main); |
| 4689 | |
| 4690 | CNodeState &state = *State(pto->GetId()); |
| 4691 | |
| 4692 | // Start block sync |
| 4693 | if (pindexBestHeader == nullptr) |
| 4694 | pindexBestHeader = m_chainman.ActiveChain().Tip(); |
| 4695 | bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->IsAddrFetchConn()); // Download if this is a nice peer, or we have no nice peers and this one might do. |
| 4696 | int64_t headers_ahead = pindexBestHeader->nHeight - m_chainman.ActiveHeight(); |
| 4697 | // ELEMENTS: Only download if our headers aren't "too far ahead" of our blocks. |
| 4698 | bool got_enough_headers = node::fTrimHeaders && (headers_ahead >= node::nHeaderDownloadBuffer); |
| 4699 | if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex && !got_enough_headers) { |
| 4700 | // Only actively request headers from a single peer, unless we're close to today. |
| 4701 | if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) { |
| 4702 | state.fSyncStarted = true; |
| 4703 | state.m_headers_sync_timeout = current_time + HEADERS_DOWNLOAD_TIMEOUT_BASE + |
| 4704 | ( |
| 4705 | // Convert HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER to microseconds before scaling |