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;
}
Example #5
0
    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 ();
        }
    }
Example #6
0
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);
    }
}
Example #7
0
void
QuorumSetTracker::askPeer(Peer::pointer peer)
{
    peer->sendGetQuorumSet(mItemID);
}
Example #8
0
void
TxSetTracker::askPeer(Peer::pointer peer)
{
    peer->sendGetTxSet(mItemID);
}
Example #9
0
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);
}