bool OverlayManagerImpl::isPeerPreferred(Peer::pointer peer) { std::string pstr = peer->toString(); if (mPreferredPeers.find(pstr) != mPreferredPeers.end()) { CLOG(DEBUG, "Overlay") << "Peer " << pstr << " is preferred"; return true; } if (peer->isAuthenticated()) { std::string kstr = PubKeyUtils::toStrKey(peer->getPeerID()); std::vector<std::string> const& pk = mApp.getConfig().PREFERRED_PEER_KEYS; if (std::find(pk.begin(), pk.end(), kstr) != pk.end()) { CLOG(DEBUG, "Overlay") << "Peer key " << mApp.getConfig().toStrKey(peer->getPeerID()) << " is preferred"; return true; } } CLOG(DEBUG, "Overlay") << "Peer " << pstr << " is not preferred"; return false; }
void OverlayManagerImpl::addConnectedPeer(Peer::pointer peer) { if (mShuttingDown) { peer->drop(); return; } CLOG(INFO, "Overlay") << "New connected peer " << peer->toString(); mConnectionsEstablished.Mark(); mPeers.push_back(peer); mPeersSize.set_count(mPeers.size()); }
void OverlayManagerImpl::dropPeer(Peer::pointer peer) { mConnectionsDropped.Mark(); CLOG(INFO, "Overlay") << "Dropping peer " << mApp.getConfig().toShortString(peer->getPeerID()) << "@" << peer->toString(); auto iter = find(mPeers.begin(), mPeers.end(), peer); if (iter != mPeers.end()) mPeers.erase(iter); else CLOG(WARNING, "Overlay") << "Dropping unlisted peer"; mPeersSize.set_count(mPeers.size()); }
bool OverlayManagerImpl::isPeerAccepted(Peer::pointer peer) { if (isPeerPreferred(peer)) { if (mPeers.size() < mApp.getConfig().MAX_PEER_CONNECTIONS) { return true; } for (auto victim : mPeers) { if (!isPeerPreferred(victim)) { CLOG(INFO, "Overlay") << "Evicting non-preferred peer " << victim->toString() << " for preferred peer " << peer->toString(); dropPeer(victim); return true; } } } if (!mApp.getConfig().PREFERRED_PEERS_ONLY && mPeers.size() < mApp.getConfig().MAX_PEER_CONNECTIONS) return true; mConnectionsRejected.Mark(); return false; }
void handleConnect (Peer::pointer new_connection, const boost::system::error_code& error) { bool delay = false; if (!error) { new_connection->connected (error); } else { if (error == boost::system::errc::too_many_files_open) delay = true; WriteLog (lsERROR, PeerDoor) << error; } if (delay) { mDelayTimer.expires_from_now (boost::posix_time::milliseconds (500)); mDelayTimer.async_wait (boost::bind (&PeerDoorImp::startListening, this)); } else { startListening (); } }
void PeerSet::sendRequest (const protocol::TMGetLedger& tmGL) { ScopedLockType sl (mLock, __FILE__, __LINE__); if (mPeers.empty ()) return; PackedMessage::pointer packet = boost::make_shared<PackedMessage> (tmGL, protocol::mtGET_LEDGER); for (boost::unordered_map<uint64, int>::iterator it = mPeers.begin (), end = mPeers.end (); it != end; ++it) { Peer::pointer peer = getApp().getPeers ().getPeerById (it->first); if (peer) peer->sendPacket (packet, false); } }
void QuorumSetTracker::askPeer(Peer::pointer peer) { peer->sendGetQuorumSet(mItemID); }
void TxSetTracker::askPeer(Peer::pointer peer) { peer->sendGetTxSet(mItemID); }
void Tracker::tryNextPeer() { // will be called by some timer or when we get a // response saying they don't have it Peer::pointer peer; CLOG(TRACE, "Overlay") << "tryNextPeer " << hexAbbrev(mItemHash) << " last: " << (mLastAskedPeer ? mLastAskedPeer->toString() : "<none>"); // if we don't have a list of peers to ask and we're not // currently asking peers, build a new list if (mPeersToAsk.empty() && !mLastAskedPeer) { std::set<std::shared_ptr<Peer>> peersWithEnvelope; for (auto const& e : mWaitingEnvelopes) { auto const& s = mApp.getOverlayManager().getPeersKnows(e.first); peersWithEnvelope.insert(s.begin(), s.end()); } // move the peers that have the envelope to the back, // to be processed first for (auto const& p : mApp.getOverlayManager().getRandomPeers()) { if (peersWithEnvelope.find(p) != peersWithEnvelope.end()) { mPeersToAsk.emplace_back(p); } else { mPeersToAsk.emplace_front(p); } } mNumListRebuild++; CLOG(TRACE, "Overlay") << "tryNextPeer " << hexAbbrev(mItemHash) << " attempt " << mNumListRebuild << " reset to #" << mPeersToAsk.size(); mTryNextPeerReset.Mark(); } while (!peer && !mPeersToAsk.empty()) { peer = mPeersToAsk.back(); if (!peer->isAuthenticated()) { peer.reset(); } mPeersToAsk.pop_back(); } std::chrono::milliseconds nextTry; if (!peer) { // we have asked all our peers // clear mLastAskedPeer so that we rebuild a new list mLastAskedPeer.reset(); if (mNumListRebuild > MAX_REBUILD_FETCH_LIST) { nextTry = MS_TO_WAIT_FOR_FETCH_REPLY * MAX_REBUILD_FETCH_LIST; } else { nextTry = MS_TO_WAIT_FOR_FETCH_REPLY * mNumListRebuild; } } else { mLastAskedPeer = peer; CLOG(TRACE, "Overlay") << "Asking for " << hexAbbrev(mItemHash) << " to " << peer->toString(); mTryNextPeer.Mark(); mAskPeer(peer, mItemHash); nextTry = MS_TO_WAIT_FOR_FETCH_REPLY; } mTimer.expires_from_now(nextTry); mTimer.async_wait([this]() { this->tryNextPeer(); }, VirtualTimer::onFailureNoop); }
// means "We got some data from an inbound ledger" void InboundLedgers::gotLedgerData (Job&, uint256 hash, boost::shared_ptr<protocol::TMLedgerData> packet_ptr, boost::weak_ptr<Peer> wPeer) { protocol::TMLedgerData& packet = *packet_ptr; Peer::pointer peer = wPeer.lock (); WriteLog (lsTRACE, InboundLedger) << "Got data (" << packet.nodes ().size () << ") for acquiring ledger: " << hash; InboundLedger::pointer ledger = find (hash); if (!ledger) { WriteLog (lsTRACE, InboundLedger) << "Got data for ledger we're not acquiring"; if (peer) peer->applyLoadCharge (LT_InvalidRequest); return; } ledger->noAwaitData (); if (!peer) return; if (packet.type () == protocol::liBASE) { if (packet.nodes_size () < 1) { WriteLog (lsWARNING, InboundLedger) << "Got empty base data"; peer->applyLoadCharge (LT_InvalidRequest); return; } if (!ledger->takeBase (packet.nodes (0).nodedata ())) { WriteLog (lsWARNING, InboundLedger) << "Got invalid base data"; peer->applyLoadCharge (LT_InvalidRequest); return; } SHAMapAddNode san = SHAMapAddNode::useful (); if ((packet.nodes ().size () > 1) && !ledger->takeAsRootNode (strCopy (packet.nodes (1).nodedata ()), san)) { WriteLog (lsWARNING, InboundLedger) << "Included ASbase invalid"; } if ((packet.nodes ().size () > 2) && !ledger->takeTxRootNode (strCopy (packet.nodes (2).nodedata ()), san)) { WriteLog (lsWARNING, InboundLedger) << "Included TXbase invalid"; } if (!san.isInvalid ()) { ledger->progress (); ledger->trigger (peer); } else WriteLog (lsDEBUG, InboundLedger) << "Peer sends invalid base data"; return; } if ((packet.type () == protocol::liTX_NODE) || (packet.type () == protocol::liAS_NODE)) { std::list<SHAMapNode> nodeIDs; std::list< Blob > nodeData; if (packet.nodes ().size () <= 0) { WriteLog (lsINFO, InboundLedger) << "Got response with no nodes"; peer->applyLoadCharge (LT_InvalidRequest); return; } for (int i = 0; i < packet.nodes ().size (); ++i) { const protocol::TMLedgerNode& node = packet.nodes (i); if (!node.has_nodeid () || !node.has_nodedata ()) { WriteLog (lsWARNING, InboundLedger) << "Got bad node"; peer->applyLoadCharge (LT_InvalidRequest); return; } nodeIDs.push_back (SHAMapNode (node.nodeid ().data (), node.nodeid ().size ())); nodeData.push_back (Blob (node.nodedata ().begin (), node.nodedata ().end ())); } SHAMapAddNode ret; if (packet.type () == protocol::liTX_NODE) ledger->takeTxNode (nodeIDs, nodeData, ret); else ledger->takeAsNode (nodeIDs, nodeData, ret); if (!ret.isInvalid ()) { ledger->progress (); ledger->trigger (peer); } else WriteLog (lsDEBUG, InboundLedger) << "Peer sends invalid node data"; return; } WriteLog (lsWARNING, InboundLedger) << "Not sure what ledger data we got"; peer->applyLoadCharge (LT_InvalidRequest); }