Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce no duplicate slots from incoming connections #4944

Merged
merged 9 commits into from
Mar 22, 2024
11 changes: 10 additions & 1 deletion src/ripple/peerfinder/impl/Logic.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ class Logic

std::lock_guard _(lock_);

// Check for duplicate connection
// Check for connection limit per address
if (is_public(remote_endpoint))
{
auto const count =
Expand All @@ -287,6 +287,15 @@ class Logic
}
}

// Check for duplicate connection
if (slots_.find(remote_endpoint) != slots_.end())
{
JLOG(m_journal.debug())
<< beast::leftw(18) << "Logic dropping " << remote_endpoint
<< " as duplicate incoming";
return SlotImp::ptr();
}

// Create the slot
SlotImp::ptr const slot(std::make_shared<SlotImp>(
local_endpoint,
Expand Down
83 changes: 83 additions & 0 deletions src/test/peerfinder/PeerFinder_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <ripple/basics/Slice.h>
#include <ripple/basics/chrono.h>
#include <ripple/beast/unit_test.h>
#include <ripple/beast/unit_test/suite.hpp>
#include <ripple/core/Config.h>
#include <ripple/peerfinder/impl/Logic.h>
#include <ripple/protocol/PublicKey.h>
Expand Down Expand Up @@ -157,6 +158,86 @@ class PeerFinder_test : public beast::unit_test::suite
BEAST_EXPECT(n <= (seconds + 59) / 60);
}

void
test_duplicateOutIn()
{
testcase("duplicate out/in");
TestStore store;
TestChecker checker;
TestStopwatch clock;
Logic<TestChecker> logic(clock, store, checker, journal_);
logic.addFixedPeer(
"test", beast::IP::Endpoint::from_string("65.0.0.1:5"));
{
Config c;
c.autoConnect = false;
c.listeningPort = 1024;
c.ipLimit = 2;
logic.config(c);
}

auto const list = logic.autoconnect();
if (BEAST_EXPECT(!list.empty()))
{
BEAST_EXPECT(list.size() == 1);
auto const remote = list.front();
auto const slot1 = logic.new_outbound_slot(remote);
if (BEAST_EXPECT(slot1 != nullptr))
{
BEAST_EXPECT(
logic.connectedAddresses_.count(remote.address()) == 1);
auto const local =
beast::IP::Endpoint::from_string("65.0.0.2:1024");
auto const slot2 = logic.new_inbound_slot(local, remote);
BEAST_EXPECT(
logic.connectedAddresses_.count(remote.address()) == 1);
if (!BEAST_EXPECT(slot2 == nullptr))
logic.on_closed(slot2);
logic.on_closed(slot1);
}
}
}

void
test_duplicateInOut()
{
testcase("duplicate in/out");
TestStore store;
TestChecker checker;
TestStopwatch clock;
Logic<TestChecker> logic(clock, store, checker, journal_);
logic.addFixedPeer(
"test", beast::IP::Endpoint::from_string("65.0.0.1:5"));
{
Config c;
c.autoConnect = false;
c.listeningPort = 1024;
c.ipLimit = 2;
logic.config(c);
}

auto const list = logic.autoconnect();
if (BEAST_EXPECT(!list.empty()))
{
BEAST_EXPECT(list.size() == 1);
auto const remote = list.front();
auto const local =
beast::IP::Endpoint::from_string("65.0.0.2:1024");
auto const slot1 = logic.new_inbound_slot(local, remote);
if (BEAST_EXPECT(slot1 != nullptr))
{
BEAST_EXPECT(
logic.connectedAddresses_.count(remote.address()) == 1);
auto const slot2 = logic.new_outbound_slot(remote);
BEAST_EXPECT(
logic.connectedAddresses_.count(remote.address()) == 1);
if (!BEAST_EXPECT(slot2 == nullptr))
logic.on_closed(slot2);
logic.on_closed(slot1);
}
}
}

void
test_config()
{
Expand Down Expand Up @@ -279,6 +360,8 @@ class PeerFinder_test : public beast::unit_test::suite
{
test_backoff1();
test_backoff2();
test_duplicateOutIn();
test_duplicateInOut();
test_config();
test_invalid_config();
}
Expand Down
Loading