Skip to content

Commit 74f0a3c

Browse files
Hotfix: Secure simple participants with initialpeers over TCP match (#5071) (#5176)
* Refs #20181: Add BB test Signed-off-by: Mario Dominguez <[email protected]> * Refs #20181: Add Fix Signed-off-by: Mario Dominguez <[email protected]> * Refs #20181: linter Signed-off-by: Mario Dominguez <[email protected]> * Refs #20181. Pass in secure_endpoints as lambda capture. Signed-off-by: Miguel Company <[email protected]> * Refs #20181. New approach. Automatically sending DATA(p) when receiving a DATA(p) could lead to an infinite ping-pong between the two participants. This resulted in some cases in the transport threads eating all CPU resources. The new approach matches the discovered participant to the builtin non-secure PDP writer, so it will receive the DATA(p) of the local participant in the next periodic announcement. Signed-off-by: Miguel Company <[email protected]> * Refs #20181. Unmatch non-secure before matching secure. Signed-off-by: Miguel Company <[email protected]> --------- Signed-off-by: Mario Dominguez <[email protected]> Signed-off-by: Miguel Company <[email protected]> Co-authored-by: Miguel Company <[email protected]> (cherry picked from commit 3ca60e0) # Conflicts: # src/cpp/rtps/builtin/discovery/participant/PDPSimple.cpp # test/blackbox/common/BlackboxTestsSecurity.cpp Co-authored-by: Mario Domínguez López <[email protected]>
1 parent 1970c71 commit 74f0a3c

File tree

3 files changed

+101
-9
lines changed

3 files changed

+101
-9
lines changed

include/fastdds/rtps/builtin/discovery/participant/PDPSimple.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,16 @@ class PDPSimple : public PDP
143143

144144
void match_pdp_remote_endpoints(
145145
const ParticipantProxyData& pdata,
146-
bool notify_secure_endpoints);
146+
bool notify_secure_endpoints,
147+
bool writer_only);
148+
149+
/**
150+
* @brief Unmatch PDP endpoints with a remote participant.
151+
*
152+
* @param participant_guid GUID of the remote participant.
153+
*/
154+
void unmatch_pdp_remote_endpoints(
155+
const GUID_t& participant_guid);
147156

148157
void assign_low_level_remote_endpoints(
149158
const ParticipantProxyData& pdata,

src/cpp/rtps/builtin/discovery/participant/PDPSimple.cpp

+19-8
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,11 @@ bool PDPSimple::createPDPEndpoints()
304304
secure_endpoints->secure_reader.listener_.reset(new PDPListener(this));
305305

306306
endpoints = secure_endpoints;
307-
endpoints->reader.listener_.reset(new PDPSecurityInitiatorListener(this));
307+
endpoints->reader.listener_.reset(new PDPSecurityInitiatorListener(this,
308+
[this](const ParticipantProxyData& participant_data)
309+
{
310+
match_pdp_remote_endpoints(participant_data, false, true);
311+
}));
308312
}
309313
else
310314
#endif // HAVE_SECURITY
@@ -550,7 +554,7 @@ void PDPSimple::assignRemoteEndpoints(
550554
{
551555
// This participant is not secure.
552556
// Match PDP and other builtin endpoints.
553-
match_pdp_remote_endpoints(*pdata, false);
557+
match_pdp_remote_endpoints(*pdata, false, false);
554558
assign_low_level_remote_endpoints(*pdata, false);
555559
}
556560
}
@@ -560,8 +564,13 @@ void PDPSimple::removeRemoteEndpoints(
560564
ParticipantProxyData* pdata)
561565
{
562566
EPROSIMA_LOG_INFO(RTPS_PDP, "For RTPSParticipant: " << pdata->m_guid);
567+
unmatch_pdp_remote_endpoints(pdata->m_guid);
568+
}
563569

