Skip to content

Commit

Permalink
Use SO_EXCLUSIVEADDRUSE for Win32 unicast listening sockets (#4056)
Browse files Browse the repository at this point in the history
* Refs #19587. Added regression unit tests.

Signed-off-by: Miguel Company <[email protected]>

* Refs #19587. Added regression blackbox test.

Signed-off-by: Miguel Company <[email protected]>

* Refs #19587. Fix issue.

Signed-off-by: Miguel Company <[email protected]>

* Refs #19587. Linters.

Signed-off-by: Miguel Company <[email protected]>

---------

Signed-off-by: Miguel Company <[email protected]>
  • Loading branch information
MiguelCompany authored Nov 30, 2023
1 parent ba4c03b commit bb2702b
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/cpp/rtps/transport/UDPv4Transport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,13 @@ eProsimaUDPSocket UDPv4Transport::OpenAndBindInputSocket(
ASIO_OS_DEF(SOL_SOCKET), SO_REUSEPORT>(true));
#endif // if defined(__QNX__)
}
else
{
#if defined(_WIN32)
getSocketPtr(socket)->set_option(asio::detail::socket_option::integer<
ASIO_OS_DEF(SOL_SOCKET), SO_EXCLUSIVEADDRUSE>(1));
#endif // if defined(_WIN32)
}

getSocketPtr(socket)->bind(generate_endpoint(sIp, port));
return socket;
Expand Down
7 changes: 7 additions & 0 deletions src/cpp/rtps/transport/UDPv6Transport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,13 @@ eProsimaUDPSocket UDPv6Transport::OpenAndBindInputSocket(
ASIO_OS_DEF(SOL_SOCKET), SO_REUSEPORT>(true));
#endif // if defined(__QNX__)
}
else
{
#if defined(_WIN32)
getSocketPtr(socket)->set_option(asio::detail::socket_option::integer<
ASIO_OS_DEF(SOL_SOCKET), SO_EXCLUSIVEADDRUSE>(1));
#endif // if defined(_WIN32)
}

getSocketPtr(socket)->bind(generate_endpoint(sIp, port));

Expand Down
31 changes: 31 additions & 0 deletions test/blackbox/common/BlackboxTestsNetworkConf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,37 @@ TEST_P(NetworkConfig, PubGetSendingLocatorsWhitelist)
}
}

// Regression test for redmine issue #19587
TEST_P(NetworkConfig, double_binding_fails)
{
PubSubReader<HelloWorldPubSubType> p1(TEST_TOPIC_NAME);
PubSubReader<HelloWorldPubSubType> p2(TEST_TOPIC_NAME);

// Create a participant without whitelist
p1.disable_builtin_transport().add_user_transport_to_pparams(descriptor_);
p1.init();
ASSERT_TRUE(p1.isInitialized());

// Add the announced addresses to the interface whitelist
LocatorList_t locators_p1;
p1.get_native_reader().get_listening_locators(locators_p1);
for (const auto& loc : locators_p1)
{
descriptor_->interfaceWhiteList.push_back(IPLocator::ip_to_string(loc));
}

// Try to listen on the same locators as the first participant
p2.disable_builtin_transport().add_user_transport_to_pparams(descriptor_);
p2.set_default_unicast_locators(locators_p1);
p2.init();
ASSERT_TRUE(p2.isInitialized());

// Should be listening on different locators
LocatorList_t locators_p2;
p2.get_native_reader().get_listening_locators(locators_p2);
EXPECT_FALSE(locators_p1 == locators_p2);
}

#ifdef INSTANTIATE_TEST_SUITE_P
#define GTEST_INSTANTIATE_TEST_MACRO(x, y, z, w) INSTANTIATE_TEST_SUITE_P(x, y, z, w)
#else
Expand Down
21 changes: 21 additions & 0 deletions test/unittest/transport/UDPv4Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,27 @@ TEST_F(UDPv4Tests, simple_throughput)
, std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0).count() / (num_samples_per_batch * 1000.0));
}

// Regression test for redmine issue #19587
TEST_F(UDPv4Tests, double_binding_fails)
{
auto whitelist_descriptor = descriptor;
whitelist_descriptor.interfaceWhiteList.emplace_back("127.0.0.1");

UDPv4Transport default_transport(descriptor);
UDPv4Transport whitelist_transport(whitelist_descriptor);

Locator_t locator;
IPLocator::createLocator(LOCATOR_KIND_UDPv4, "127.0.0.1", g_default_port, locator);

MockReceiverResource whitelist_receiver(whitelist_transport, locator);
EXPECT_TRUE(whitelist_receiver.is_valid());
EXPECT_TRUE(whitelist_transport.IsInputChannelOpen(locator));

MockReceiverResource default_receiver(default_transport, locator);
EXPECT_FALSE(default_receiver.is_valid());
EXPECT_FALSE(default_transport.IsInputChannelOpen(locator));
}

void UDPv4Tests::HELPER_SetDescriptorDefaults()
{
descriptor.maxMessageSize = 5;
Expand Down
21 changes: 21 additions & 0 deletions test/unittest/transport/UDPv6Tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,27 @@ TEST_F(UDPv6Tests, simple_throughput)
, std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0).count() / (num_samples_per_batch * 1000.0));
}

// Regression test for redmine issue #19587
TEST_F(UDPv6Tests, double_binding_fails)
{
auto whitelist_descriptor = descriptor;
whitelist_descriptor.interfaceWhiteList.emplace_back("::1");

UDPv6Transport default_transport(descriptor);
UDPv6Transport whitelist_transport(whitelist_descriptor);

Locator_t locator;
IPLocator::createLocator(LOCATOR_KIND_UDPv6, "::1", g_default_port, locator);

MockReceiverResource whitelist_receiver(whitelist_transport, locator);
EXPECT_TRUE(whitelist_receiver.is_valid());
EXPECT_TRUE(whitelist_transport.IsInputChannelOpen(locator));

MockReceiverResource default_receiver(default_transport, locator);
EXPECT_FALSE(default_receiver.is_valid());
EXPECT_FALSE(default_transport.IsInputChannelOpen(locator));
}

void UDPv6Tests::HELPER_SetDescriptorDefaults()
{
descriptor.maxMessageSize = 5;
Expand Down
5 changes: 5 additions & 0 deletions test/unittest/transport/mock/MockReceiverResource.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ class MockReceiverResource : public ReceiverResource
{
public:

bool is_valid() const
{
return mValid;
}

virtual void OnDataReceived(
const octet*,
const uint32_t,
Expand Down

0 comments on commit bb2702b

Please sign in to comment.