From b7a7890027f6621164ead7b50959bb45f9b02998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Ferreira=20Gonz=C3=A1lez?= Date: Thu, 22 Feb 2024 15:08:24 +0100 Subject: [PATCH] LARGE_DATA Participants logic with same listening ports (#4396) * Refs #20438: Add unittest to validate interfaces check Signed-off-by: cferreiragonz * Refs #20438: Add support to same listening_port and different IP address Signed-off-by: cferreiragonz * Refs #20438: Fix Windows build Signed-off-by: cferreiragonz * Refs #20438: Add Ipv6 addresses support Signed-off-by: cferreiragonz * Refs #20438: Remove repeated addition of listener port (added by default) Signed-off-by: cferreiragonz * Refs #20438: Apply suggestions Signed-off-by: cferreiragonz * Refs #20438: Apply suggestions: ipv6 Signed-off-by: cferreiragonz * Refs #20438: Fix windows build Signed-off-by: cferreiragonz --------- Signed-off-by: cferreiragonz (cherry picked from commit 3ff9180617ef9f1cb845d0718edecfee6649c8e1) --- .../rtps/transport/TCPTransportInterface.cpp | 23 ++++++++++++++- test/unittest/transport/TCPv4Tests.cpp | 28 +++++++++++++++++++ test/unittest/transport/TCPv6Tests.cpp | 27 ++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/cpp/rtps/transport/TCPTransportInterface.cpp b/src/cpp/rtps/transport/TCPTransportInterface.cpp index a870807d69e..ba743d4e4e0 100644 --- a/src/cpp/rtps/transport/TCPTransportInterface.cpp +++ b/src/cpp/rtps/transport/TCPTransportInterface.cpp @@ -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 list; + std::vector 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: " diff --git a/test/unittest/transport/TCPv4Tests.cpp b/test/unittest/transport/TCPv4Tests.cpp index 9fbe3dccb77..f2fe1acb9b0 100644 --- a/test/unittest/transport/TCPv4Tests.cpp +++ b/test/unittest/transport/TCPv4Tests.cpp @@ -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); diff --git a/test/unittest/transport/TCPv6Tests.cpp b/test/unittest/transport/TCPv6Tests.cpp index 596e2460acc..994ea001829 100644 --- a/test/unittest/transport/TCPv6Tests.cpp +++ b/test/unittest/transport/TCPv6Tests.cpp @@ -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) {