diff --git a/include/fastdds/rtps/attributes/RTPSParticipantAttributes.h b/include/fastdds/rtps/attributes/RTPSParticipantAttributes.h index 67674c77b93..0cefd9ee32b 100644 --- a/include/fastdds/rtps/attributes/RTPSParticipantAttributes.h +++ b/include/fastdds/rtps/attributes/RTPSParticipantAttributes.h @@ -61,8 +61,10 @@ typedef enum DiscoveryProtocol Server locators should be specified as attributes. */ SERVER, /*!< The participant will behave as a server concerning discovery operation. Discovery operation is volatile (discovery handshake must take place if shutdown). */ - BACKUP /*!< The participant will behave as a server concerning discovery operation. + BACKUP, /*!< The participant will behave as a server concerning discovery operation. Discovery operation persist on a file (discovery handshake wouldn't repeat if shutdown). */ + SUPER_CLIENT /*!< The participant will behave as a client concerning all internal behaviour. + Remote servers will treat it as a server and will share every discovery information. */ } DiscoveryProtocol_t; diff --git a/include/fastdds/rtps/attributes/ServerAttributes.h b/include/fastdds/rtps/attributes/ServerAttributes.h index 3e2b3d905af..4fc02a4fb8e 100644 --- a/include/fastdds/rtps/attributes/ServerAttributes.h +++ b/include/fastdds/rtps/attributes/ServerAttributes.h @@ -106,13 +106,13 @@ typedef std::list RemoteServerList_t; // port use if the ros environment variable doesn't specified one constexpr uint16_t DEFAULT_ROS2_SERVER_PORT = 11811; // default server base guidPrefix -const char* const DEFAULT_ROS2_SERVER_GUIDPREFIX = "44.49.53.43.53.45.52.56.45.52.5F.30"; +const char* const DEFAULT_ROS2_SERVER_GUIDPREFIX = "44.53.00.5f.45.50.52.4f.53.49.4d.41"; /** * Retrieves a ; separated list of locators from an environment variable and * populates a RemoteServerList_t mapping list position to default guid. * @param list servers listening locator list provided. - * @param attributes referenct to a RemoteServerList_t to populate. + * @param attributes reference to a RemoteServerList_t to populate. * @return true if parsing succeeds */ RTPS_DllAPI bool load_environment_server_info( diff --git a/include/fastdds/rtps/builtin/discovery/participant/PDP.h b/include/fastdds/rtps/builtin/discovery/participant/PDP.h index c994685bba7..58831707203 100644 --- a/include/fastdds/rtps/builtin/discovery/participant/PDP.h +++ b/include/fastdds/rtps/builtin/discovery/participant/PDP.h @@ -49,6 +49,7 @@ struct ParticipantType static const char SERVER[]; static const char CLIENT[]; static const char BACKUP[]; + static const char SUPER_CLIENT[]; }; } // namespace rtps diff --git a/include/fastdds/rtps/common/GuidPrefix_t.hpp b/include/fastdds/rtps/common/GuidPrefix_t.hpp index f16f941532b..7bcbfb3b943 100644 --- a/include/fastdds/rtps/common/GuidPrefix_t.hpp +++ b/include/fastdds/rtps/common/GuidPrefix_t.hpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace eprosima { namespace fastrtps { @@ -93,11 +94,13 @@ inline std::ostream& operator <<( const GuidPrefix_t& guiP) { output << std::hex; + char old_fill = output.fill('0'); for (uint8_t i = 0; i < 11; ++i) { - output << (int)guiP.value[i] << "."; + output << std::setw(2) << (int)guiP.value[i] << "."; } - output << (int)guiP.value[11]; + output << std::setw(2) << (int)guiP.value[11]; + output.fill(old_fill); return output << std::dec; } diff --git a/include/fastrtps/xmlparser/XMLParserCommon.h b/include/fastrtps/xmlparser/XMLParserCommon.h index 71ed9950bee..c08d233ddfe 100644 --- a/include/fastrtps/xmlparser/XMLParserCommon.h +++ b/include/fastrtps/xmlparser/XMLParserCommon.h @@ -264,6 +264,7 @@ extern const char* NONE; extern const char* CLIENT; extern const char* SERVER; extern const char* BACKUP; +extern const char* SUPER_CLIENT; extern const char* IGNORE_PARTICIPANT_FLAGS; extern const char* FILTER_DIFFERENT_HOST; extern const char* FILTER_DIFFERENT_PROCESS; diff --git a/resources/xsd/fastRTPS_profiles.xsd b/resources/xsd/fastRTPS_profiles.xsd index a3ed36f3b87..e1c473b48ae 100644 --- a/resources/xsd/fastRTPS_profiles.xsd +++ b/resources/xsd/fastRTPS_profiles.xsd @@ -299,6 +299,7 @@ + diff --git a/src/cpp/rtps/builtin/BuiltinProtocols.cpp b/src/cpp/rtps/builtin/BuiltinProtocols.cpp index 8766f34587b..834e35b3992 100644 --- a/src/cpp/rtps/builtin/BuiltinProtocols.cpp +++ b/src/cpp/rtps/builtin/BuiltinProtocols.cpp @@ -114,6 +114,10 @@ bool BuiltinProtocols::initBuiltinProtocols( break; #endif // if HAVE_SQLITE3 + case DiscoveryProtocol_t::SUPER_CLIENT: + mp_PDP = new fastdds::rtps::PDPClient(this, allocation, true); + break; + default: logError(RTPS_PDP, "Unknown DiscoveryProtocol_t specified."); return false; diff --git a/src/cpp/rtps/builtin/discovery/database/DiscoveryParticipantChangeData.hpp b/src/cpp/rtps/builtin/discovery/database/DiscoveryParticipantChangeData.hpp index abba515272b..bce4bd68f4f 100644 --- a/src/cpp/rtps/builtin/discovery/database/DiscoveryParticipantChangeData.hpp +++ b/src/cpp/rtps/builtin/discovery/database/DiscoveryParticipantChangeData.hpp @@ -82,7 +82,9 @@ class DiscoveryParticipantChangeData // The metatraffic locators of from the serialized payload fastrtps::rtps::RemoteLocatorList metatraffic_locators_; - // Whether this participant is a CLIENT or a SERVER + // Whether this participant is a CLIENT or a SERVER/BACKUP/SUPER_CLIENT + // This variable affects the discovery filter applied to each entity: + // false => send all data ; true => send only data that is required to match endpoints bool is_client_ = false; // Whether this participant (CLIENT OR SERVER) is a client of this server bool is_local_ = false; diff --git a/src/cpp/rtps/builtin/discovery/participant/PDP.cpp b/src/cpp/rtps/builtin/discovery/participant/PDP.cpp index 71efeac3add..9be9c771328 100644 --- a/src/cpp/rtps/builtin/discovery/participant/PDP.cpp +++ b/src/cpp/rtps/builtin/discovery/participant/PDP.cpp @@ -72,6 +72,7 @@ const char ParticipantType::SIMPLE[] = "SIMPLE"; const char ParticipantType::SERVER[] = "SERVER"; const char ParticipantType::CLIENT[] = "CLIENT"; const char ParticipantType::BACKUP[] = "BACKUP"; +const char ParticipantType::SUPER_CLIENT[] = "SUPER_CLIENT"; } // namespace rtps } // namespace fastdds diff --git a/src/cpp/rtps/builtin/discovery/participant/PDPClient.cpp b/src/cpp/rtps/builtin/discovery/participant/PDPClient.cpp index 7bc25c484cc..caed4c5d733 100644 --- a/src/cpp/rtps/builtin/discovery/participant/PDPClient.cpp +++ b/src/cpp/rtps/builtin/discovery/participant/PDPClient.cpp @@ -51,10 +51,12 @@ using namespace fastrtps::rtps; PDPClient::PDPClient( BuiltinProtocols* builtin, - const RTPSParticipantAllocationAttributes& allocation) + const RTPSParticipantAllocationAttributes& allocation, + bool super_client) : PDP(builtin, allocation) , mp_sync(nullptr) , _serverPing(false) + , _super_client(super_client) { } @@ -71,7 +73,12 @@ void PDPClient::initializeParticipantProxyData( { PDP::initializeParticipantProxyData(participant_data); // TODO: Remember that the PDP version USES security - if (getRTPSParticipant()->getAttributes().builtin.discovery_config.discoveryProtocol != DiscoveryProtocol_t::CLIENT) + if ( + getRTPSParticipant()->getAttributes().builtin.discovery_config.discoveryProtocol + != DiscoveryProtocol_t::CLIENT + && + getRTPSParticipant()->getAttributes().builtin.discovery_config.discoveryProtocol + != DiscoveryProtocol_t::SUPER_CLIENT ) { logError(RTPS_PDP, "Using a PDP client object with another user's settings"); } @@ -91,8 +98,18 @@ void PDPClient::initializeParticipantProxyData( } // Set participant type and discovery server version properties - participant_data->m_properties.push_back(std::pair({fastdds::dds::parameter_property_participant_type, fastdds::rtps::ParticipantType::CLIENT})); + if (_super_client) + { + participant_data->m_properties.push_back(std::pair( + {fastdds::dds::parameter_property_participant_type, fastdds::rtps::ParticipantType::SUPER_CLIENT})); + } + else + { + participant_data->m_properties.push_back(std::pair({fastdds::dds::parameter_property_participant_type, + fastdds::rtps::ParticipantType::CLIENT})); + } participant_data->m_properties.push_back(std::pair({fastdds::dds::parameter_property_ds_version, fastdds::dds::parameter_property_current_ds_version})); @@ -716,8 +733,8 @@ bool get_server_client_default_guidPrefix( && id < 256 && std::istringstream(DEFAULT_ROS2_SERVER_GUIDPREFIX) >> guid) { - // Last octet denotes the default server id but to ease debugging it starts on char '0' = 48 - guid.value[11] = static_cast((48 + id) % 256); + // Third octet denotes the server id + guid.value[2] = static_cast(id); return true; } diff --git a/src/cpp/rtps/builtin/discovery/participant/PDPClient.h b/src/cpp/rtps/builtin/discovery/participant/PDPClient.h index edc0db02a7e..d2620444b67 100644 --- a/src/cpp/rtps/builtin/discovery/participant/PDPClient.h +++ b/src/cpp/rtps/builtin/discovery/participant/PDPClient.h @@ -52,7 +52,8 @@ class PDPClient : public PDP */ PDPClient( BuiltinProtocols* builtin, - const RTPSParticipantAllocationAttributes& allocation); + const RTPSParticipantAllocationAttributes& allocation, + bool super_client = false); ~PDPClient(); void initializeParticipantProxyData( @@ -139,6 +140,9 @@ class PDPClient : public PDP //! flag to hightlight we need a server ping announcement bool _serverPing; + + //! flag to know this client must use super client participant type + bool _super_client; }; } /* namespace rtps */ diff --git a/src/cpp/rtps/builtin/discovery/participant/PDPServer.cpp b/src/cpp/rtps/builtin/discovery/participant/PDPServer.cpp index 08164d511d3..3ea2c2669a4 100644 --- a/src/cpp/rtps/builtin/discovery/participant/PDPServer.cpp +++ b/src/cpp/rtps/builtin/discovery/participant/PDPServer.cpp @@ -352,8 +352,11 @@ void PDPServer::initializeParticipantProxyData( { PDP::initializeParticipantProxyData(participant_data); - if (!(getRTPSParticipant()->getAttributes().builtin.discovery_config.discoveryProtocol != - DiscoveryProtocol_t::CLIENT)) + if (getRTPSParticipant()->getAttributes().builtin.discovery_config.discoveryProtocol != + DiscoveryProtocol_t::SERVER + && + getRTPSParticipant()->getAttributes().builtin.discovery_config.discoveryProtocol != + DiscoveryProtocol_t::BACKUP) { logError(RTPS_PDP_SERVER, "Using a PDP Server object with another user's settings"); } diff --git a/src/cpp/rtps/builtin/discovery/participant/PDPServerListener.cpp b/src/cpp/rtps/builtin/discovery/participant/PDPServerListener.cpp index a0fe36482d5..4cfb8bfa70d 100644 --- a/src/cpp/rtps/builtin/discovery/participant/PDPServerListener.cpp +++ b/src/cpp/rtps/builtin/discovery/participant/PDPServerListener.cpp @@ -178,7 +178,8 @@ void PDPServerListener::onNewCacheChangeAdded( if (participant_type != properties.end()) { if (participant_type->second() == ParticipantType::SERVER || - participant_type->second() == ParticipantType::BACKUP) + participant_type->second() == ParticipantType::BACKUP || + participant_type->second() == ParticipantType::SUPER_CLIENT) { is_client = false; } diff --git a/src/cpp/rtps/participant/RTPSParticipantImpl.cpp b/src/cpp/rtps/participant/RTPSParticipantImpl.cpp index 4ab9d0533fc..a80d1863167 100644 --- a/src/cpp/rtps/participant/RTPSParticipantImpl.cpp +++ b/src/cpp/rtps/participant/RTPSParticipantImpl.cpp @@ -155,6 +155,7 @@ RTPSParticipantImpl::RTPSParticipantImpl( case DiscoveryProtocol::BACKUP: case DiscoveryProtocol::CLIENT: case DiscoveryProtocol::SERVER: + case DiscoveryProtocol::SUPER_CLIENT: // Verify if listening ports are provided for (auto& transportDescriptor : PParam.userTransports) { diff --git a/src/cpp/rtps/xmlparser/XMLElementParser.cpp b/src/cpp/rtps/xmlparser/XMLElementParser.cpp index b3e413d4499..c05a9c308cc 100644 --- a/src/cpp/rtps/xmlparser/XMLElementParser.cpp +++ b/src/cpp/rtps/xmlparser/XMLElementParser.cpp @@ -3331,6 +3331,7 @@ XMLP_ret XMLParser::getXMLEnum( + */ @@ -3367,6 +3368,10 @@ XMLP_ret XMLParser::getXMLEnum( { *e = DiscoveryProtocol_t::BACKUP; } + else if (strcmp(text, SUPER_CLIENT) == 0) + { + *e = DiscoveryProtocol_t::SUPER_CLIENT; + } else { logError(XMLPARSER, "Node '" << RTPS_PDP_TYPE << "' with bad content"); diff --git a/src/cpp/rtps/xmlparser/XMLParserCommon.cpp b/src/cpp/rtps/xmlparser/XMLParserCommon.cpp index fd973cf4e3b..54c74f9fe18 100644 --- a/src/cpp/rtps/xmlparser/XMLParserCommon.cpp +++ b/src/cpp/rtps/xmlparser/XMLParserCommon.cpp @@ -248,6 +248,7 @@ const char* NONE = "NONE"; const char* CLIENT = "CLIENT"; const char* SERVER = "SERVER"; const char* BACKUP = "BACKUP"; +const char* SUPER_CLIENT = "SUPER_CLIENT"; const char* IGNORE_PARTICIPANT_FLAGS = "ignoreParticipantFlags"; const char* FILTER_DIFFERENT_HOST = "FILTER_DIFFERENT_HOST"; const char* FILTER_DIFFERENT_PROCESS = "FILTER_DIFFERENT_PROCESS"; diff --git a/test/blackbox/common/RTPSBlackboxTestsPersistenceGuid.cpp b/test/blackbox/common/RTPSBlackboxTestsPersistenceGuid.cpp index a0ccf036d04..e3f8d3a0ed0 100644 --- a/test/blackbox/common/RTPSBlackboxTestsPersistenceGuid.cpp +++ b/test/blackbox/common/RTPSBlackboxTestsPersistenceGuid.cpp @@ -211,7 +211,8 @@ TEST_P(PersistenceGuid, CheckPrevalenceBetweenManualAndPropertyConfiguration) // Check if there is one entry in the writers database table with the stated persistence guid result1 = - system("python check_guid.py \"persistence.db\" \"writers_histories\" \"0.0.0.0.0.0.0.0.0.0.0.1|0.0.0.1\""); + system( + "python check_guid.py \"persistence.db\" \"writers_histories\" \"00.00.00.00.00.00.00.00.00.00.00.01|0.0.0.1\""); ASSERT_EQ(result1, 1); // Check if that there is no entry in the readers database table with the stated persistence guid @@ -220,7 +221,8 @@ TEST_P(PersistenceGuid, CheckPrevalenceBetweenManualAndPropertyConfiguration) ASSERT_EQ(result2, 0); // Check if there is one entry in the readers database table with the stated persistence guid - result2 = system("python check_guid.py \"persistence.db\" \"readers\" \"0.0.0.0.0.0.0.0.0.0.0.2|0.0.0.1\""); + result2 = system( + "python check_guid.py \"persistence.db\" \"readers\" \"00.00.00.00.00.00.00.00.00.00.00.02|0.0.0.1\""); ASSERT_EQ(result2, 1); #else @@ -230,7 +232,8 @@ TEST_P(PersistenceGuid, CheckPrevalenceBetweenManualAndPropertyConfiguration) ASSERT_EQ((result1 >> 8), 0); // Check if there is one entry in the writers database table with the stated persistence guid - result1 = system("python3 check_guid.py 'persistence.db' 'writers_histories' '0.0.0.0.0.0.0.0.0.0.0.1|0.0.0.1'"); + result1 = system( + "python3 check_guid.py 'persistence.db' 'writers_histories' '00.00.00.00.00.00.00.00.00.00.00.01|0.0.0.1'"); ASSERT_EQ((result1 >> 8), 1); // Check if that there is no entry in the readers database table with the stated persistence guid @@ -239,7 +242,7 @@ TEST_P(PersistenceGuid, CheckPrevalenceBetweenManualAndPropertyConfiguration) ASSERT_EQ((result2 >> 8), 0); // Check if there is one entry in the readers database table with the stated persistence guid - result2 = system("python3 check_guid.py 'persistence.db' 'readers' '0.0.0.0.0.0.0.0.0.0.0.2|0.0.0.1'"); + result2 = system("python3 check_guid.py 'persistence.db' 'readers' '00.00.00.00.00.00.00.00.00.00.00.02|0.0.0.1'"); ASSERT_EQ((result2 >> 8), 1); #endif // WIN32 } diff --git a/test/unittest/xmlparser/XMLElementParserTests.cpp b/test/unittest/xmlparser/XMLElementParserTests.cpp index 845c1d69d17..4247733e0b3 100644 --- a/test/unittest/xmlparser/XMLElementParserTests.cpp +++ b/test/unittest/xmlparser/XMLElementParserTests.cpp @@ -3174,6 +3174,7 @@ TEST_F(XMLParserTests, getXMLOctetVector_NegativeClauses) * 2. CLIENT * 3. SERVER * 4. BACKUP + * 5. SUPER_CLIENT * 3. Check XMLEnum with arg ParticipantFilteringFlags_t * 1. FILTER_DIFFERENT_PROCESS */ @@ -3249,6 +3250,13 @@ TEST_F(XMLParserTests, getXMLEnum_positive) titleElement = xml_doc.RootElement(); EXPECT_EQ(XMLP_ret::XML_OK, XMLParserTest::getXMLEnum_wrapper(titleElement, &e, ident)); EXPECT_EQ(DiscoveryProtocol_t::BACKUP, e); + + // SUPER_CLIENT case + sprintf(xml, enum_p, "SUPER_CLIENT"); + ASSERT_EQ(tinyxml2::XMLError::XML_SUCCESS, xml_doc.Parse(xml)); + titleElement = xml_doc.RootElement(); + EXPECT_EQ(XMLP_ret::XML_OK, XMLParserTest::getXMLEnum_wrapper(titleElement, &e, ident)); + EXPECT_EQ(DiscoveryProtocol_t::SUPER_CLIENT, e); } // ParticipantFilteringFlags_t Enum diff --git a/tools/fds/server.cpp b/tools/fds/server.cpp index 2fa97c61a0e..09754e9b064 100644 --- a/tools/fds/server.cpp +++ b/tools/fds/server.cpp @@ -27,6 +27,7 @@ #include #include +#include #include using namespace eprosima; @@ -99,6 +100,7 @@ int main ( // Retrieve server Id: is mandatory and only specified once // Note there is a specific cast to pointer if the Option is valid option::Option* pOp = options[SERVERID]; + int server_id; if ( nullptr == pOp ) { @@ -112,7 +114,6 @@ int main ( } else { - int server_id; stringstream is; is << pOp->arg; @@ -211,7 +212,6 @@ int main ( // Create the server int return_value = 0; Participant* pServer = Domain::createParticipant(*att, nullptr); - att.reset(); if ( nullptr == pServer ) { @@ -224,7 +224,22 @@ int main ( // handle signal SIGINT for every thread signal(SIGINT, sigint_handler); - cout << endl << "\n### Server is running ###" << endl; + // Print running server attributes + cout << "### Server is running ###" << endl; + cout << " Server ID: " << server_id << endl; + cout << " Server GUID prefix: " << pServer->getGuid().guidPrefix << endl; + cout << " Server Addresses: "; + for (auto locator_it = att->rtps.builtin.metatrafficUnicastLocatorList.begin(); + locator_it != att->rtps.builtin.metatrafficUnicastLocatorList.end();) + { + cout << *locator_it; + if (++locator_it != att->rtps.builtin.metatrafficUnicastLocatorList.end()) + { + cout << std::endl << " "; + } + } + cout << std::endl; + g_signal_cv.wait(lock, [] { @@ -234,6 +249,7 @@ int main ( cout << endl << "### Server shut down ###" << endl; } + att.reset(); fastdds::dds::Log::Flush(); cout.flush(); Domain::stopAll();