564-
GUID_t guid = pdata->m_guid;
570+
void PDPSimple::unmatch_pdp_remote_endpoints(
571+
const GUID_t& participant_guid)
572+
{
573+
GUID_t guid = participant_guid;
565574

566575
{
567576
auto endpoints = dynamic_cast<fastdds::rtps::SimplePDPEndpoints*>(builtin_endpoints_.get());
@@ -593,7 +602,8 @@ void PDPSimple::notifyAboveRemoteEndpoints(
593602
{
594603
if (notify_secure_endpoints)
595604
{
596-
match_pdp_remote_endpoints(pdata, true);
605+
unmatch_pdp_remote_endpoints(pdata.m_guid);
606+
match_pdp_remote_endpoints(pdata, true, false);
597607
}
598608
else
599609
{
@@ -606,7 +616,7 @@ void PDPSimple::notifyAboveRemoteEndpoints(
606616
notify_and_maybe_ignore_new_participant(part_data, ignored);
607617
if (!ignored)
608618
{
609-
match_pdp_remote_endpoints(*part_data, false);
619+
match_pdp_remote_endpoints(*part_data, false, false);
610620
assign_low_level_remote_endpoints(*part_data, false);
611621
}
612622
}
@@ -616,7 +626,8 @@ void PDPSimple::notifyAboveRemoteEndpoints(
616626

617627
void PDPSimple::match_pdp_remote_endpoints(
618628
const ParticipantProxyData& pdata,
619-
bool notify_secure_endpoints)
629+
bool notify_secure_endpoints,
630+
bool writer_only)
620631
{
621632
#if !HAVE_SECURITY
622633
static_cast<void>(notify_secure_endpoints);
@@ -653,7 +664,7 @@ void PDPSimple::match_pdp_remote_endpoints(
653664
}
654665
#endif // HAVE_SECURITY
655666

656-
if (0 != (endp & pdp_writer_mask))
667+
if (!writer_only && (0 != (endp & pdp_writer_mask)))
657668
{
658669
auto temp_writer_data = get_temporary_writer_proxies_pool().get();
659670

@@ -711,7 +722,7 @@ void PDPSimple::match_pdp_remote_endpoints(
711722
writer->matched_reader_add(*temp_reader_data);
712723
}
713724

714-
if (BEST_EFFORT_RELIABILITY_QOS == reliability_kind)
725+
if (!writer_only && (BEST_EFFORT_RELIABILITY_QOS == reliability_kind))
715726
{
716727
endpoints->writer.writer_->unsent_changes_reset();
717728
}

test/blackbox/common/BlackboxTestsSecurity.cpp

+72
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <fstream>
2222
#include <map>
2323

24+
#include <fastrtps/utils/IPFinder.h>
2425
#include <gtest/gtest.h>
2526

2627
#include "PubSubReader.hpp"
@@ -5016,6 +5017,77 @@ TEST(Security, ValidateAuthenticationHandshakeProperties)
50165017
ASSERT_TRUE(auth_elapsed_time < max_time);
50175018
}
50185019

5020+
// Regression test for Redmine issue #20181
5021+
// Two simple secure participants with tcp transport and initial peers must match.
5022+
// It basically tests that the PDPSecurityInitiatorListener
5023+
// in PDPSimple answers back with the proxy data.
5024+
TEST(Security, security_with_initial_peers_over_tcpv4_correctly_behaves)
5025+
{
5026+
// Create
5027+
PubSubWriter<HelloWorldPubSubType> tcp_client("HelloWorldTopic_TCP");
5028+
PubSubReader<HelloWorldPubSubType> tcp_server("HelloWorldTopic_TCP");
5029+
5030+
// Search for a valid WAN address
5031+
LocatorList_t all_locators;
5032+
Locator_t wan_locator;
5033+
IPFinder::getIP4Address(&all_locators);
5034+
5035+
for (auto& locator : all_locators)
5036+
{
5037+
if (!IPLocator::isLocal(locator))
5038+
{
5039+
wan_locator = locator;
5040+
break;
5041+
}
5042+
}
5043+
5044+
uint16_t server_listening_port = 11810;
5045+
wan_locator.port = server_listening_port;
5046+
wan_locator.kind = LOCATOR_KIND_TCPv4;
5047+
5048+
auto tcp_client_transport_descriptor = std::make_shared<eprosima::fastdds::rtps::TCPv4TransportDescriptor>();
5049+
LocatorList_t initial_peers;
5050+
initial_peers.push_back(wan_locator);
5051+
tcp_client.disable_builtin_transport()
5052+
.add_user_transport_to_pparams(tcp_client_transport_descriptor)
5053+
.initial_peers(initial_peers);
5054+
5055+
auto tcp_server_transport_descriptor = std::make_shared<eprosima::fastdds::rtps::TCPv4TransportDescriptor>();
5056+
tcp_server_transport_descriptor->listening_ports.push_back(server_listening_port);
5057+
IPLocator::copyIPv4(wan_locator, tcp_server_transport_descriptor->wan_addr);
5058+
5059+
std::cout << "SETTING WAN address to " << wan_locator << std::endl;
5060+
5061+
tcp_server.disable_builtin_transport()
5062+
.add_user_transport_to_pparams(tcp_server_transport_descriptor);
5063+
5064+
// Configure security
5065+
const std::string governance_file("governance_helloworld_all_enable.smime");
5066+
const std::string permissions_file("permissions_helloworld.smime");
5067+
CommonPermissionsConfigure(tcp_server, tcp_client, governance_file, permissions_file);
5068+
5069+
tcp_server.init();
5070+
tcp_client.init();
5071+
5072+
ASSERT_TRUE(tcp_server.isInitialized());
5073+
ASSERT_TRUE(tcp_client.isInitialized());
5074+
5075+
tcp_server.waitAuthorized();
5076+
tcp_client.waitAuthorized();
5077+
5078+
tcp_server.wait_discovery();
5079+
tcp_client.wait_discovery();
5080+
5081+
ASSERT_TRUE(tcp_server.is_matched());
5082+
ASSERT_TRUE(tcp_client.is_matched());
5083+
5084+
auto data = default_helloworld_data_generator();
5085+
tcp_server.startReception(data);
5086+
tcp_client.send(data);
5087+
ASSERT_TRUE(data.empty());
5088+
tcp_server.block_for_all(std::chrono::seconds(10));
5089+
}
5090+
50195091

50205092
void blackbox_security_init()
50215093
{

0 commit comments

Comments
 (0)