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

[20438] LARGE_DATA Participants logic with same listening ports (backport #4396) #4432

Merged
merged 1 commit into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion src/cpp/rtps/transport/TCPTransportInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,10 +716,31 @@ bool TCPTransportInterface::OpenOutputChannel(
listening_port = config->listening_ports.front();
}

bool local_lower_interface = false;
if (IPLocator::getPhysicalPort(physical_locator) == listening_port)
{
std::vector<Locator> list;
std::vector<fastrtps::rtps::IPFinder::info_IP> local_interfaces;
get_ips(local_interfaces);
for (const auto& interface_it : local_interfaces)
{
Locator interface_loc(interface_it.locator);
interface_loc.port = physical_locator.port;
if (is_interface_allowed(interface_loc))
{
list.push_back(interface_loc);
}
}
if (!list.empty() && (list.front() < physical_locator))
{
local_lower_interface = true;
}
}

// If the remote physical port is higher than our listening port, a new CONNECT channel needs to be created and connected
// and the locator added to the send_resource_list.
// If the remote physical port is lower than our listening port, only the locator needs to be added to the send_resource_list.
if (IPLocator::getPhysicalPort(physical_locator) > listening_port)
if (IPLocator::getPhysicalPort(physical_locator) > listening_port || local_lower_interface)
{
// Client side (either Server-Client or LARGE_DATA)
EPROSIMA_LOG_INFO(OpenOutputChannel, "OpenOutputChannel: [CONNECT] (physical: "
Expand Down
28 changes: 28 additions & 0 deletions test/unittest/transport/TCPv4Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2047,6 +2047,34 @@ TEST_F(TCPv4Tests, reconnect_after_open_port_failure)
client_resource_list.clear();
}

// This test verifies that OpenOutputChannel correctly handles a remote locator with
// same physical port as the local listening port.
TEST_F(TCPv4Tests, opening_output_channel_with_same_locator_as_local_listening_port)
{
TCPv4Transport transportUnderTest(descriptor);
transportUnderTest.init();

// Two locators with the same port as the local listening port, but different addresses
Locator_t lowerOutputChannelLocator;
lowerOutputChannelLocator.kind = LOCATOR_KIND_TCPv4;
lowerOutputChannelLocator.port = g_default_port;
IPLocator::setLogicalPort(lowerOutputChannelLocator, g_default_port);
Locator_t higherOutputChannelLocator = lowerOutputChannelLocator;
IPLocator::setIPv4(lowerOutputChannelLocator, 1, 1, 1, 1);
IPLocator::setIPv4(higherOutputChannelLocator, 255, 255, 255, 255);

SendResourceList send_resource_list;

// If the remote address is lower than the local one, no channel must be created but it must be added to the send_resource_list
ASSERT_TRUE(transportUnderTest.OpenOutputChannel(send_resource_list, lowerOutputChannelLocator));
ASSERT_FALSE(transportUnderTest.is_output_channel_open_for(lowerOutputChannelLocator));
ASSERT_EQ(send_resource_list.size(), 1);
// If the remote address is higher than the local one, a CONNECT channel must be created and added to the send_resource_list
ASSERT_TRUE(transportUnderTest.OpenOutputChannel(send_resource_list, higherOutputChannelLocator));
ASSERT_TRUE(transportUnderTest.is_output_channel_open_for(higherOutputChannelLocator));
ASSERT_EQ(send_resource_list.size(), 2);
}

void TCPv4Tests::HELPER_SetDescriptorDefaults()
{
descriptor.add_listener_port(g_default_port);
Expand Down
27 changes: 27 additions & 0 deletions test/unittest/transport/TCPv6Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,33 @@ TEST_F(TCPv6Tests, reconnect_after_open_port_failure)
client_resource_list.clear();
}

TEST_F(TCPv6Tests, opening_output_channel_with_same_locator_as_local_listening_port)
{
descriptor.add_listener_port(g_default_port);
TCPv6Transport transportUnderTest(descriptor);
transportUnderTest.init();

// Two locators with the same port as the local listening port, but different addresses
Locator_t lowerOutputChannelLocator;
lowerOutputChannelLocator.kind = LOCATOR_KIND_TCPv6;
lowerOutputChannelLocator.port = g_default_port;
IPLocator::setLogicalPort(lowerOutputChannelLocator, g_default_port);
Locator_t higherOutputChannelLocator = lowerOutputChannelLocator;
IPLocator::setIPv6(lowerOutputChannelLocator, "::");
IPLocator::setIPv6(higherOutputChannelLocator, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");

SendResourceList send_resource_list;

// If the remote address is lower than the local one, no channel must be created but it must be added to the send_resource_list
ASSERT_TRUE(transportUnderTest.OpenOutputChannel(send_resource_list, lowerOutputChannelLocator));
ASSERT_FALSE(transportUnderTest.is_output_channel_open_for(lowerOutputChannelLocator));
ASSERT_EQ(send_resource_list.size(), 1);
// If the remote address is higher than the local one, a CONNECT channel must be created and added to the send_resource_list
ASSERT_TRUE(transportUnderTest.OpenOutputChannel(send_resource_list, higherOutputChannelLocator));
ASSERT_TRUE(transportUnderTest.is_output_channel_open_for(higherOutputChannelLocator));
ASSERT_EQ(send_resource_list.size(), 2);
}

/*
TEST_F(TCPv6Tests, send_and_receive_between_both_secure_ports)
{
Expand Down
Loading