diff --git a/include/fastdds/rtps/attributes/ServerAttributes.h b/include/fastdds/rtps/attributes/ServerAttributes.h index e3a006e7ae9..0f1c42144d0 100644 --- a/include/fastdds/rtps/attributes/ServerAttributes.h +++ b/include/fastdds/rtps/attributes/ServerAttributes.h @@ -178,6 +178,15 @@ const char* const DEFAULT_ROS2_SERVER_GUIDPREFIX = "44.53.00.5f.45.50.52.4f.53.4 */ const char* const DEFAULT_ROS2_MASTER_URI = "ROS_DISCOVERY_SERVER"; +/* Environment variable to transform a SIMPLE participant in a SUPER CLIENT. + * If the participant is not SIMPLE, the variable doesn't have any effects. + * The variable can assume the following values: + * - FALSE, false, False, 0 + * - TRUE, true, True, 1 + * If the variable is not set, the program will behave like the variable is set to false. + */ +const char* const ROS_SUPER_CLIENT = "ROS_SUPER_CLIENT"; + /** * Retrieves a semicolon-separated list of locators from a string, and * populates a RemoteServerList_t mapping list position to default guid. @@ -211,6 +220,12 @@ RTPS_DllAPI bool load_environment_server_info( */ RTPS_DllAPI const std::string& ros_discovery_server_env(); +/** + * Get the value of environment variable ROS_SUPER_CLIENT + * @return The value of environment variable ROS_SUPER_CLIENT. False if the variable is not defined. + */ +RTPS_DllAPI bool ros_super_client_env(); + /** * Returns the guidPrefix associated to the given server id * @param[in] id of the default server whose guidPrefix we want to retrieve @@ -233,9 +248,11 @@ using fastdds::rtps::RemoteServerList_t; using fastdds::rtps::DEFAULT_ROS2_SERVER_PORT; using fastdds::rtps::DEFAULT_ROS2_SERVER_GUIDPREFIX; using fastdds::rtps::DEFAULT_ROS2_MASTER_URI; +using fastdds::rtps::ROS_SUPER_CLIENT; using fastdds::rtps::load_environment_server_info; using fastdds::rtps::ros_discovery_server_env; using fastdds::rtps::get_server_client_default_guidPrefix; +using fastdds::rtps::ros_super_client_env; } // fastrtps } // rtps diff --git a/src/cpp/rtps/RTPSDomain.cpp b/src/cpp/rtps/RTPSDomain.cpp index d89595b498f..13491688333 100644 --- a/src/cpp/rtps/RTPSDomain.cpp +++ b/src/cpp/rtps/RTPSDomain.cpp @@ -570,6 +570,12 @@ RTPSParticipant* RTPSDomainImpl::clientServerEnvironmentCreationOverride( client_att.builtin.discovery_config.discoveryProtocol = DiscoveryProtocol_t::CLIENT; // RemoteServerAttributes already fill in above + // Check if the client must become a super client + if (ros_super_client_env()) + { + client_att.builtin.discovery_config.discoveryProtocol = DiscoveryProtocol_t::SUPER_CLIENT; + } + RTPSParticipant* part = createParticipant(domain_id, enabled, client_att, listen); if (nullptr != part) { diff --git a/src/cpp/rtps/builtin/discovery/participant/PDPClient.cpp b/src/cpp/rtps/builtin/discovery/participant/PDPClient.cpp index acb55f9da53..7900017b0f4 100644 --- a/src/cpp/rtps/builtin/discovery/participant/PDPClient.cpp +++ b/src/cpp/rtps/builtin/discovery/participant/PDPClient.cpp @@ -929,6 +929,33 @@ void PDPClient::match_pdp_reader_nts_( } } +bool ros_super_client_env() +{ + std::string super_client_str; + bool super_client = false; + std::vector true_vec = {"TRUE", "true", "True", "1"}; + std::vector false_vec = {"FALSE", "false", "False", "0"}; + + SystemInfo::get_env(ROS_SUPER_CLIENT, super_client_str); + if (super_client_str != "") + { + if (find(true_vec.begin(), true_vec.end(), super_client_str) != true_vec.end()) + { + super_client = true; + } + else if (find(false_vec.begin(), false_vec.end(), super_client_str) != false_vec.end()) + { + super_client = false; + } + else + { + EPROSIMA_LOG_ERROR(RTPS_PDP, + "Invalid value for ROS_SUPER_CLIENT environment variable : " << super_client_str); + } + } + return super_client; +} + const std::string& ros_discovery_server_env() { static std::string servers; diff --git a/test/unittest/dds/participant/ParticipantTests.cpp b/test/unittest/dds/participant/ParticipantTests.cpp index a97aa46c298..2e880b0a97a 100644 --- a/test/unittest/dds/participant/ParticipantTests.cpp +++ b/test/unittest/dds/participant/ParticipantTests.cpp @@ -876,6 +876,95 @@ TEST(ParticipantTests, SimpleParticipantRemoteServerListConfiguration) } +/** + * Test that a SIMPLE participant is transformed into a CLIENT if the variable ROS_SUPER_CLIENT is false and into a SUPERCLIENT if it's true. + * It also checks that the environment variable has priority over the coded QoS settings. + */ +TEST(ParticipantTests, TransformSimpleParticipantToSuperclientByEnvVariable) +{ + set_environment_variable(); + +#ifdef _WIN32 + ASSERT_EQ(0, _putenv_s(rtps::ROS_SUPER_CLIENT, "false")); +#else + ASSERT_EQ(0, setenv(rtps::ROS_SUPER_CLIENT, "false", 1)); +#endif // _WIN32 + + rtps::RemoteServerList_t output; + rtps::RemoteServerList_t qos_output; + expected_remote_server_list_output(output); + + DomainParticipantQos qos; + set_participant_qos(qos, qos_output); + + DomainParticipant* participant = DomainParticipantFactory::get_instance()->create_participant( + (uint32_t)GET_PID() % 230, qos); + ASSERT_NE(nullptr, participant); + + fastrtps::rtps::RTPSParticipantAttributes attributes; + get_rtps_attributes(participant, attributes); + EXPECT_EQ(attributes.builtin.discovery_config.discoveryProtocol, fastrtps::rtps::DiscoveryProtocol::CLIENT); + EXPECT_EQ(attributes.builtin.discovery_config.m_DiscoveryServers, output); + +#ifdef _WIN32 + ASSERT_EQ(0, _putenv_s(rtps::ROS_SUPER_CLIENT, "true")); +#else + ASSERT_EQ(0, setenv(rtps::ROS_SUPER_CLIENT, "true", 1)); +#endif // _WIN32 + + DomainParticipant* participant_2 = DomainParticipantFactory::get_instance()->create_participant( + (uint32_t)GET_PID() % 230, qos); + ASSERT_NE(nullptr, participant_2); + + fastrtps::rtps::RTPSParticipantAttributes attributes_2; + get_rtps_attributes(participant_2, attributes_2); + EXPECT_EQ(attributes_2.builtin.discovery_config.discoveryProtocol, fastrtps::rtps::DiscoveryProtocol::SUPER_CLIENT); + EXPECT_EQ(attributes_2.builtin.discovery_config.m_DiscoveryServers, output); + + // check UDPv6 transport is there + auto udpv6_check = [](fastrtps::rtps::RTPSParticipantAttributes& attributes) -> bool + { + for (auto& transportDescriptor : attributes.userTransports) + { + if ( nullptr != dynamic_cast(transportDescriptor.get())) + { + return true; + } + } + + return false; + }; + EXPECT_TRUE(udpv6_check(attributes)); + + DomainParticipantQos result_qos = participant->get_qos(); + EXPECT_EQ(result_qos.wire_protocol().builtin.discovery_config.m_DiscoveryServers, qos_output); + EXPECT_EQ(ReturnCode_t::RETCODE_OK, participant->set_qos(result_qos)); + + // check UDPv6 transport is there + auto udpv6_check_2 = [](fastrtps::rtps::RTPSParticipantAttributes& attributes_2) -> bool + { + for (auto& transportDescriptor : attributes_2.userTransports) + { + if ( nullptr != dynamic_cast(transportDescriptor.get())) + { + return true; + } + } + + return false; + }; + EXPECT_TRUE(udpv6_check_2(attributes_2)); + + result_qos = participant_2->get_qos(); + EXPECT_EQ(result_qos.wire_protocol().builtin.discovery_config.m_DiscoveryServers, qos_output); + EXPECT_EQ(ReturnCode_t::RETCODE_OK, participant_2->set_qos(result_qos)); + + EXPECT_EQ(ReturnCode_t::RETCODE_OK, DomainParticipantFactory::get_instance()->delete_participant(participant)); + EXPECT_EQ(ReturnCode_t::RETCODE_OK, DomainParticipantFactory::get_instance()->delete_participant(participant_2)); +} + + + /** * Test that: * + checks a SIMPLE participant is transformed into a CLIENT.