Skip to content

Commit 9f63e89

Browse files
committed
Enabling multiple interfaces through whitelist in TCP servers (#4297)
* Refs #20238: Add whitelist test in TCPv4 Signed-off-by: cferreiragonz <[email protected]> * Refs #20238: Add whitelist test in TCPv6 Signed-off-by: cferreiragonz <[email protected]> * Refs #20238: Adding interface to locator if whitelist is not empty Signed-off-by: cferreiragonz <[email protected]> * Refs #20238: Uncrustify Signed-off-by: cferreiragonz <[email protected]> * Refs #20238: Fix build in Windows Signed-off-by: cferreiragonz <[email protected]> * Refs #20238: Apply suggestions Signed-off-by: cferreiragonz <[email protected]> * Refs #20238: Remove repeated addition of listener port (added by default) Signed-off-by: cferreiragonz <[email protected]> --------- Signed-off-by: cferreiragonz <[email protected]> (cherry picked from commit 5f65a65)
1 parent 88fe9f3 commit 9f63e89

File tree

5 files changed

+153
-2
lines changed

5 files changed

+153
-2
lines changed

src/cpp/rtps/transport/TCPTransportInterface.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,11 +298,20 @@ uint16_t TCPTransportInterface::create_acceptor_socket(
298298
std::vector<std::string> vInterfaces = get_binding_interfaces_list();
299299
for (std::string& sInterface : vInterfaces)
300300
{
301+
Locator loc = locator;
302+
if (loc.kind == LOCATOR_KIND_TCPv4)
303+
{
304+
IPLocator::setIPv4(loc, sInterface);
305+
}
306+
else if (loc.kind == LOCATOR_KIND_TCPv6)
307+
{
308+
IPLocator::setIPv6(loc, sInterface);
309+
}
301310
#if TLS_FOUND
302311
if (configuration()->apply_security)
303312
{
304313
std::shared_ptr<TCPAcceptorSecure> acceptor =
305-
std::make_shared<TCPAcceptorSecure>(io_service_, sInterface, locator);
314+
std::make_shared<TCPAcceptorSecure>(io_service_, sInterface, loc);
306315
acceptors_[acceptor->locator()] = acceptor;
307316
acceptor->accept(this, ssl_context_);
308317
final_port = static_cast<uint16_t>(acceptor->locator().port);
@@ -311,7 +320,7 @@ uint16_t TCPTransportInterface::create_acceptor_socket(
311320
#endif // if TLS_FOUND
312321
{
313322
std::shared_ptr<TCPAcceptorBasic> acceptor =
314-
std::make_shared<TCPAcceptorBasic>(io_service_, sInterface, locator);
323+
std::make_shared<TCPAcceptorBasic>(io_service_, sInterface, loc);
315324
acceptors_[acceptor->locator()] = acceptor;
316325
acceptor->accept(this);
317326
final_port = static_cast<uint16_t>(acceptor->locator().port);

test/unittest/transport/TCPv4Tests.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,64 @@ TEST_F(TCPv4Tests, send_and_receive_between_allowed_interfaces_ports)
463463
}
464464
}
465465

466+
static void GetIP4s(
467+
std::vector<IPFinder::info_IP>& interfaces)
468+
{
469+
IPFinder::getIPs(&interfaces, false);
470+
auto new_end = remove_if(interfaces.begin(),
471+
interfaces.end(),
472+
[](IPFinder::info_IP ip)
473+
{
474+
return ip.type != IPFinder::IP4 && ip.type != IPFinder::IP4_LOCAL;
475+
});
476+
interfaces.erase(new_end, interfaces.end());
477+
std::for_each(interfaces.begin(), interfaces.end(), [](IPFinder::info_IP& loc)
478+
{
479+
loc.locator.kind = LOCATOR_KIND_TCPv4;
480+
});
481+
}
482+
483+
TEST_F(TCPv4Tests, check_TCPv4_interface_whitelist_initialization)
484+
{
485+
std::vector<IPFinder::info_IP> interfaces;
486+
487+
GetIP4s(interfaces);
488+
489+
std::vector<std::string> mock_interfaces;
490+
for (auto& ip : interfaces)
491+
{
492+
mock_interfaces.push_back(ip.name);
493+
}
494+
// Add manually localhost to test adding multiple interfaces
495+
mock_interfaces.push_back("127.0.0.1");
496+
497+
for (auto& ip : mock_interfaces)
498+
{
499+
descriptor.interfaceWhiteList.emplace_back(ip);
500+
}
501+
MockTCPv4Transport transportUnderTest(descriptor);
502+
transportUnderTest.init();
503+
504+
// Check that the transport whitelist and the acceptors map is the same size as the mock_interfaces
505+
ASSERT_EQ(transportUnderTest.get_interface_whitelist().size(), descriptor.interfaceWhiteList.size());
506+
ASSERT_EQ(transportUnderTest.get_acceptors_map().size(), descriptor.interfaceWhiteList.size());
507+
508+
// Check that every interface is in the whitelist
509+
auto check_whitelist = transportUnderTest.get_interface_whitelist();
510+
for (auto& ip : mock_interfaces)
511+
{
512+
ASSERT_NE(std::find(check_whitelist.begin(), check_whitelist.end(), asio::ip::address_v4::from_string(
513+
ip)), check_whitelist.end());
514+
}
515+
516+
// Check that every interface is in the acceptors map
517+
for (const auto& test : transportUnderTest.get_acceptors_map())
518+
{
519+
ASSERT_NE(std::find(mock_interfaces.begin(), mock_interfaces.end(), IPLocator::toIPv4string(
520+
test.first)), mock_interfaces.end());
521+
}
522+
}
523+
466524
#if TLS_FOUND
467525
TEST_F(TCPv4Tests, send_and_receive_between_secure_ports_client_verifies)
468526
{

test/unittest/transport/TCPv6Tests.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,70 @@ TEST_F(TCPv6Tests, autofill_port)
205205
EXPECT_TRUE(transportUnderTest_multiple_autofill.configuration()->listening_ports.size() == 3);
206206
}
207207

208+
static void GetIP6s(
209+
std::vector<IPFinder::info_IP>& interfaces)
210+
{
211+
IPFinder::getIPs(&interfaces, false);
212+
auto new_end = remove_if(interfaces.begin(),
213+
interfaces.end(),
214+
[](IPFinder::info_IP ip)
215+
{
216+
return ip.type != IPFinder::IP6 && ip.type != IPFinder::IP6_LOCAL;
217+
});
218+
interfaces.erase(new_end, interfaces.end());
219+
std::for_each(interfaces.begin(), interfaces.end(), [](IPFinder::info_IP& loc)
220+
{
221+
loc.locator.kind = LOCATOR_KIND_TCPv6;
222+
});
223+
}
224+
225+
TEST_F(TCPv6Tests, check_TCPv6_interface_whitelist_initialization)
226+
{
227+
std::vector<IPFinder::info_IP> interfaces;
228+
229+
GetIP6s(interfaces);
230+
231+
// asio::ip::addres_v6 appends the interface name to the IP address, but the locator does not
232+
// Create two different vectors to compare them
233+
std::vector<std::string> asio_interfaces;
234+
std::vector<std::string> locator_interfaces;
235+
for (auto& ip : interfaces)
236+
{
237+
asio_interfaces.push_back(ip.name);
238+
locator_interfaces.push_back(IPLocator::toIPv6string(ip.locator));
239+
}
240+
// Add manually localhost to test adding multiple interfaces
241+
asio_interfaces.push_back("::1");
242+
locator_interfaces.push_back("::1");
243+
244+
for (auto& ip : locator_interfaces)
245+
{
246+
descriptor.interfaceWhiteList.emplace_back(ip);
247+
}
248+
descriptor.add_listener_port(g_default_port);
249+
MockTCPv6Transport transportUnderTest(descriptor);
250+
transportUnderTest.init();
251+
252+
// Check that the transport whitelist and the acceptors map is the same size as the locator_interfaces
253+
ASSERT_EQ(transportUnderTest.get_interface_whitelist().size(), descriptor.interfaceWhiteList.size());
254+
ASSERT_EQ(transportUnderTest.get_acceptors_map().size(), descriptor.interfaceWhiteList.size());
255+
256+
// Check that every interface is in the whitelist
257+
auto check_whitelist = transportUnderTest.get_interface_whitelist();
258+
for (auto& ip : asio_interfaces)
259+
{
260+
ASSERT_NE(std::find(check_whitelist.begin(), check_whitelist.end(), asio::ip::address_v6::from_string(
261+
ip)), check_whitelist.end());
262+
}
263+
264+
// Check that every interface is in the acceptors map
265+
for (const auto& test : transportUnderTest.get_acceptors_map())
266+
{
267+
ASSERT_NE(std::find(locator_interfaces.begin(), locator_interfaces.end(), IPLocator::toIPv6string(
268+
test.first)), locator_interfaces.end());
269+
}
270+
}
271+
208272
// This test verifies server's channel resources mapping keys uniqueness, where keys are clients locators.
209273
// Clients typically communicated its PID as its locator port. When having several clients in the same
210274
// process this lead to overwriting server's channel resources map elements.

test/unittest/transport/mock/MockTCPv4Transport.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ class MockTCPv4Transport : public TCPv4Transport
4646
return unbound_channel_resources_;
4747
}
4848

49+
const std::vector<asio::ip::address_v4>& get_interface_whitelist() const
50+
{
51+
return interface_whitelist_;
52+
}
53+
54+
const std::map<Locator_t, std::shared_ptr<fastdds::rtps::TCPAcceptor>>& get_acceptors_map() const
55+
{
56+
return acceptors_;
57+
}
58+
4959
};
5060

5161
} // namespace rtps

test/unittest/transport/mock/MockTCPv6Transport.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ class MockTCPv6Transport : public TCPv6Transport
4646
return unbound_channel_resources_;
4747
}
4848

49+
const std::vector<asio::ip::address_v6>& get_interface_whitelist() const
50+
{
51+
return interface_whitelist_;
52+
}
53+
54+
const std::map<Locator_t, std::shared_ptr<fastdds::rtps::TCPAcceptor>>& get_acceptors_map() const
55+
{
56+
return acceptors_;
57+
}
58+
4959
};
5060

5161
} // namespace rtps

0 commit comments

Comments
 (0)