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

[20019] Add Autofill port to TCP Transport (backport #4061) #4104

Merged
merged 2 commits into from
Dec 12, 2023
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
2 changes: 2 additions & 0 deletions src/cpp/rtps/transport/TCPAcceptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ TCPAcceptor::TCPAcceptor(
, locator_(locator)
, io_service_(&io_service)
{
locator_.port = acceptor_.local_endpoint().port();
endpoint_ = asio::ip::tcp::endpoint(parent->generate_protocol(), IPLocator::getPhysicalPort(locator_));
}

Expand All @@ -43,6 +44,7 @@ TCPAcceptor::TCPAcceptor(
, locator_(locator)
, io_service_(&io_service)
{
locator_.port = acceptor_.local_endpoint().port();
endpoint_ = asio::ip::tcp::endpoint(asio::ip::address_v4::from_string(interface),
IPLocator::getPhysicalPort(locator_));
}
Expand Down
17 changes: 11 additions & 6 deletions src/cpp/rtps/transport/TCPTransportInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,10 @@ void TCPTransportInterface::calculate_crc(
header.crc = crc;
}

bool TCPTransportInterface::create_acceptor_socket(
uint16_t TCPTransportInterface::create_acceptor_socket(
const Locator& locator)
{
uint16_t final_port = 0;
try
{
if (is_interface_whitelist_empty())
Expand All @@ -264,16 +265,18 @@ bool TCPTransportInterface::create_acceptor_socket(
{
std::shared_ptr<TCPAcceptorSecure> acceptor =
std::make_shared<TCPAcceptorSecure>(io_service_, this, locator);
acceptors_[locator] = acceptor;
acceptors_[acceptor->locator()] = acceptor;
acceptor->accept(this, ssl_context_);
final_port = static_cast<uint16_t>(acceptor->locator().port);
}
else
#endif // if TLS_FOUND
{
std::shared_ptr<TCPAcceptorBasic> acceptor =
std::make_shared<TCPAcceptorBasic>(io_service_, this, locator);
acceptors_[locator] = acceptor;
acceptors_[acceptor->locator()] = acceptor;
acceptor->accept(this);
final_port = static_cast<uint16_t>(acceptor->locator().port);
}

logInfo(RTCP, " OpenAndBindInput (physical: " << IPLocator::getPhysicalPort(locator) << "; logical: "
Expand All @@ -290,16 +293,18 @@ bool TCPTransportInterface::create_acceptor_socket(
{
std::shared_ptr<TCPAcceptorSecure> acceptor =
std::make_shared<TCPAcceptorSecure>(io_service_, sInterface, locator);
acceptors_[locator] = acceptor;
acceptors_[acceptor->locator()] = acceptor;
acceptor->accept(this, ssl_context_);
final_port = static_cast<uint16_t>(acceptor->locator().port);
}
else
#endif // if TLS_FOUND
{
std::shared_ptr<TCPAcceptorBasic> acceptor =
std::make_shared<TCPAcceptorBasic>(io_service_, sInterface, locator);
acceptors_[locator] = acceptor;
acceptors_[acceptor->locator()] = acceptor;
acceptor->accept(this);
final_port = static_cast<uint16_t>(acceptor->locator().port);
}

logInfo(RTCP, " OpenAndBindInput (physical: " << IPLocator::getPhysicalPort(locator) << "; logical: "
Expand All @@ -322,7 +327,7 @@ bool TCPTransportInterface::create_acceptor_socket(
return false;
}

return true;
return final_port;
}

void TCPTransportInterface::fill_rtcp_header(
Expand Down
2 changes: 1 addition & 1 deletion src/cpp/rtps/transport/TCPTransportInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class TCPTransportInterface : public TransportInterface
std::shared_ptr<TCPChannelResource>& channel);

//! Creates a TCP acceptor to wait for incoming connections by the given locator.
bool create_acceptor_socket(
uint16_t create_acceptor_socket(
const Locator& locator);

virtual void get_ips(
Expand Down
4 changes: 2 additions & 2 deletions src/cpp/rtps/transport/TCPv4Transport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ TCPv4Transport::TCPv4Transport(
interface_whitelist_.emplace_back(ip::address_v4::from_string(interface));
}

for (uint16_t port : configuration_.listening_ports)
for (uint16_t& port : configuration_.listening_ports)
{
Locator locator(LOCATOR_KIND_TCPv4, port);
create_acceptor_socket(locator);
port = create_acceptor_socket(locator);
}

#if !TLS_FOUND
Expand Down
4 changes: 2 additions & 2 deletions src/cpp/rtps/transport/TCPv6Transport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ TCPv6Transport::TCPv6Transport(
interface_whitelist_.emplace_back(ip::address_v6::from_string(interface));
}

for (uint16_t port : configuration_.listening_ports)
for (uint16_t& port : configuration_.listening_ports)
{
Locator locator(LOCATOR_KIND_TCPv6, port);
create_acceptor_socket(locator);
port = create_acceptor_socket(locator);
}

#if !TLS_FOUND
Expand Down
2 changes: 1 addition & 1 deletion test/blackbox/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ if(FASTRTPS_API_TESTS)
GTest::gtest
$<$<BOOL:${LibP11_FOUND}>:eProsima_p11> # $<TARGET_NAME_IF_EXISTS:eProsima_p11>
)

add_blackbox_gtest(BlackboxTests_FastRTPS SOURCES ${BLACKBOXTESTS_TEST_SOURCE}
ENVIRONMENTS "CERTS_PATH=${PROJECT_SOURCE_DIR}/test/certs"
"TOPIC_RANDOM_NUMBER=${TOPIC_RANDOM_NUMBER}"
Expand Down
66 changes: 64 additions & 2 deletions test/blackbox/common/BlackboxTestsTransportTCP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "BlackboxTests.hpp"
#include "TCPReqRepHelloWorldRequester.hpp"
#include "TCPReqRepHelloWorldReplier.hpp"
#include "PubSubReader.hpp"
#include "PubSubWriter.hpp"

#include <gtest/gtest.h>

Expand Down Expand Up @@ -526,7 +528,7 @@ TEST_P(TransportTCP, TCPv6_equal_operator)
// Test copy constructor and copy assignment for TCPv6
TEST_P(TransportTCP, TCPv6_copy)
{
// Change some varibles in order to check the non default cretion
// Change some varibles in order to check the non default creation
TCPv6TransportDescriptor tcpv6_transport;
tcpv6_transport.enable_tcp_nodelay = !tcpv6_transport.enable_tcp_nodelay; // change default value
tcpv6_transport.max_logical_port = tcpv6_transport.max_logical_port + 10; // change default value
Expand Down Expand Up @@ -602,6 +604,66 @@ TEST(TransportTCP, Client_reconnection)
delete requester;
}

// Test copy constructor and copy assignment for TCPv4
TEST_P(TransportTCP, TCPv4_autofill_port)
{
PubSubReader<HelloWorldPubSubType> p1(TEST_TOPIC_NAME);
PubSubReader<HelloWorldPubSubType> p2(TEST_TOPIC_NAME);

// Add TCP Transport with listening port 0
auto p1_transport = std::make_shared<TCPv4TransportDescriptor>();
p1_transport->add_listener_port(0);
p1.disable_builtin_transport().add_user_transport_to_pparams(p1_transport);
p1.init();
ASSERT_TRUE(p1.isInitialized());

// Add TCP Transport with listening port different from 0
uint16_t port = 12345;
auto p2_transport = std::make_shared<TCPv4TransportDescriptor>();
p2_transport->add_listener_port(port);
p2.disable_builtin_transport().add_user_transport_to_pparams(p2_transport);
p2.init();
ASSERT_TRUE(p2.isInitialized());

LocatorList_t p1_locators;
p1.get_native_reader().get_listening_locators(p1_locators);
EXPECT_TRUE(IPLocator::getPhysicalPort(p1_locators.begin()[0]) != 0);

LocatorList_t p2_locators;
p2.get_native_reader().get_listening_locators(p2_locators);
EXPECT_TRUE(IPLocator::getPhysicalPort(p2_locators.begin()[0]) == port);
}

// Test copy constructor and copy assignment for TCPv6
TEST_P(TransportTCP, TCPv6_autofill_port)
{
PubSubReader<HelloWorldPubSubType> p1(TEST_TOPIC_NAME);
PubSubReader<HelloWorldPubSubType> p2(TEST_TOPIC_NAME);

// Add TCP Transport with listening port 0
auto p1_transport = std::make_shared<TCPv6TransportDescriptor>();
p1_transport->add_listener_port(0);
p1.disable_builtin_transport().add_user_transport_to_pparams(p1_transport);
p1.init();
ASSERT_TRUE(p1.isInitialized());

// Add TCP Transport with listening port different from 0
uint16_t port = 12345;
auto p2_transport = std::make_shared<TCPv6TransportDescriptor>();
p2_transport->add_listener_port(port);
p2.disable_builtin_transport().add_user_transport_to_pparams(p2_transport);
p2.init();
ASSERT_TRUE(p2.isInitialized());

LocatorList_t p1_locators;
p1.get_native_reader().get_listening_locators(p1_locators);
EXPECT_TRUE(IPLocator::getPhysicalPort(p1_locators.begin()[0]) != 0);

LocatorList_t p2_locators;
p2.get_native_reader().get_listening_locators(p2_locators);
EXPECT_TRUE(IPLocator::getPhysicalPort(p2_locators.begin()[0]) == port);
}

#ifdef INSTANTIATE_TEST_SUITE_P
#define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_SUITE_P(x, y, z, w)
#else
Expand All @@ -622,4 +684,4 @@ GTEST_INSTANTIATE_TEST_MACRO(TransportTCP,
return "Transport" + suffix;
}

});
});
38 changes: 38 additions & 0 deletions test/unittest/transport/TCPv4Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1508,6 +1508,44 @@ TEST_F(TCPv4Tests, header_read_interrumption)
thread.join();
}

// This test verifies that the autofill port feature correctly sets an automatic port when
// the descriptors's port is set to 0.
TEST_F(TCPv4Tests, autofill_port)
{
// Check normal port assignation
TCPv4TransportDescriptor test_descriptor;
test_descriptor.add_listener_port(g_default_port);
TCPv4Transport transportUnderTest(test_descriptor);
transportUnderTest.init();

EXPECT_TRUE(transportUnderTest.configuration()->listening_ports[0] == g_default_port);

// Check default port assignation
TCPv4TransportDescriptor test_descriptor_autofill;
test_descriptor_autofill.add_listener_port(0);
TCPv4Transport transportUnderTest_autofill(test_descriptor_autofill);
transportUnderTest_autofill.init();

EXPECT_TRUE(transportUnderTest_autofill.configuration()->listening_ports[0] != 0);
EXPECT_TRUE(transportUnderTest_autofill.configuration()->listening_ports.size() == 1);

uint16_t port = 12345;
TCPv4TransportDescriptor test_descriptor_multiple_autofill;
test_descriptor_multiple_autofill.add_listener_port(0);
test_descriptor_multiple_autofill.add_listener_port(port);
test_descriptor_multiple_autofill.add_listener_port(0);
TCPv4Transport transportUnderTest_multiple_autofill(test_descriptor_multiple_autofill);
transportUnderTest_multiple_autofill.init();

EXPECT_TRUE(transportUnderTest_multiple_autofill.configuration()->listening_ports[0] != 0);
EXPECT_TRUE(transportUnderTest_multiple_autofill.configuration()->listening_ports[1] == port);
EXPECT_TRUE(transportUnderTest_multiple_autofill.configuration()->listening_ports[2] != 0);
EXPECT_TRUE(
transportUnderTest_multiple_autofill.configuration()->listening_ports[0] !=
transportUnderTest_multiple_autofill.configuration()->listening_ports[2]);
EXPECT_TRUE(transportUnderTest_multiple_autofill.configuration()->listening_ports.size() == 3);
}

void TCPv4Tests::HELPER_SetDescriptorDefaults()
{
descriptor.add_listener_port(g_default_port);
Expand Down
38 changes: 38 additions & 0 deletions test/unittest/transport/TCPv6Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,44 @@ TEST_F(TCPv6Tests, opening_and_closing_input_channel)
ASSERT_FALSE (transportUnderTest.IsInputChannelOpen(multicastFilterLocator));
ASSERT_FALSE (transportUnderTest.CloseInputChannel(multicastFilterLocator));
}

// This test verifies that the autofill port feature correctly sets an automatic port when
// the descriptors's port is set to 0.
TEST_F(TCPv6Tests, autofill_port)
{
// Check normal port assignation
TCPv6TransportDescriptor test_descriptor;
test_descriptor.add_listener_port(g_default_port);
TCPv6Transport transportUnderTest(test_descriptor);
transportUnderTest.init();

EXPECT_TRUE(transportUnderTest.configuration()->listening_ports[0] == g_default_port);

// Check default port assignation
TCPv6TransportDescriptor test_descriptor_autofill;
test_descriptor_autofill.add_listener_port(0);
TCPv6Transport transportUnderTest_autofill(test_descriptor_autofill);
transportUnderTest_autofill.init();

EXPECT_TRUE(transportUnderTest_autofill.configuration()->listening_ports[0] != 0);
EXPECT_TRUE(transportUnderTest_autofill.configuration()->listening_ports.size() == 1);

uint16_t port = 12345;
TCPv6TransportDescriptor test_descriptor_multiple_autofill;
test_descriptor_multiple_autofill.add_listener_port(0);
test_descriptor_multiple_autofill.add_listener_port(port);
test_descriptor_multiple_autofill.add_listener_port(0);
TCPv6Transport transportUnderTest_multiple_autofill(test_descriptor_multiple_autofill);
transportUnderTest_multiple_autofill.init();

EXPECT_TRUE(transportUnderTest_multiple_autofill.configuration()->listening_ports[0] != 0);
EXPECT_TRUE(transportUnderTest_multiple_autofill.configuration()->listening_ports[1] == port);
EXPECT_TRUE(transportUnderTest_multiple_autofill.configuration()->listening_ports[2] != 0);
EXPECT_TRUE(
transportUnderTest_multiple_autofill.configuration()->listening_ports[0] !=
transportUnderTest_multiple_autofill.configuration()->listening_ports[2]);
EXPECT_TRUE(transportUnderTest_multiple_autofill.configuration()->listening_ports.size() == 3);
}
/*
TEST_F(TCPv6Tests, send_and_receive_between_both_secure_ports)
{
Expand Down
Loading