diff --git a/ddsrouter_core/include/ddsrouter_core/configuration/DDSRouterConfiguration.hpp b/ddsrouter_core/include/ddsrouter_core/configuration/DDSRouterConfiguration.hpp index 707ac7d2c..4135e8196 100644 --- a/ddsrouter_core/include/ddsrouter_core/configuration/DDSRouterConfiguration.hpp +++ b/ddsrouter_core/include/ddsrouter_core/configuration/DDSRouterConfiguration.hpp @@ -69,7 +69,7 @@ struct DDSRouterConfiguration : public DDSRouterReloadConfiguration // VARIABLES ///////////////////////// - std::set> participants_configurations_ = {}; + std::set> participants_configurations = {}; unsigned int number_of_threads = 12; diff --git a/ddsrouter_core/include/ddsrouter_core/configuration/participant/DiscoveryServerParticipantConfiguration.hpp b/ddsrouter_core/include/ddsrouter_core/configuration/participant/DiscoveryServerParticipantConfiguration.hpp index 22b7936dc..ba94126b1 100644 --- a/ddsrouter_core/include/ddsrouter_core/configuration/participant/DiscoveryServerParticipantConfiguration.hpp +++ b/ddsrouter_core/include/ddsrouter_core/configuration/participant/DiscoveryServerParticipantConfiguration.hpp @@ -48,6 +48,7 @@ struct DiscoveryServerParticipantConfiguration : public SimpleParticipantConfigu DDSROUTER_CORE_DllAPI DiscoveryServerParticipantConfiguration( const types::ParticipantId& id, const types::ParticipantKind& kind, + const bool is_repeater, const types::DomainId& domain_id, const types::GuidPrefix& discovery_server_guid_prefix, const std::set& listening_addresses, diff --git a/ddsrouter_core/include/ddsrouter_core/configuration/participant/InitialPeersParticipantConfiguration.hpp b/ddsrouter_core/include/ddsrouter_core/configuration/participant/InitialPeersParticipantConfiguration.hpp new file mode 100644 index 000000000..f977f5504 --- /dev/null +++ b/ddsrouter_core/include/ddsrouter_core/configuration/participant/InitialPeersParticipantConfiguration.hpp @@ -0,0 +1,83 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file InitialPeersParticipantConfiguration.hpp + */ + +#ifndef _DDSROUTERCORE_CONFIGURATION_PARTICIPANT_INITIALPEERSPARTICIPANTCONFIGURATION_HPP_ +#define _DDSROUTERCORE_CONFIGURATION_PARTICIPANT_INITIALPEERSPARTICIPANTCONFIGURATION_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace eprosima { +namespace ddsrouter { +namespace core { +namespace configuration { + +/** + * This data struct joins Initial Peers Participant Configuration features + */ +struct InitialPeersParticipantConfiguration : public SimpleParticipantConfiguration +{ + + ///////////////////////// + // CONSTRUCTORS + ///////////////////////// + + DDSROUTER_CORE_DllAPI InitialPeersParticipantConfiguration() = default; + + DDSROUTER_CORE_DllAPI InitialPeersParticipantConfiguration( + const types::ParticipantId& id, + const types::ParticipantKind& kind, + const bool is_repeater, + const types::DomainId& domain_id, + const std::set& listening_addresses, + const std::set& connection_addresses, + const types::security::TlsConfiguration tls_configuration); + + ///////////////////////// + // METHODS + ///////////////////////// + + DDSROUTER_CORE_DllAPI virtual bool is_valid( + utils::Formatter& error_msg) const noexcept override; + + DDSROUTER_CORE_DllAPI bool operator ==( + const InitialPeersParticipantConfiguration& other) const noexcept; + + ///////////////////////// + // VARIABLES + ///////////////////////// + + std::set listening_addresses = {}; + + std::set connection_addresses = {}; + + types::security::TlsConfiguration tls_configuration = types::security::TlsConfiguration(); +}; + +} /* namespace configuration */ +} /* namespace core */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ + +#endif /* _DDSROUTERCORE_CONFIGURATION_PARTICIPANT_INITIALPEERSPARTICIPANTCONFIGURATION_HPP_ */ diff --git a/ddsrouter_core/include/ddsrouter_core/configuration/participant/ParticipantConfiguration.hpp b/ddsrouter_core/include/ddsrouter_core/configuration/participant/ParticipantConfiguration.hpp index f8ff1cbf9..e4b25a7c4 100644 --- a/ddsrouter_core/include/ddsrouter_core/configuration/participant/ParticipantConfiguration.hpp +++ b/ddsrouter_core/include/ddsrouter_core/configuration/participant/ParticipantConfiguration.hpp @@ -40,7 +40,8 @@ struct ParticipantConfiguration : public BaseConfiguration DDSROUTER_CORE_DllAPI ParticipantConfiguration( const types::ParticipantId& id, - const types::ParticipantKind& kind) noexcept; + const types::ParticipantKind& kind, + const bool is_repeater) noexcept; ///////////////////////// // METHODS @@ -58,15 +59,14 @@ struct ParticipantConfiguration : public BaseConfiguration DDSROUTER_CORE_DllAPI virtual bool is_valid( utils::Formatter& error_msg) const noexcept override; - ///////////////////////// - // VARIABLES - ///////////////////////// - //! Participant Id associated with this configuration types::ParticipantId id; //! Participant Kind of the Participant that this configuration refers. types::ParticipantKind kind; + + //! Whether this Participant should connect its readers with its writers. + bool is_repeater = false; }; } /* namespace configuration */ diff --git a/ddsrouter_core/include/ddsrouter_core/configuration/participant/SimpleParticipantConfiguration.hpp b/ddsrouter_core/include/ddsrouter_core/configuration/participant/SimpleParticipantConfiguration.hpp index 3cf96f419..8a34e2548 100644 --- a/ddsrouter_core/include/ddsrouter_core/configuration/participant/SimpleParticipantConfiguration.hpp +++ b/ddsrouter_core/include/ddsrouter_core/configuration/participant/SimpleParticipantConfiguration.hpp @@ -43,6 +43,7 @@ struct SimpleParticipantConfiguration : public ParticipantConfiguration DDSROUTER_CORE_DllAPI SimpleParticipantConfiguration( const types::ParticipantId& id, const types::ParticipantKind& kind, + const bool is_repeater, const types::DomainId& domain_id) noexcept; ///////////////////////// diff --git a/ddsrouter_core/include/ddsrouter_core/types/address/Address.hpp b/ddsrouter_core/include/ddsrouter_core/types/address/Address.hpp index 39d2aabd0..2bfe8fe2d 100644 --- a/ddsrouter_core/include/ddsrouter_core/types/address/Address.hpp +++ b/ddsrouter_core/include/ddsrouter_core/types/address/Address.hpp @@ -140,7 +140,7 @@ class Address DDSROUTER_CORE_DllAPI bool is_ipv6() const noexcept; //! Get FastDDS Locator kind - DDSROUTER_CORE_DllAPI LocatorType get_locator_kind() noexcept; + DDSROUTER_CORE_DllAPI LocatorType get_locator_kind() const noexcept; /** * @brief Whether the address is correct diff --git a/ddsrouter_core/include/ddsrouter_core/types/participant/ParticipantKind.hpp b/ddsrouter_core/include/ddsrouter_core/types/participant/ParticipantKind.hpp index e504fffd3..6f95e68d7 100644 --- a/ddsrouter_core/include/ddsrouter_core/types/participant/ParticipantKind.hpp +++ b/ddsrouter_core/include/ddsrouter_core/types/participant/ParticipantKind.hpp @@ -38,11 +38,12 @@ enum class ParticipantKind : ParticipantKindType echo, //! Echo Participant Kind dummy, //! Dummy Participant Kind simple_rtps, //! Simple RTPS Participant Kind - local_discovery_server, //! Discovery Server RTPS UDP Participant Kind - wan, //! Discovery Server RTPS TCP Participant Kind + local_discovery_server, //! Discovery Server RTPS Participant Kind + wan_discovery_server, //! Discovery Server Inter Router Participant Kind + wan_initial_peers, //! Initial Peers Inter Router Participant Kind }; -static constexpr unsigned PARTICIPANT_KIND_COUNT = 7; +static constexpr unsigned PARTICIPANT_KIND_COUNT = 8; /** * @brief All ParticipantKind enum values as a std::array. @@ -54,7 +55,8 @@ constexpr std::array ALL_PARTICIPANT_KI ParticipantKind::dummy, ParticipantKind::simple_rtps, ParticipantKind::local_discovery_server, - ParticipantKind::wan + ParticipantKind::wan_discovery_server, + ParticipantKind::wan_initial_peers, }; /** @@ -67,7 +69,8 @@ constexpr std::array ALL_VALID_PART ParticipantKind::dummy, ParticipantKind::simple_rtps, ParticipantKind::local_discovery_server, - ParticipantKind::wan + ParticipantKind::wan_discovery_server, + ParticipantKind::wan_initial_peers, }; constexpr std::array PARTICIPANT_KIND_STRINGS = { @@ -75,9 +78,10 @@ constexpr std::array PARTICIPANT_KIND_STRIN "blank", "echo", "dummy", - "simple_rtps", - "local_discovery_server", - "wan", + "simple-rtps", + "local-discovery-server", + "wan-ds", + "wan-initial-peers", }; static constexpr unsigned MAX_PARTICIPANT_KIND_ALIASES = 4; @@ -94,7 +98,8 @@ constexpr std::array PARTICI ParticipantKindAliasesType({"dummy", "", "", ""}), ParticipantKindAliasesType({"local", "simple", "", ""}), ParticipantKindAliasesType({"discovery-server", "ds", "local-ds", "local-discovery-server"}), - ParticipantKindAliasesType({"wan", "router", "", ""}), + ParticipantKindAliasesType({"wan-ds", "wan-discovery-server", "", ""}), + ParticipantKindAliasesType({"wan", "router", "initial-peers", ""}), }; DDSROUTER_CORE_DllAPI std::ostream& operator <<( diff --git a/ddsrouter_core/include/ddsrouter_core/types/security/tls/TlsConfiguration.hpp b/ddsrouter_core/include/ddsrouter_core/types/security/tls/TlsConfiguration.hpp index da05d82fc..823cb1bc5 100644 --- a/ddsrouter_core/include/ddsrouter_core/types/security/tls/TlsConfiguration.hpp +++ b/ddsrouter_core/include/ddsrouter_core/types/security/tls/TlsConfiguration.hpp @@ -20,6 +20,9 @@ #define _DDSROUTERCORE_SECURITY_TLS_TLSCONFIGURATION_HPP_ #include +#include + +#include #include @@ -152,6 +155,20 @@ class TlsConfiguration */ DDSROUTER_CORE_DllAPI const std::string& dh_params_file() const; + //! Activate TLS configuration in a TCP transport descriptor + DDSROUTER_CORE_DllAPI void enable_tls( + std::shared_ptr descriptor, + bool client = false) const; + + //! Activate TLS client configuration in a TCP transport descriptor + DDSROUTER_CORE_DllAPI void enable_tls_client( + std::shared_ptr descriptor, + bool only_client) const; + + //! Activate TLS server configuration in a TCP transport descriptor + DDSROUTER_CORE_DllAPI void enable_tls_server( + std::shared_ptr descriptor) const; + private: //! Internal throwing check diff --git a/ddsrouter_core/src/cpp/communication/Bridge.cpp b/ddsrouter_core/src/cpp/communication/Bridge.cpp index 9674da17c..630a1643e 100644 --- a/ddsrouter_core/src/cpp/communication/Bridge.cpp +++ b/ddsrouter_core/src/cpp/communication/Bridge.cpp @@ -57,8 +57,15 @@ Bridge::Bridge( std::map> writers_except_one = writers_; // Create a copy of the map - // Get this Track source participant before removing it from map - writers_except_one.erase(id); // TODO: check if this element is removed in erase or if source is still valid + if (!participants_->get_participant(id)->is_repeater()) + { + // Remove this Track source participant because it is not repeater + writers_except_one.erase(id); + + logDebug( + DDSROUTER_BRIDGE, + "Not adding own Writer to Track in " << *this << " in Participant " << id << "."); + } // This insert is required as there is no copy method for Track // Tracks are always created disabled and then enabled with Bridge enable() method diff --git a/ddsrouter_core/src/cpp/communication/Track.cpp b/ddsrouter_core/src/cpp/communication/Track.cpp index b545186f0..54f714adf 100644 --- a/ddsrouter_core/src/cpp/communication/Track.cpp +++ b/ddsrouter_core/src/cpp/communication/Track.cpp @@ -220,6 +220,10 @@ void Track::transmit_() noexcept // Send data through writers for (auto& writer_it : writers_) { + logDebug( + DDSROUTER_TRACK, + "Forwarding data to writer " << writer_it.first << "."); + ret = writer_it.second->write(data); if (!ret) diff --git a/ddsrouter_core/src/cpp/configuration/DDSRouterConfiguration.cpp b/ddsrouter_core/src/cpp/configuration/DDSRouterConfiguration.cpp index dafb7814f..73ecb5c5c 100644 --- a/ddsrouter_core/src/cpp/configuration/DDSRouterConfiguration.cpp +++ b/ddsrouter_core/src/cpp/configuration/DDSRouterConfiguration.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -40,7 +41,7 @@ DDSRouterConfiguration::DDSRouterConfiguration( std::set> participants_configurations, unsigned int number_of_threads /* = default_number_of_threads() */) : DDSRouterReloadConfiguration (allowlist, blocklist, builtin_topics) - , participants_configurations_(participants_configurations) + , participants_configurations(participants_configurations) , number_of_threads(number_of_threads) { } @@ -55,16 +56,16 @@ bool DDSRouterConfiguration::is_valid( } // Check there are at least two participants - if (participants_configurations_.size() < 2) + if (participants_configurations.size() < 1) { - error_msg << "There must be at least 2 participants. "; + error_msg << "There must be at least 1 participant."; return false; } // Check Participant Configurations AND // check Participant Configuration IDs are not repeated std::set ids; - for (std::shared_ptr configuration : participants_configurations_) + for (std::shared_ptr configuration : participants_configurations) { // Check configuration is not null if (!configuration) @@ -93,7 +94,7 @@ bool DDSRouterConfiguration::is_valid( } // If the number of ids are not equal the number of configurations, is because they are repeated - if (ids.size() != participants_configurations_.size()) + if (ids.size() != participants_configurations.size()) { error_msg << "Participant ids are not unique. "; return false; @@ -126,9 +127,12 @@ bool DDSRouterConfiguration::check_correct_configuration_object_( return check_correct_configuration_object_by_type_(configuration); case ParticipantKind::local_discovery_server: - case ParticipantKind::wan: + case ParticipantKind::wan_discovery_server: return check_correct_configuration_object_by_type_(configuration); + case ParticipantKind::wan_initial_peers: + return check_correct_configuration_object_by_type_(configuration); + default: return check_correct_configuration_object_by_type_(configuration); } diff --git a/ddsrouter_core/src/cpp/configuration/participant/DiscoveryServerParticipantConfiguration.cpp b/ddsrouter_core/src/cpp/configuration/participant/DiscoveryServerParticipantConfiguration.cpp index d5506489c..073dfb3b4 100644 --- a/ddsrouter_core/src/cpp/configuration/participant/DiscoveryServerParticipantConfiguration.cpp +++ b/ddsrouter_core/src/cpp/configuration/participant/DiscoveryServerParticipantConfiguration.cpp @@ -29,14 +29,15 @@ namespace configuration { using namespace eprosima::ddsrouter::core::types; DiscoveryServerParticipantConfiguration::DiscoveryServerParticipantConfiguration( - const types::ParticipantId& id, - const types::ParticipantKind& kind, - const types::DomainId& domain_id, - const types::GuidPrefix& discovery_server_guid_prefix, - const std::set& listening_addresses, - const std::set& connection_addresses, + const ParticipantId& id, + const ParticipantKind& kind, + const bool is_repeater, + const DomainId& domain_id, + const GuidPrefix& discovery_server_guid_prefix, + const std::set
& listening_addresses, + const std::set& connection_addresses, const types::security::TlsConfiguration tls_configuration) - : SimpleParticipantConfiguration(id, kind, domain_id) + : SimpleParticipantConfiguration(id, kind, is_repeater, domain_id) , discovery_server_guid_prefix(discovery_server_guid_prefix) , listening_addresses(listening_addresses) , connection_addresses(connection_addresses) diff --git a/ddsrouter_core/src/cpp/configuration/participant/InitialPeersParticipantConfiguration.cpp b/ddsrouter_core/src/cpp/configuration/participant/InitialPeersParticipantConfiguration.cpp new file mode 100644 index 000000000..a5e9abc3a --- /dev/null +++ b/ddsrouter_core/src/cpp/configuration/participant/InitialPeersParticipantConfiguration.cpp @@ -0,0 +1,120 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file InitialPeersParticipantConfiguration.cpp + */ + +#include +#include +#include +#include + +namespace eprosima { +namespace ddsrouter { +namespace core { +namespace configuration { + +using namespace eprosima::ddsrouter::core::types; + +InitialPeersParticipantConfiguration::InitialPeersParticipantConfiguration( + const types::ParticipantId& id, + const types::ParticipantKind& kind, + const bool is_repeater, + const types::DomainId& domain_id, + const std::set& listening_addresses, + const std::set& connection_addresses, + const types::security::TlsConfiguration tls_configuration) + : SimpleParticipantConfiguration(id, kind, is_repeater, domain_id) + , listening_addresses(listening_addresses) + , connection_addresses(connection_addresses) + , tls_configuration(tls_configuration) +{ + // Do nothing +} + +bool InitialPeersParticipantConfiguration::is_valid( + utils::Formatter& error_msg) const noexcept +{ + // Check parent class validity + if (!SimpleParticipantConfiguration::is_valid(error_msg)) + { + return false; + } + + // Check listening addresses + for (Address address : listening_addresses) + { + if (!address.is_valid()) + { + error_msg << "Incorrect address " << address << " in listening addresses. "; + return false; + } + } + + // Check connection addresses + for (Address address : connection_addresses) + { + if (!address.is_valid()) + { + error_msg << "Incorrect address " << address << " in connection addresses. "; + return false; + } + } + + // Check exist at least one address + if (listening_addresses.empty() && connection_addresses.empty()) + { + error_msg << "No listening or connection address specified. "; + return false; + } + + // If active, check it is valid + if (tls_configuration.is_active()) + { + // If has listening addresses, it should be able to provide TLS server configuration + if (!listening_addresses.empty()) + { + if (!tls_configuration.compatible()) + { + error_msg << "TLS requires to support Server Configuration if listening addresses set. "; + return false; + } + } + + // If has connection addresses, it should be able to provide TLS client configuration + if (!connection_addresses.empty()) + { + if (!tls_configuration.compatible()) + { + error_msg << "TLS requires to support Client Configuration if connection addresses set. "; + return false; + } + } + } + + return true; +} + +bool InitialPeersParticipantConfiguration::operator ==( + const InitialPeersParticipantConfiguration& other) const noexcept +{ + // TODO + return false; +} + +} /* namespace configuration */ +} /* namespace core */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ diff --git a/ddsrouter_core/src/cpp/configuration/participant/ParticipantConfiguration.cpp b/ddsrouter_core/src/cpp/configuration/participant/ParticipantConfiguration.cpp index c3a4bbb1b..07df3b92f 100644 --- a/ddsrouter_core/src/cpp/configuration/participant/ParticipantConfiguration.cpp +++ b/ddsrouter_core/src/cpp/configuration/participant/ParticipantConfiguration.cpp @@ -30,9 +30,11 @@ using namespace eprosima::ddsrouter::core::types; ParticipantConfiguration::ParticipantConfiguration( const ParticipantId& id, - const ParticipantKind& kind) noexcept + const ParticipantKind& kind, + const bool is_repeater /* = false */) noexcept : id(id) , kind(kind) + , is_repeater(is_repeater) { } diff --git a/ddsrouter_core/src/cpp/configuration/participant/SimpleParticipantConfiguration.cpp b/ddsrouter_core/src/cpp/configuration/participant/SimpleParticipantConfiguration.cpp index 742bba4c6..a46cf0d6b 100644 --- a/ddsrouter_core/src/cpp/configuration/participant/SimpleParticipantConfiguration.cpp +++ b/ddsrouter_core/src/cpp/configuration/participant/SimpleParticipantConfiguration.cpp @@ -28,9 +28,10 @@ using namespace eprosima::ddsrouter::core::types; SimpleParticipantConfiguration::SimpleParticipantConfiguration( const ParticipantId& id, - const ParticipantKind& kind /* = ParticipantKind::simple_rtps */, - const DomainId& domain_id /* = DEFAULT_DOMAIN_ID_ */) noexcept - : ParticipantConfiguration(id, kind) + const ParticipantKind& kind, + const bool is_repeater, + const DomainId& domain_id) noexcept + : ParticipantConfiguration(id, kind, is_repeater) , domain(domain_id) { } diff --git a/ddsrouter_core/src/cpp/core/DDSRouterImpl.cpp b/ddsrouter_core/src/cpp/core/DDSRouterImpl.cpp index 0c011475d..2eefe0184 100644 --- a/ddsrouter_core/src/cpp/core/DDSRouterImpl.cpp +++ b/ddsrouter_core/src/cpp/core/DDSRouterImpl.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include namespace eprosima { namespace ddsrouter { @@ -278,7 +278,7 @@ void DDSRouterImpl::init_allowed_topics_() void DDSRouterImpl::init_participants_() { for (std::shared_ptr participant_config : - configuration_.participants_configurations_) + configuration_.participants_configurations) { std::shared_ptr new_participant; diff --git a/ddsrouter_core/src/cpp/core/ParticipantFactory.cpp b/ddsrouter_core/src/cpp/core/ParticipantFactory.cpp index a0e857f3b..7681da22a 100644 --- a/ddsrouter_core/src/cpp/core/ParticipantFactory.cpp +++ b/ddsrouter_core/src/cpp/core/ParticipantFactory.cpp @@ -30,7 +30,8 @@ #include #include #include -#include +#include +#include namespace eprosima { namespace ddsrouter { @@ -97,7 +98,7 @@ std::shared_ptr ParticipantFactory::create_participant( discovery_database); } - case ParticipantKind::wan: + case ParticipantKind::wan_discovery_server: // Discovery Server RTPS Participant { std::shared_ptr conf_ = @@ -110,7 +111,26 @@ std::shared_ptr ParticipantFactory::create_participant( participant_configuration->kind); } - return std::make_shared ( + return std::make_shared ( + (*conf_), + payload_pool, + discovery_database); + } + + case ParticipantKind::wan_initial_peers: + // Initial Peers RTPS Participant + { + std::shared_ptr conf_ = + std::dynamic_pointer_cast( + participant_configuration); + if (!conf_) + { + throw utils::ConfigurationException( + utils::Formatter() << "Configuration from Participant: " << participant_configuration->id << " is not for Participant Kind: " << + participant_configuration->kind); + } + + return std::make_shared ( (*conf_), payload_pool, discovery_database); diff --git a/ddsrouter_core/src/cpp/efficiency/cache_change/CacheChangePool.cpp b/ddsrouter_core/src/cpp/efficiency/cache_change/CacheChangePool.cpp new file mode 100644 index 000000000..515ecca30 --- /dev/null +++ b/ddsrouter_core/src/cpp/efficiency/cache_change/CacheChangePool.cpp @@ -0,0 +1,52 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file CacheChangePool.cpp + */ + +#include +#include + +namespace eprosima { +namespace ddsrouter { +namespace core { + +CacheChangePool::CacheChangePool( + utils::PoolConfiguration configuration) + : utils::UnboundedPool(configuration) +{ + initialize_vector_(); +} + +bool CacheChangePool::reserve_cache( + fastrtps::rtps::CacheChange_t*& cache_change) +{ + return loan(cache_change); +} + +bool CacheChangePool::release_cache( + fastrtps::rtps::CacheChange_t* cache_change) +{ + return return_loan(cache_change); +} + +fastrtps::rtps::CacheChange_t* CacheChangePool::new_element_() +{ + return new types::RouterCacheChange(); +} + +} /* namespace core */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ diff --git a/ddsrouter_core/src/cpp/efficiency/cache_change/CacheChangePool.hpp b/ddsrouter_core/src/cpp/efficiency/cache_change/CacheChangePool.hpp new file mode 100644 index 000000000..fedcbc867 --- /dev/null +++ b/ddsrouter_core/src/cpp/efficiency/cache_change/CacheChangePool.hpp @@ -0,0 +1,71 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file CacheChangePool.hpp + */ + +#ifndef __SRC_DDSROUTERCORE_EFFICIENCY_CACHECHANGE_CACHACHANGEPOOL_HPP_ +#define __SRC_DDSROUTERCORE_EFFICIENCY_CACHECHANGE_CACHACHANGEPOOL_HPP_ + +#include + +#include +#include + +namespace eprosima { +namespace ddsrouter { +namespace core { + +/** + * @brief This class implements a pool of CacheChange objects specialized as RouterCacheChanges. + * + * It reuses the UnboundedPool implementation, what allow to create an unbounded reusable pool. + * + * TODO: implement this class as an IPool (or having an internal pool), without being force to be unbounded. + */ +class CacheChangePool : public fastrtps::rtps::IChangePool, public utils::UnboundedPool +{ +public: + + /** + * @brief Construct a new Cache Change Pool object from a Pool Configuration + * + * @param configuration pool configuration + * + * @warning max size will not be used as it is Unbounded + */ + CacheChangePool( + utils::PoolConfiguration configuration); + + //! Call UnboundedPool::reserve + virtual bool reserve_cache( + fastrtps::rtps::CacheChange_t*& cache_change) override; + + //! Call UnboundedPool::release + virtual bool release_cache( + fastrtps::rtps::CacheChange_t* cache_change) override; + +protected: + + //! Override the UnboundedPool::create_element method to create a RouterCacheChange object. + virtual fastrtps::rtps::CacheChange_t* new_element_() override; + +}; + +} /* namespace core */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ + +#endif /* __SRC_DDSROUTERCORE_EFFICIENCY_CACHECHANGE_CACHACHANGEPOOL_HPP_ */ diff --git a/ddsrouter_core/src/cpp/efficiency/CopyPayloadPool.cpp b/ddsrouter_core/src/cpp/efficiency/payload/CopyPayloadPool.cpp similarity index 97% rename from ddsrouter_core/src/cpp/efficiency/CopyPayloadPool.cpp rename to ddsrouter_core/src/cpp/efficiency/payload/CopyPayloadPool.cpp index 3868f33dc..dc97e7ce4 100644 --- a/ddsrouter_core/src/cpp/efficiency/CopyPayloadPool.cpp +++ b/ddsrouter_core/src/cpp/efficiency/payload/CopyPayloadPool.cpp @@ -17,7 +17,7 @@ * */ -#include +#include #include namespace eprosima { diff --git a/ddsrouter_core/src/cpp/efficiency/CopyPayloadPool.hpp b/ddsrouter_core/src/cpp/efficiency/payload/CopyPayloadPool.hpp similarity index 86% rename from ddsrouter_core/src/cpp/efficiency/CopyPayloadPool.hpp rename to ddsrouter_core/src/cpp/efficiency/payload/CopyPayloadPool.hpp index e56144b2c..6e29a7f94 100644 --- a/ddsrouter_core/src/cpp/efficiency/CopyPayloadPool.hpp +++ b/ddsrouter_core/src/cpp/efficiency/payload/CopyPayloadPool.hpp @@ -16,10 +16,10 @@ * @file CopyPayloadPool.hpp */ -#ifndef __SRC_DDSROUTERCORE_EFFICIENCY_COPYPAYLOADPOOL_HPP_ -#define __SRC_DDSROUTERCORE_EFFICIENCY_COPYPAYLOADPOOL_HPP_ +#ifndef __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOAD_COPYPAYLOADPOOL_HPP_ +#define __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOAD_COPYPAYLOADPOOL_HPP_ -#include +#include namespace eprosima { namespace ddsrouter { @@ -57,4 +57,4 @@ class CopyPayloadPool : public PayloadPool } /* namespace ddsrouter */ } /* namespace eprosima */ -#endif /* __SRC_DDSROUTERCORE_EFFICIENCY_COPYPAYLOADPOOL_HPP_ */ +#endif /* __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOAD_COPYPAYLOADPOOL_HPP_ */ diff --git a/ddsrouter_core/src/cpp/efficiency/FastPayloadPool.cpp b/ddsrouter_core/src/cpp/efficiency/payload/FastPayloadPool.cpp similarity index 98% rename from ddsrouter_core/src/cpp/efficiency/FastPayloadPool.cpp rename to ddsrouter_core/src/cpp/efficiency/payload/FastPayloadPool.cpp index e5313fdb9..f15c47d52 100644 --- a/ddsrouter_core/src/cpp/efficiency/FastPayloadPool.cpp +++ b/ddsrouter_core/src/cpp/efficiency/payload/FastPayloadPool.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include namespace eprosima { namespace ddsrouter { diff --git a/ddsrouter_core/src/cpp/efficiency/FastPayloadPool.hpp b/ddsrouter_core/src/cpp/efficiency/payload/FastPayloadPool.hpp similarity index 95% rename from ddsrouter_core/src/cpp/efficiency/FastPayloadPool.hpp rename to ddsrouter_core/src/cpp/efficiency/payload/FastPayloadPool.hpp index ce2dbb3a8..6fafc4c41 100644 --- a/ddsrouter_core/src/cpp/efficiency/FastPayloadPool.hpp +++ b/ddsrouter_core/src/cpp/efficiency/payload/FastPayloadPool.hpp @@ -16,14 +16,14 @@ * @file FastPayloadPool.hpp */ -#ifndef __SRC_DDSROUTERCORE_EFFICIENCY_FASTPAYLOADPOOL_HPP_ -#define __SRC_DDSROUTERCORE_EFFICIENCY_FASTPAYLOADPOOL_HPP_ +#ifndef __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOAD_FASTPAYLOADPOOL_HPP_ +#define __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOAD_FASTPAYLOADPOOL_HPP_ #include #include #include -#include +#include namespace eprosima { namespace ddsrouter { @@ -147,4 +147,4 @@ class FastPayloadPool : public PayloadPool } /* namespace ddsrouter */ } /* namespace eprosima */ -#endif /* __SRC_DDSROUTERCORE_EFFICIENCY_FASTPAYLOADPOOL_HPP_ */ +#endif /* __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOAD_FASTPAYLOADPOOL_HPP_ */ diff --git a/ddsrouter_core/src/cpp/efficiency/MapPayloadPool.cpp b/ddsrouter_core/src/cpp/efficiency/payload/MapPayloadPool.cpp similarity index 98% rename from ddsrouter_core/src/cpp/efficiency/MapPayloadPool.cpp rename to ddsrouter_core/src/cpp/efficiency/payload/MapPayloadPool.cpp index b8905af79..ac27bb69d 100644 --- a/ddsrouter_core/src/cpp/efficiency/MapPayloadPool.cpp +++ b/ddsrouter_core/src/cpp/efficiency/payload/MapPayloadPool.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include namespace eprosima { namespace ddsrouter { diff --git a/ddsrouter_core/src/cpp/efficiency/MapPayloadPool.hpp b/ddsrouter_core/src/cpp/efficiency/payload/MapPayloadPool.hpp similarity index 93% rename from ddsrouter_core/src/cpp/efficiency/MapPayloadPool.hpp rename to ddsrouter_core/src/cpp/efficiency/payload/MapPayloadPool.hpp index 9d5316311..93f78be6d 100644 --- a/ddsrouter_core/src/cpp/efficiency/MapPayloadPool.hpp +++ b/ddsrouter_core/src/cpp/efficiency/payload/MapPayloadPool.hpp @@ -16,14 +16,14 @@ * @file MapPayloadPool.hpp */ -#ifndef __SRC_DDSROUTERCORE_EFFICIENCY_MAPPAYLOADPOOL_HPP_ -#define __SRC_DDSROUTERCORE_EFFICIENCY_MAPPAYLOADPOOL_HPP_ +#ifndef __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOAD_MAPPAYLOADPOOL_HPP_ +#define __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOAD_MAPPAYLOADPOOL_HPP_ #include #include #include -#include +#include namespace eprosima { namespace ddsrouter { @@ -116,4 +116,4 @@ class MapPayloadPool : public PayloadPool } /* namespace ddsrouter */ } /* namespace eprosima */ -#endif /* __SRC_DDSROUTERCORE_EFFICIENCY_MAPPAYLOADPOOL_HPP_ */ +#endif /* __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOAD_MAPPAYLOADPOOL_HPP_ */ diff --git a/ddsrouter_core/src/cpp/efficiency/PayloadPool.cpp b/ddsrouter_core/src/cpp/efficiency/payload/PayloadPool.cpp similarity index 98% rename from ddsrouter_core/src/cpp/efficiency/PayloadPool.cpp rename to ddsrouter_core/src/cpp/efficiency/payload/PayloadPool.cpp index efc422e2a..9eec115d2 100644 --- a/ddsrouter_core/src/cpp/efficiency/PayloadPool.cpp +++ b/ddsrouter_core/src/cpp/efficiency/payload/PayloadPool.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include namespace eprosima { namespace ddsrouter { diff --git a/ddsrouter_core/src/cpp/efficiency/PayloadPool.hpp b/ddsrouter_core/src/cpp/efficiency/payload/PayloadPool.hpp similarity index 97% rename from ddsrouter_core/src/cpp/efficiency/PayloadPool.hpp rename to ddsrouter_core/src/cpp/efficiency/payload/PayloadPool.hpp index 3d8279f21..e7744c325 100644 --- a/ddsrouter_core/src/cpp/efficiency/PayloadPool.hpp +++ b/ddsrouter_core/src/cpp/efficiency/payload/PayloadPool.hpp @@ -16,8 +16,8 @@ * @file PayloadPool.hpp */ -#ifndef __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOADPOOL_HPP_ -#define __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOADPOOL_HPP_ +#ifndef __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOAD_PAYLOADPOOL_HPP_ +#define __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOAD_PAYLOADPOOL_HPP_ #include @@ -245,4 +245,4 @@ class PayloadPool : public eprosima::fastrtps::rtps::IPayloadPool } /* namespace ddsrouter */ } /* namespace eprosima */ -#endif /* __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOADPOOL_HPP_ */ +#endif /* __SRC_DDSROUTERCORE_EFFICIENCY_PAYLOAD_PAYLOADPOOL_HPP_ */ diff --git a/ddsrouter_core/src/cpp/participant/IParticipant.hpp b/ddsrouter_core/src/cpp/participant/IParticipant.hpp index 790bdd8ee..23beea5e5 100644 --- a/ddsrouter_core/src/cpp/participant/IParticipant.hpp +++ b/ddsrouter_core/src/cpp/participant/IParticipant.hpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include @@ -63,6 +63,11 @@ class IParticipant */ virtual types::ParticipantKind kind() const noexcept = 0; + /** + * @brief Whether this Participant requires to connect ist own readers with its own writers. + */ + virtual bool is_repeater() const noexcept = 0; + /** * @brief Return a new Writer * diff --git a/ddsrouter_core/src/cpp/participant/implementations/auxiliar/BaseParticipant.hpp b/ddsrouter_core/src/cpp/participant/implementations/auxiliar/BaseParticipant.hpp index 238a63860..8bf4800d1 100644 --- a/ddsrouter_core/src/cpp/participant/implementations/auxiliar/BaseParticipant.hpp +++ b/ddsrouter_core/src/cpp/participant/implementations/auxiliar/BaseParticipant.hpp @@ -86,6 +86,15 @@ class BaseParticipant : public IParticipant */ types::ParticipantKind kind() const noexcept override; + /** + * @brief Override is_repeater_ IParticipant method + * + * It gets the kind from the configuration. + * + * Thread safe with mutex \c mutex_ . + */ + bool is_repeater() const noexcept override; + /** * @brief Override create_writer() IParticipant method * diff --git a/ddsrouter_core/src/cpp/participant/implementations/auxiliar/BlankParticipant.cpp b/ddsrouter_core/src/cpp/participant/implementations/auxiliar/BlankParticipant.cpp index 1665a97d4..048371446 100644 --- a/ddsrouter_core/src/cpp/participant/implementations/auxiliar/BlankParticipant.cpp +++ b/ddsrouter_core/src/cpp/participant/implementations/auxiliar/BlankParticipant.cpp @@ -43,6 +43,11 @@ ParticipantKind BlankParticipant::kind() const noexcept return ParticipantKind::blank; } +bool BlankParticipant::is_repeater() const noexcept +{ + return false; +} + std::shared_ptr BlankParticipant::create_writer( RealTopic topic) { diff --git a/ddsrouter_core/src/cpp/participant/implementations/auxiliar/BlankParticipant.hpp b/ddsrouter_core/src/cpp/participant/implementations/auxiliar/BlankParticipant.hpp index 95a6d5e6e..5f06c00f9 100644 --- a/ddsrouter_core/src/cpp/participant/implementations/auxiliar/BlankParticipant.hpp +++ b/ddsrouter_core/src/cpp/participant/implementations/auxiliar/BlankParticipant.hpp @@ -47,6 +47,9 @@ class BlankParticipant : public IParticipant //! Override kind() IParticipant method types::ParticipantKind kind() const noexcept override; + //! Override is_repeater() IParticipant method + bool is_repeater() const noexcept override; + //! Override create_writer() IParticipant method std::shared_ptr create_writer( types::RealTopic topic) override; diff --git a/ddsrouter_core/src/cpp/participant/implementations/auxiliar/impl/BaseParticipant.ipp b/ddsrouter_core/src/cpp/participant/implementations/auxiliar/impl/BaseParticipant.ipp index 58c2e740e..5ef42396b 100644 --- a/ddsrouter_core/src/cpp/participant/implementations/auxiliar/impl/BaseParticipant.ipp +++ b/ddsrouter_core/src/cpp/participant/implementations/auxiliar/impl/BaseParticipant.ipp @@ -79,6 +79,14 @@ types::ParticipantKind BaseParticipant::kind() const noexcept return configuration_.kind; } +template +bool BaseParticipant::is_repeater() const noexcept +{ + std::lock_guard lock(mutex_); + + return configuration_.is_repeater; +} + template std::shared_ptr BaseParticipant::create_writer( types::RealTopic topic) diff --git a/ddsrouter_core/src/cpp/participant/implementations/rtps/DiscoveryServerParticipant.hpp b/ddsrouter_core/src/cpp/participant/implementations/rtps/DiscoveryServerParticipant.hpp index 122a1e9a3..1fdb1e38e 100644 --- a/ddsrouter_core/src/cpp/participant/implementations/rtps/DiscoveryServerParticipant.hpp +++ b/ddsrouter_core/src/cpp/participant/implementations/rtps/DiscoveryServerParticipant.hpp @@ -50,19 +50,6 @@ class DiscoveryServerParticipant virtual fastrtps::rtps::RTPSParticipantAttributes participant_attributes_() const override; - static void enable_tls( - std::shared_ptr descriptor, - const types::security::TlsConfiguration& tls_configuration, - bool client = false); - - static void enable_tls_client( - std::shared_ptr descriptor, - const types::security::TlsConfiguration& tls_configuration, - bool only_client); - - static void enable_tls_server( - std::shared_ptr descriptor, - const types::security::TlsConfiguration& tls_configuration); }; } /* namespace rpts */ diff --git a/ddsrouter_core/src/cpp/participant/implementations/rtps/WANParticipant.cpp b/ddsrouter_core/src/cpp/participant/implementations/rtps/WanDiscoveryServerParticipant.cpp similarity index 87% rename from ddsrouter_core/src/cpp/participant/implementations/rtps/WANParticipant.cpp rename to ddsrouter_core/src/cpp/participant/implementations/rtps/WanDiscoveryServerParticipant.cpp index 5013bd52c..da6f802b5 100644 --- a/ddsrouter_core/src/cpp/participant/implementations/rtps/WANParticipant.cpp +++ b/ddsrouter_core/src/cpp/participant/implementations/rtps/WanDiscoveryServerParticipant.cpp @@ -13,10 +13,10 @@ // limitations under the License. /** - * @file WANParticipant.cpp + * @file WanDiscoveryServerParticipant.cpp */ -#include +#include namespace eprosima { namespace ddsrouter { @@ -25,7 +25,7 @@ namespace rtps { using namespace eprosima::ddsrouter::core::types; -WANParticipant::WANParticipant( +WanDiscoveryServerParticipant::WanDiscoveryServerParticipant( const configuration::DiscoveryServerParticipantConfiguration participant_configuration, std::shared_ptr payload_pool, std::shared_ptr discovery_database) diff --git a/ddsrouter_core/src/cpp/participant/implementations/rtps/WANParticipant.hpp b/ddsrouter_core/src/cpp/participant/implementations/rtps/WanDiscoveryServerParticipant.hpp similarity index 87% rename from ddsrouter_core/src/cpp/participant/implementations/rtps/WANParticipant.hpp rename to ddsrouter_core/src/cpp/participant/implementations/rtps/WanDiscoveryServerParticipant.hpp index 344f6b24a..7e6b62405 100644 --- a/ddsrouter_core/src/cpp/participant/implementations/rtps/WANParticipant.hpp +++ b/ddsrouter_core/src/cpp/participant/implementations/rtps/WanDiscoveryServerParticipant.hpp @@ -13,11 +13,11 @@ // limitations under the License. /** - * @file WANParticipant.hpp + * @file WanDiscoveryServerParticipant.hpp */ -#ifndef __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_WANPARTICIPANT_HPP_ -#define __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_WANPARTICIPANT_HPP_ +#ifndef __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_WANDISCOVERYSERVERPARTICIPANT_HPP_ +#define __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_WANDISCOVERYSERVERPARTICIPANT_HPP_ #include #include @@ -30,12 +30,12 @@ namespace rtps { /** * TODO */ -class WANParticipant +class WanDiscoveryServerParticipant : public DiscoveryServerParticipant { public: - WANParticipant( + WanDiscoveryServerParticipant( const configuration::DiscoveryServerParticipantConfiguration participant_configuration, std::shared_ptr payload_pool, std::shared_ptr discovery_database); @@ -46,4 +46,4 @@ class WANParticipant } /* namespace ddsrouter */ } /* namespace eprosima */ -#endif /* __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_WANPARTICIPANT_HPP_ */ +#endif /* __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_WANDISCOVERYSERVERPARTICIPANT_HPP_ */ diff --git a/ddsrouter_core/src/cpp/participant/implementations/rtps/WanInitialPeersParticipant.cpp b/ddsrouter_core/src/cpp/participant/implementations/rtps/WanInitialPeersParticipant.cpp new file mode 100644 index 000000000..6bc596d98 --- /dev/null +++ b/ddsrouter_core/src/cpp/participant/implementations/rtps/WanInitialPeersParticipant.cpp @@ -0,0 +1,307 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file WanInitialPeersParticipant.cpp + */ + +#include +#include +#include +#include + +#include + +namespace eprosima { +namespace ddsrouter { +namespace core { +namespace rtps { + +using namespace eprosima::ddsrouter::core::types; + +WanInitialPeersParticipant::WanInitialPeersParticipant( + const configuration::InitialPeersParticipantConfiguration participant_configuration, + std::shared_ptr payload_pool, + std::shared_ptr discovery_database) + : CommonRTPSRouterParticipant + (participant_configuration, payload_pool, discovery_database) +{ + create_participant_(); +} + +fastrtps::rtps::RTPSParticipantAttributes WanInitialPeersParticipant::participant_attributes_() const +{ + // Auxiliary variable to save characters and improve readability + const auto& tls_config = this->configuration_.tls_configuration; + + // Set attributes + fastrtps::rtps::RTPSParticipantAttributes params; + // CommonRTPSRouterParticipant::participant_attributes(); // Use default as base attributes + + // Needed values to check at the end if descriptor must be set + bool has_listening_addresses = false; + bool has_connection_addresses = false; + bool has_listening_tcp_ipv4 = false; + bool has_listening_tcp_ipv6 = false; + bool has_connection_tcp_ipv4 = false; + bool has_connection_tcp_ipv6 = false; + bool has_connection_udp_ipv4 = false; + bool has_connection_udp_ipv6 = false; + bool has_udp_ipv4 = false; + bool has_udp_ipv6 = false; + + params.useBuiltinTransports = false; + + ///// + // Set listening addresses + for (const types::Address& address : this->configuration_.listening_addresses) + { + if (!address.is_valid()) + { + // Invalid address, continue with next one + logWarning(DDSROUTER_INITIALPEERS_PARTICIPANT, + "Discard listening address: " << address << " in Participant " << this->id() << " initialization."); + continue; + } + + has_listening_addresses = true; + + // TCP Listening WAN address + if (address.is_tcp()) + { + if (address.is_ipv4()) + { + has_listening_tcp_ipv4 = true; + + std::shared_ptr descriptor = + std::make_shared(); + + descriptor->add_listener_port(address.port()); + descriptor->set_WAN_address(address.ip()); + + // Enable TLS + if (tls_config.is_active()) + { + tls_config.enable_tls(descriptor); + } + + params.userTransports.push_back(descriptor); + } + else + { + has_listening_tcp_ipv6 = true; + + std::shared_ptr descriptor = + std::make_shared(); + + descriptor->add_listener_port(address.port()); + + // Enable TLS + if (tls_config.is_active()) + { + tls_config.enable_tls(descriptor); + } + + params.userTransports.push_back(descriptor); + } + } + else + { + has_udp_ipv4 = address.is_ipv4(); + has_udp_ipv6 = !address.is_ipv4(); + } + + // For any, UDP or TCP + // Create Locator + eprosima::fastrtps::rtps::Locator_t locator; + locator.kind = address.get_locator_kind(); + + // IP + if (address.is_ipv4()) + { + eprosima::fastrtps::rtps::IPLocator::setIPv4(locator, address.ip()); + eprosima::fastrtps::rtps::IPLocator::setWan(locator, address.ip()); + } + else + { + eprosima::fastrtps::rtps::IPLocator::setIPv6(locator, address.ip()); + } + + // Set Logical port for every locator + eprosima::fastrtps::rtps::IPLocator::setPhysicalPort(locator, address.port()); + + // In TCP case, set Physical port + if (address.is_tcp()) + { + eprosima::fastrtps::rtps::IPLocator::setLogicalPort(locator, address.port()); + } + + // Add listening address to builtin + params.builtin.metatrafficUnicastLocatorList.push_back(locator); + params.defaultUnicastLocatorList.push_back(locator); + + logDebug(DDSROUTER_INITIALPEERS_PARTICIPANT, + "Add listening address " << address << " to Participant " << this->id() << "."); + } + + ///// + // Set connection addresses + for (const types::Address& connection_address : this->configuration_.connection_addresses) + { + if (!connection_address.is_valid()) + { + // Invalid connection address, continue with next one + logWarning(DDSROUTER_INITIALPEERS_PARTICIPANT, + "Discard connection address: " << connection_address << + " in Participant " << this->id() << " initialization."); + continue; + } + + has_connection_addresses = true; + + // Create Locator for connection initial peers + eprosima::fastrtps::rtps::Locator_t locator; + + // KIND + locator.kind = connection_address.get_locator_kind(); + + // In case it is TCP mark has_connection_tcp as true + if (connection_address.is_tcp()) + { + has_connection_tcp_ipv4 = connection_address.is_ipv4(); + has_connection_tcp_ipv6 = !connection_address.is_ipv4(); + } + else + { + has_connection_udp_ipv4 = connection_address.is_ipv4(); + has_connection_udp_ipv6 = !connection_address.is_ipv4(); + has_udp_ipv4 = connection_address.is_ipv4(); + has_udp_ipv6 = !connection_address.is_ipv4(); + } + + // IP + if (connection_address.is_ipv4()) + { + eprosima::fastrtps::rtps::IPLocator::setIPv4(locator, connection_address.ip()); + } + else + { + eprosima::fastrtps::rtps::IPLocator::setIPv6(locator, connection_address.ip()); + } + + // Set Logical port for every locator + eprosima::fastrtps::rtps::IPLocator::setPhysicalPort(locator, connection_address.port()); + + // In TCP case, set Physical port + if (connection_address.is_tcp()) + { + eprosima::fastrtps::rtps::IPLocator::setLogicalPort(locator, connection_address.port()); + } + + // Add it to builtin + params.builtin.initialPeersList.push_back(locator); + + logDebug(DDSROUTER_INITIALPEERS_PARTICIPANT, + "Add connection address " << connection_address << + " to Participant " << this->id() << "."); + } + + ///// + // Create specific descriptors if needed + + // If has TCP connections but not TCP listening addresses, it must specify the TCP transport + if (has_connection_tcp_ipv4 && !has_listening_tcp_ipv4) + { + std::shared_ptr descriptor = + std::make_shared(); + + // Enable TLS + if (tls_config.is_active()) + { + tls_config.enable_tls(descriptor, true); + } + + params.userTransports.push_back(descriptor); + + logDebug(DDSROUTER_INITIALPEERS_PARTICIPANT, + "Adding TCPv4 Transport to Participant " << this->id() << "."); + } + + if (has_connection_tcp_ipv6 && !has_listening_tcp_ipv6) + { + std::shared_ptr descriptor = + std::make_shared(); + + // Enable TLS + if (tls_config.is_active()) + { + tls_config.enable_tls(descriptor, true); + } + + params.userTransports.push_back(descriptor); + + logDebug(DDSROUTER_INITIALPEERS_PARTICIPANT, + "Adding TCPv6 Transport to Participant " << this->id() << "."); + } + + // If has UDP, create descriptor because it has not been created yet + if (has_udp_ipv4) + { + std::shared_ptr descriptor = + std::make_shared(); + params.userTransports.push_back(descriptor); + + logDebug(DDSROUTER_INITIALPEERS_PARTICIPANT, + "Adding UDPv4 Transport to Participant " << this->id() << "."); + } + + if (has_udp_ipv6) + { + std::shared_ptr descriptor_v6 = + std::make_shared(); + params.userTransports.push_back(descriptor_v6); + + logDebug(DDSROUTER_INITIALPEERS_PARTICIPANT, + "Adding UDPv6 Transport to Participant " << this->id() << "."); + } + + // To avoid creating a multicast transport in UDP when non listening addresses + // Fast requires an empty locator that will be set by default afterwards + if (!has_listening_addresses) + { + if (has_connection_udp_ipv4) + { + eprosima::fastrtps::rtps::Locator_t locator; + locator.kind = LOCATOR_KIND_UDPv4; + params.builtin.metatrafficUnicastLocatorList.push_back(locator); + } + + if (has_connection_udp_ipv6) + { + eprosima::fastrtps::rtps::Locator_t locator; + locator.kind = LOCATOR_KIND_UDPv6; + params.builtin.metatrafficUnicastLocatorList.push_back(locator); + } + } + + logDebug(DDSROUTER_INITIALPEERS_PARTICIPANT, + "Configured Participant " << this->id()); + + return params; +} + +} /* namespace rtps */ +} /* namespace core */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ diff --git a/ddsrouter_core/src/cpp/participant/implementations/rtps/WanInitialPeersParticipant.hpp b/ddsrouter_core/src/cpp/participant/implementations/rtps/WanInitialPeersParticipant.hpp new file mode 100644 index 000000000..c279b83cc --- /dev/null +++ b/ddsrouter_core/src/cpp/participant/implementations/rtps/WanInitialPeersParticipant.hpp @@ -0,0 +1,56 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file WanInitialPeersParticipant.hpp + */ + +#ifndef __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_WANINITIALPEERSPARTICIPANT_HPP_ +#define __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_WANINITIALPEERSPARTICIPANT_HPP_ + +#include + +#include +#include + +#include + +namespace eprosima { +namespace ddsrouter { +namespace core { +namespace rtps { + +/** + * TODO + */ +class WanInitialPeersParticipant + : public CommonRTPSRouterParticipant +{ +public: + + WanInitialPeersParticipant( + const configuration::InitialPeersParticipantConfiguration participant_configuration, + std::shared_ptr payload_pool, + std::shared_ptr discovery_database); + + virtual fastrtps::rtps::RTPSParticipantAttributes participant_attributes_() const override; + +}; + +} /* namespace rpts */ +} /* namespace core */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ + +#endif /* __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_WANINITIALPEERSPARTICIPANT_HPP_ */ diff --git a/ddsrouter_core/src/cpp/participant/implementations/rtps/impl/CommonRTPSRouterParticipant.ipp b/ddsrouter_core/src/cpp/participant/implementations/rtps/impl/CommonRTPSRouterParticipant.ipp index bcf74a9f7..70d614e8a 100644 --- a/ddsrouter_core/src/cpp/participant/implementations/rtps/impl/CommonRTPSRouterParticipant.ipp +++ b/ddsrouter_core/src/cpp/participant/implementations/rtps/impl/CommonRTPSRouterParticipant.ipp @@ -234,7 +234,8 @@ void CommonRTPSRouterParticipant::create_participant_() logInfo(DDSROUTER_RTPS_PARTICIPANT, "New Participant " << this->configuration_.kind << " created with id " << this->id() << - " in domain " << domain << " with guid " << rtps_participant_->getGuid()); + " in domain " << domain << " with guid " << rtps_participant_->getGuid() << + (this->is_repeater() ? " (repeater)" : " (non repeater)")); } template @@ -242,15 +243,22 @@ std::shared_ptr CommonRTPSRouterParticipant::create_ types::RealTopic topic) { return std::make_shared( - this->id(), topic, - this->payload_pool_, rtps_participant_); + this->id(), + topic, + this->payload_pool_, + rtps_participant_, + this->configuration_.is_repeater); } template std::shared_ptr CommonRTPSRouterParticipant::create_reader_( types::RealTopic topic) { - return std::make_shared(this->id(), topic, this->payload_pool_, rtps_participant_); + return std::make_shared( + this->id(), + topic, + this->payload_pool_, + rtps_participant_); } template diff --git a/ddsrouter_core/src/cpp/participant/implementations/rtps/impl/DiscoveryServerParticipant.ipp b/ddsrouter_core/src/cpp/participant/implementations/rtps/impl/DiscoveryServerParticipant.ipp index 69ef53886..13a43b2df 100644 --- a/ddsrouter_core/src/cpp/participant/implementations/rtps/impl/DiscoveryServerParticipant.ipp +++ b/ddsrouter_core/src/cpp/participant/implementations/rtps/impl/DiscoveryServerParticipant.ipp @@ -104,7 +104,7 @@ DiscoveryServerParticipant::participant_attributes_() const // Enable TLS if (tls_config.is_active()) { - enable_tls(descriptor, tls_config); + tls_config.enable_tls(descriptor); } params.userTransports.push_back(descriptor); @@ -121,7 +121,7 @@ DiscoveryServerParticipant::participant_attributes_() const // Enable TLS if (tls_config.is_active()) { - enable_tls(descriptor, tls_config); + tls_config.enable_tls(descriptor); } params.userTransports.push_back(descriptor); @@ -274,7 +274,7 @@ DiscoveryServerParticipant::participant_attributes_() const // Enable TLS if (tls_config.is_active()) { - enable_tls(descriptor, tls_config, true); + tls_config.enable_tls(descriptor, true); } params.userTransports.push_back(descriptor); @@ -290,7 +290,7 @@ DiscoveryServerParticipant::participant_attributes_() const // Enable TLS if (tls_config.is_active()) { - enable_tls(descriptor, tls_config, true); + tls_config.enable_tls(descriptor, true); } params.userTransports.push_back(descriptor); @@ -326,109 +326,6 @@ DiscoveryServerParticipant::participant_attributes_() const return params; } -template -void DiscoveryServerParticipant::enable_tls( - std::shared_ptr descriptor, - const types::security::TlsConfiguration& tls_configuration, - bool client /* = false */) -{ - // Apply security ON - descriptor->apply_security = true; - - // Options - descriptor->tls_config.add_option( - eprosima::fastdds::rtps::TCPTransportDescriptor::TLSConfig::TLSOptions::DEFAULT_WORKAROUNDS); - descriptor->tls_config.add_option( - eprosima::fastdds::rtps::TCPTransportDescriptor::TLSConfig::TLSOptions::SINGLE_DH_USE); - descriptor->tls_config.add_option( - eprosima::fastdds::rtps::TCPTransportDescriptor::TLSConfig::TLSOptions::NO_SSLV2); // not safe - - // Perform verification of the server - descriptor->tls_config.add_verify_mode( - eprosima::fastdds::rtps::TCPTransportDescriptor::TLSConfig::TLSVerifyMode::VERIFY_PEER); - - if (client) - { - if (!tls_configuration.compatible()) - { - logError(DDSROUTER_DISCOVERYSERVER_PARTICIPANT, - "TLS Configuration expected a Client configuration."); - throw utils::ConfigurationException("TLS Configuration expected a Client configuration."); - } - else - { - enable_tls_client(descriptor, tls_configuration, true); - } - } - else - { - if (!tls_configuration.compatible()) - { - logError(DDSROUTER_DISCOVERYSERVER_PARTICIPANT, - "TLS Configuration expected a Server configuration."); - throw utils::ConfigurationException("TLS Configuration expected a Server configuration."); - } - else - { - // Add configuration for server - enable_tls_server(descriptor, tls_configuration); - - // In case it could also be client, add tls config - if (tls_configuration.compatible()) - { - enable_tls_client(descriptor, tls_configuration, false); - } - } - } - - logDebug(DDSROUTER_DISCOVERYSERVER_PARTICIPANT, - "TLS configured."); -} - -template -void DiscoveryServerParticipant::enable_tls_client( - std::shared_ptr descriptor, - const types::security::TlsConfiguration& tls_configuration, - bool only_client) -{ - if (!tls_configuration.compatible()) - { - utils::tsnh( - utils::Formatter() << "Error, TlsConfiguration expected a Client-compatible configuration."); - } - - if (only_client) - { - // Fail verification if the server has no certificate - descriptor->tls_config.add_verify_mode( - eprosima::fastdds::rtps::TCPTransportDescriptor::TLSConfig::TLSVerifyMode::VERIFY_FAIL_IF_NO_PEER_CERT); - } - - // CA certificate - descriptor->tls_config.verify_file = tls_configuration.certificate_authority_file(); -} - -template -void DiscoveryServerParticipant::enable_tls_server( - std::shared_ptr descriptor, - const types::security::TlsConfiguration& tls_configuration) -{ - if (!tls_configuration.compatible()) - { - utils::tsnh( - utils::Formatter() << "Error, TlsConfiguration expected a Server-compatible configuration."); - } - - // Password - descriptor->tls_config.password = tls_configuration.private_key_file_password(); - // Private key - descriptor->tls_config.private_key_file = tls_configuration.private_key_file(); - // DDS-Router certificate - descriptor->tls_config.cert_chain_file = tls_configuration.certificate_chain_file(); - // DH - descriptor->tls_config.tmp_dh_file = tls_configuration.dh_params_file(); -} - } /* namespace rtps */ } /* namespace core */ } /* namespace ddsrouter */ diff --git a/ddsrouter_core/src/cpp/reader/IReader.hpp b/ddsrouter_core/src/cpp/reader/IReader.hpp index 10822e676..df3e856e6 100644 --- a/ddsrouter_core/src/cpp/reader/IReader.hpp +++ b/ddsrouter_core/src/cpp/reader/IReader.hpp @@ -26,7 +26,7 @@ #include #include -#include +#include namespace eprosima { namespace ddsrouter { diff --git a/ddsrouter_core/src/cpp/reader/implementations/rtps/Reader.cpp b/ddsrouter_core/src/cpp/reader/implementations/rtps/Reader.cpp index 4e44e0138..95ff0b2f6 100644 --- a/ddsrouter_core/src/cpp/reader/implementations/rtps/Reader.cpp +++ b/ddsrouter_core/src/cpp/reader/implementations/rtps/Reader.cpp @@ -277,6 +277,10 @@ void Reader::onNewCacheChangeAdded( } else { + logWarning( + DDSROUTER_RTPS_READER_LISTENER, + "Ignoring data from this same Participant in reader " << *this << "."); + // If it is a message from this Participant, do not send it forward and remove it // TODO: do this more elegant rtps_reader_->getHistory()->remove_change((fastrtps::rtps::CacheChange_t*)change); diff --git a/ddsrouter_core/src/cpp/types/address/Address.cpp b/ddsrouter_core/src/cpp/types/address/Address.cpp index b5c135dad..055b3f857 100644 --- a/ddsrouter_core/src/cpp/types/address/Address.cpp +++ b/ddsrouter_core/src/cpp/types/address/Address.cpp @@ -156,7 +156,7 @@ bool Address::is_ipv6() const noexcept return ip_version_ == IpVersion::v6; } -LocatorType Address::get_locator_kind() noexcept +LocatorType Address::get_locator_kind() const noexcept { if (ip_version_ == IpVersion::v4) { diff --git a/ddsrouter_core/src/cpp/types/dds/RouterCacheChange.hpp b/ddsrouter_core/src/cpp/types/dds/RouterCacheChange.hpp new file mode 100644 index 000000000..4369934f9 --- /dev/null +++ b/ddsrouter_core/src/cpp/types/dds/RouterCacheChange.hpp @@ -0,0 +1,62 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file RouterCacheChange.hpp + */ + +#ifndef __SRC_DDSROUTERCORE_TYPES_DDS_ROUTERCACHECHANGE_HPP_ +#define __SRC_DDSROUTERCORE_TYPES_DDS_ROUTERCACHECHANGE_HPP_ + +#include +#include + +#include + +namespace eprosima { +namespace ddsrouter { +namespace core { +namespace types { + +/** + * @brief Specialization of CacheChange for DDS Router. + * + * It adds the following attributes: + * - last_writer_guid_prefix: store last jump of message Participant GuidPrefix + * + * This Change is required to be used for features: + * - Repeater participant: avoid redirecting the message to the source participant. + */ +struct RouterCacheChange : public fastrtps::rtps::CacheChange_t +{ +public: + + //! Using parent constructors + using fastrtps::rtps::CacheChange_t::CacheChange_t; + + /** + * @brief GuidPrefix of the Participant that has sent this message through the router. + * + * @note it is not the same as origin writer, as there could be more routers in the path. + */ + fastrtps::rtps::GuidPrefix_t last_writer_guid_prefix; +}; + +} /* namespace types */ +} /* namespace core */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ + +#endif /* __SRC_DDSROUTERCORE_TYPES_DDS_ROUTERCACHECHANGE_HPP_ */ + diff --git a/ddsrouter_core/src/cpp/types/security/tls/TlsConfiguration.cpp b/ddsrouter_core/src/cpp/types/security/tls/TlsConfiguration.cpp index 47ece2d07..8bf195698 100644 --- a/ddsrouter_core/src/cpp/types/security/tls/TlsConfiguration.cpp +++ b/ddsrouter_core/src/cpp/types/security/tls/TlsConfiguration.cpp @@ -17,9 +17,13 @@ * */ -#include -#include +#include #include +#include +#include +#include + +#include namespace eprosima { namespace ddsrouter { @@ -166,6 +170,103 @@ const std::string& TlsConfiguration::dh_params_file() const } } +void TlsConfiguration::enable_tls( + std::shared_ptr descriptor, + bool client /* = false */) const +{ + // Apply security ON + descriptor->apply_security = true; + + // Options + descriptor->tls_config.add_option( + eprosima::fastdds::rtps::TCPTransportDescriptor::TLSConfig::TLSOptions::DEFAULT_WORKAROUNDS); + descriptor->tls_config.add_option( + eprosima::fastdds::rtps::TCPTransportDescriptor::TLSConfig::TLSOptions::SINGLE_DH_USE); + descriptor->tls_config.add_option( + eprosima::fastdds::rtps::TCPTransportDescriptor::TLSConfig::TLSOptions::NO_SSLV2); // not safe + + // Perform verification of the server + descriptor->tls_config.add_verify_mode( + eprosima::fastdds::rtps::TCPTransportDescriptor::TLSConfig::TLSVerifyMode::VERIFY_PEER); + + if (client) + { + if (!compatible()) + { + logError(DDSROUTER_DISCOVERYSERVER_PARTICIPANT, + "TLS Configuration expected a Client configuration."); + throw utils::ConfigurationException("TLS Configuration expected a Client configuration."); + } + else + { + enable_tls_client(descriptor, true); + } + } + else + { + if (!compatible()) + { + logError(DDSROUTER_DISCOVERYSERVER_PARTICIPANT, + "TLS Configuration expected a Server configuration."); + throw utils::ConfigurationException("TLS Configuration expected a Server configuration."); + } + else + { + // Add configuration for server + enable_tls_server(descriptor); + + // In case it could also be client, add tls config + if (compatible()) + { + enable_tls_client(descriptor, false); + } + } + } + + logDebug(DDSROUTER_DISCOVERYSERVER_PARTICIPANT, + "TLS configured."); +} + +void TlsConfiguration::enable_tls_client( + std::shared_ptr descriptor, + bool only_client) const +{ + if (!compatible()) + { + utils::tsnh( + utils::Formatter() << "Error, TlsConfiguration expected a Client-compatible configuration."); + } + + if (only_client) + { + // Fail verification if the server has no certificate + descriptor->tls_config.add_verify_mode( + eprosima::fastdds::rtps::TCPTransportDescriptor::TLSConfig::TLSVerifyMode::VERIFY_FAIL_IF_NO_PEER_CERT); + } + + // CA certificate + descriptor->tls_config.verify_file = certificate_authority_file(); +} + +void TlsConfiguration::enable_tls_server( + std::shared_ptr descriptor) const +{ + if (!compatible()) + { + utils::tsnh( + utils::Formatter() << "Error, TlsConfiguration expected a Server-compatible configuration."); + } + + // Password + descriptor->tls_config.password = private_key_file_password(); + // Private key + descriptor->tls_config.private_key_file = private_key_file(); + // DDS-Router certificate + descriptor->tls_config.cert_chain_file = certificate_chain_file(); + // DH + descriptor->tls_config.tmp_dh_file = dh_params_file(); +} + } /* namespace security */ } /* namespace types */ } /* namespace core */ diff --git a/ddsrouter_core/src/cpp/writer/IWriter.hpp b/ddsrouter_core/src/cpp/writer/IWriter.hpp index d5bb9b47c..f0b844c3a 100644 --- a/ddsrouter_core/src/cpp/writer/IWriter.hpp +++ b/ddsrouter_core/src/cpp/writer/IWriter.hpp @@ -24,7 +24,7 @@ #include #include -#include +#include namespace eprosima { namespace ddsrouter { diff --git a/ddsrouter_core/src/cpp/writer/implementations/rtps/Writer.cpp b/ddsrouter_core/src/cpp/writer/implementations/rtps/Writer.cpp index 308e88d3f..763547566 100644 --- a/ddsrouter_core/src/cpp/writer/implementations/rtps/Writer.cpp +++ b/ddsrouter_core/src/cpp/writer/implementations/rtps/Writer.cpp @@ -20,9 +20,13 @@ #include #include -#include #include #include +#include +#include +#include +#include +#include namespace eprosima { namespace ddsrouter { @@ -35,8 +39,10 @@ Writer::Writer( const ParticipantId& participant_id, const RealTopic& topic, std::shared_ptr payload_pool, - fastrtps::rtps::RTPSParticipant* rtps_participant) + fastrtps::rtps::RTPSParticipant* rtps_participant, + const bool repeater /* = false */) : BaseWriter(participant_id, topic, payload_pool) + , repeater_(repeater) { // TODO Use payload pool for this writer, so change does not need to be copied @@ -46,12 +52,29 @@ Writer::Writer( // Create Writer fastrtps::rtps::WriterAttributes writer_att = writer_attributes_(); - rtps_writer_ = fastrtps::rtps::RTPSDomain::createRTPSWriter( - rtps_participant, - writer_att, - payload_pool_, - rtps_history_, - nullptr); + + if (repeater) + { + logDebug(DDSROUTER_RTPS_WRITER, "Writer created with repeater filter"); + + utils::PoolConfiguration pool_config = cache_change_pool_configuration_(); + rtps_writer_ = fastrtps::rtps::RTPSDomain::createRTPSWriter( + rtps_participant, + writer_att, + payload_pool_, + std::make_shared(pool_config), + rtps_history_, + nullptr); + } + else + { + rtps_writer_ = fastrtps::rtps::RTPSDomain::createRTPSWriter( + rtps_participant, + writer_att, + payload_pool_, + rtps_history_, + nullptr); + } if (!rtps_writer_) { @@ -72,6 +95,19 @@ Writer::Writer( " for Simple RTPSWriter in Participant " << participant_id); } + if (repeater) + { + // Use filter writer of origin + data_filter_ = std::make_unique(); + } + else + { + // Use default filter + data_filter_ = std::make_unique(); + } + + rtps_writer_->reader_data_filter(data_filter_.get()); + logInfo(DDSROUTER_RTPS_WRITER, "New Writer created in Participant " << participant_id_ << " for topic " << topic << " with guid " << rtps_writer_->getGuid()); } @@ -136,6 +172,13 @@ utils::ReturnCode Writer::write_( "Writer " << *this << " sending payload " << new_change->serializedPayload << " from " << data->source_guid); + if (repeater_) + { + // Add origin to change in case the cache change is RouterCacheChange (only in repeater mode) + types::RouterCacheChange& change_ref = static_cast(*new_change); + change_ref.last_writer_guid_prefix = data->source_guid.guidPrefix; + } + // Send data by adding it to Writer History rtps_history_->add_change(new_change); @@ -193,6 +236,17 @@ fastrtps::WriterQos Writer::writer_qos_() const noexcept return qos; } +utils::PoolConfiguration Writer::cache_change_pool_configuration_() const noexcept +{ + utils::PoolConfiguration config; + config.maximum_size = 0; // No maximum + config.initial_size = 20; + config.batch_size = 20; + // NOTE: Not use of memory policy or maximum yet + + return config; +} + } /* namespace rtps */ } /* namespace core */ } /* namespace ddsrouter */ diff --git a/ddsrouter_core/src/cpp/writer/implementations/rtps/Writer.hpp b/ddsrouter_core/src/cpp/writer/implementations/rtps/Writer.hpp index c6be5ba53..9c5e052f2 100644 --- a/ddsrouter_core/src/cpp/writer/implementations/rtps/Writer.hpp +++ b/ddsrouter_core/src/cpp/writer/implementations/rtps/Writer.hpp @@ -28,8 +28,28 @@ #include #include - #include +#include + +///// +// Forward declarations +namespace eprosima { +namespace ddsrouter { +namespace core { + +struct CacheChangePoolConfiguration; + +} /* namespace core */ +} /* namespace ddsrouter */ + +namespace fastdds { +namespace rtps { + +struct IReaderDataFilter; + +} /* namespace rtps */ +} /* namespace fastdds */ +} /* namespace eprosima */ namespace eprosima { namespace ddsrouter { @@ -59,7 +79,8 @@ class Writer : public BaseWriter const types::ParticipantId& participant_id, const types::RealTopic& topic, std::shared_ptr payload_pool, - fastrtps::rtps::RTPSParticipant* rtps_participant); + fastrtps::rtps::RTPSParticipant* rtps_participant, + const bool repeater = false); /** * @brief Destroy the Writer object @@ -122,6 +143,9 @@ class Writer : public BaseWriter //! Default QoS Writer (must be the same as the attributes) fastrtps::WriterQos writer_qos_() const noexcept; + //! Default Cache Change Pool Configuration + utils::PoolConfiguration cache_change_pool_configuration_() const noexcept; + ///// // VARIABLES @@ -130,6 +154,11 @@ class Writer : public BaseWriter //! RTPS Writer History associated to \c rtps_reader_ fastrtps::rtps::WriterHistory* rtps_history_; + + //! Data Filter used to filter cache changes at the RTPSWriter level. + std::unique_ptr data_filter_; + + bool repeater_; }; } /* namespace rtps */ diff --git a/ddsrouter_core/src/cpp/writer/implementations/rtps/filter/RepeaterDataFilter.cpp b/ddsrouter_core/src/cpp/writer/implementations/rtps/filter/RepeaterDataFilter.cpp new file mode 100644 index 000000000..d685e5f6c --- /dev/null +++ b/ddsrouter_core/src/cpp/writer/implementations/rtps/filter/RepeaterDataFilter.cpp @@ -0,0 +1,61 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file RepeaterDataFilter.cpp + */ + +#include +#include +#include + +#include +#include + +namespace eprosima { +namespace ddsrouter { +namespace core { +namespace rtps { + +bool RepeaterDataFilter::is_relevant( + const fastrtps::rtps::CacheChange_t& change, + const fastrtps::rtps::GUID_t& reader_guid) const +{ + if (!SelfDataFilter::is_relevant(change, reader_guid)) + { + logDebug( + REPEATER_DATA_FILTER, + "Ignoring message by SelfDataFilter is_relevant result."); + + // If origin filter does not pass this change, it is discarded + return false; + } + + // As ChangePool is our own, and we use RouterCacheChange, we can cast this without problem + const auto& change_ref = static_cast(change); + + bool is_relevant = change_ref.last_writer_guid_prefix != reader_guid.guidPrefix; + + logDebug( + REPEATER_DATA_FILTER, + "Evaluating whether Change with origin writer GUID prefix " << change_ref.last_writer_guid_prefix << + " is relevant for reader GUID " << reader_guid << "? " << (is_relevant ? "TRUE" : "FALSE")); + + return is_relevant; +} + +} /* namespace rtps */ +} /* namespace core */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ diff --git a/ddsrouter_core/src/cpp/writer/implementations/rtps/filter/RepeaterDataFilter.hpp b/ddsrouter_core/src/cpp/writer/implementations/rtps/filter/RepeaterDataFilter.hpp new file mode 100644 index 000000000..91f7737a9 --- /dev/null +++ b/ddsrouter_core/src/cpp/writer/implementations/rtps/filter/RepeaterDataFilter.hpp @@ -0,0 +1,59 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file RepeaterDataFilter.hpp + */ + +#ifndef __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_FILTER_REPEATERDATAFILTER_HPP_ +#define __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_FILTER_REPEATERDATAFILTER_HPP_ + +#include + +namespace eprosima { +namespace ddsrouter { +namespace core { +namespace rtps { + +/** + * This filter allows to not send messages from this Writer to the Readers belonging to the source Participant. + * It is used in "repeater" participants in order to propagate information to external participants + * (participants not belonging to the same DDS-Router instance), + * leaving out the participant from which this information was received. + * + * This uses the RouterCacheChange extra information. + */ +class RepeaterDataFilter : public SelfDataFilter +{ +public: + + /** + * @brief Whether incoming change is relevant for this reader. + * + * @return true if the reader does not belong to Participant that previously sent this message. + * @return false otherwise. + */ + bool is_relevant( + const fastrtps::rtps::CacheChange_t& change, + const fastrtps::rtps::GUID_t& reader_guid + ) const override; +}; + +} /* namespace rtps */ +} /* namespace core */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ + +#endif /* __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_FILTER_REPEATERDATAFILTER_HPP_ */ + diff --git a/ddsrouter_core/src/cpp/writer/implementations/rtps/filter/SelfDataFilter.cpp b/ddsrouter_core/src/cpp/writer/implementations/rtps/filter/SelfDataFilter.cpp new file mode 100644 index 000000000..ce87c314a --- /dev/null +++ b/ddsrouter_core/src/cpp/writer/implementations/rtps/filter/SelfDataFilter.cpp @@ -0,0 +1,42 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file SelfDataFilter.cpp + */ + +#include +#include +#include + +#include +#include + +namespace eprosima { +namespace ddsrouter { +namespace core { +namespace rtps { + +bool SelfDataFilter::is_relevant( + const fastrtps::rtps::CacheChange_t& change, + const fastrtps::rtps::GUID_t& reader_guid) const +{ + // It is relevant only if the reader does not belong to same participant as writer + return change.writerGUID.guidPrefix != reader_guid.guidPrefix; +} + +} /* namespace rtps */ +} /* namespace core */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ diff --git a/ddsrouter_core/src/cpp/writer/implementations/rtps/filter/SelfDataFilter.hpp b/ddsrouter_core/src/cpp/writer/implementations/rtps/filter/SelfDataFilter.hpp new file mode 100644 index 000000000..3184819f7 --- /dev/null +++ b/ddsrouter_core/src/cpp/writer/implementations/rtps/filter/SelfDataFilter.hpp @@ -0,0 +1,67 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file SelfDataFilter.hpp + */ + +#ifndef __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_FILTER_SelfParticipantDataFilter_HPP_ +#define __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_FILTER_SelfParticipantDataFilter_HPP_ + +#include + +///// +// Forward declarations +namespace eprosima { +namespace fastrtps { +namespace rtps { + +struct CacheChange_t; +struct GUID_t; + +} /* namespace rtps */ +} /* namespace fastrtps */ +} /* namespace eprosima */ + +namespace eprosima { +namespace ddsrouter { +namespace core { +namespace rtps { + +/** + * This filter allows to not send messages from this Writer to the Readers in the same Participant. + */ +class SelfDataFilter : public fastdds::rtps::IReaderDataFilter +{ +public: + + /** + * @brief Whether incoming change is relevant for this reader. + * + * @return true if the reader does not belong to same Participant. + * @return false otherwise. + */ + bool is_relevant( + const fastrtps::rtps::CacheChange_t& change, + const fastrtps::rtps::GUID_t& reader_guid + ) const override; +}; + +} /* namespace rtps */ +} /* namespace core */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ + +#endif /* __SRC_DDSROUTERCORE_PARTICIPANT_IMPLEMENTATIONS_RTPS_FILTER_SelfParticipantDataFilter_HPP_ */ + diff --git a/ddsrouter_core/test/TestUtils/test_utils.cpp b/ddsrouter_core/test/TestUtils/test_utils.cpp index a92506694..927ae2989 100644 --- a/ddsrouter_core/test/TestUtils/test_utils.cpp +++ b/ddsrouter_core/test/TestUtils/test_utils.cpp @@ -220,10 +220,11 @@ std::shared_ptr random_participan return std::make_shared( id, kind, + false, random_domain(seed)); case ParticipantKind::local_discovery_server: - case ParticipantKind::wan: + case ParticipantKind::wan_discovery_server: { // TODO get random values @@ -235,6 +236,7 @@ std::shared_ptr random_participan return std::make_shared( id, kind, + false, random_domain(seed), random_guid_prefix(seed), std::set
(), @@ -242,9 +244,22 @@ std::shared_ptr random_participan security::TlsConfiguration()); } + case ParticipantKind::wan_initial_peers: + + { + return std::make_shared( + id, + kind, + false, + random_domain(seed), + std::set
(), + std::set
({Address()}), + security::TlsConfiguration()); + } + // Add cases where Participants need specific arguments default: - return std::make_shared(id, kind); + return std::make_shared(id, kind, false); } } diff --git a/ddsrouter_core/test/TestUtils/test_utils.hpp b/ddsrouter_core/test/TestUtils/test_utils.hpp index cf6d70601..cd8dd5038 100644 --- a/ddsrouter_core/test/TestUtils/test_utils.hpp +++ b/ddsrouter_core/test/TestUtils/test_utils.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/ddsrouter_core/test/blackbox/ddsrouter_core/dds/CMakeLists.txt b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/CMakeLists.txt index e0dd990dd..fa027636a 100644 --- a/ddsrouter_core/test/blackbox/ddsrouter_core/dds/CMakeLists.txt +++ b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/CMakeLists.txt @@ -12,5 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. +add_subdirectory(InitialPeers) add_subdirectory(local) add_subdirectory(WAN) diff --git a/ddsrouter_core/test/blackbox/ddsrouter_core/dds/InitialPeers/CMakeLists.txt b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/InitialPeers/CMakeLists.txt new file mode 100644 index 000000000..593b24ade --- /dev/null +++ b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/InitialPeers/CMakeLists.txt @@ -0,0 +1,60 @@ +# Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################ +# DDS Test InitialPeers # +################ + +set(TEST_NAME + DDSTestInitialPeers) + +set(TEST_SOURCES + DDSTestInitialPeers.cpp + ${PROJECT_SOURCE_DIR}/test/blackbox/ddsrouter_core/dds/types/HelloWorld/HelloWorld.cxx + ${PROJECT_SOURCE_DIR}/test/blackbox/ddsrouter_core/dds/types/HelloWorld/HelloWorldPubSubTypes.cxx + ${PROJECT_SOURCE_DIR}/test/blackbox/ddsrouter_core/dds/types/HelloWorldKeyed/HelloWorldKeyed.cxx + ${PROJECT_SOURCE_DIR}/test/blackbox/ddsrouter_core/dds/types/HelloWorldKeyed/HelloWorldKeyedPubSubTypes.cxx) + +set(TEST_LIST + end_to_end_InitialPeers_communication_UDPv4 + end_to_end_InitialPeers_communication_UDPv6 + end_to_end_InitialPeers_communication_TCPv4 + end_to_end_InitialPeers_communication_TCPv6 + end_to_end_InitialPeers_communication_TLSv4 + end_to_end_InitialPeers_communication_TLSv6 + end_to_end_InitialPeers_communication_high_throughput + ) + + +set(TEST_NEEDED_SOURCES + # TLS security files + ../../resources/tls/ca.crt + ../../resources/tls/ddsrouter.crt + ../../resources/tls/ddsrouter.key + ../../resources/tls/dh_params.pem + ) + +set(TEST_EXTRA_HEADERS + ${PROJECT_SOURCE_DIR}/test/blackbox/ddsrouter_core/dds/types/HelloWorld + ${PROJECT_SOURCE_DIR}/test/blackbox/ddsrouter_core/dds/types) + +add_blackbox_executable( + "${TEST_NAME}" + "${TEST_SOURCES}" + "${TEST_LIST}" + "${TEST_NEEDED_SOURCES}" + "${TEST_EXTRA_HEADERS}") + +# Set flaky tests as xfail +add_xfail_label(${CMAKE_CURRENT_SOURCE_DIR}/TEST_XFAIL.list) diff --git a/ddsrouter_core/test/blackbox/ddsrouter_core/dds/InitialPeers/DDSTestInitialPeers.cpp b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/InitialPeers/DDSTestInitialPeers.cpp new file mode 100644 index 000000000..3f9347627 --- /dev/null +++ b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/InitialPeers/DDSTestInitialPeers.cpp @@ -0,0 +1,481 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +namespace eprosima { +namespace ddsrouter { +namespace core { +namespace test { + +enum class WanKind +{ + server, + client, + server_and_client +}; + +bool is_client( + WanKind wan_kind) +{ + return wan_kind == WanKind::client || wan_kind == WanKind::server_and_client; +} + +bool is_server( + WanKind wan_kind) +{ + return wan_kind == WanKind::server || wan_kind == WanKind::server_and_client; +} + +constexpr const uint32_t DEFAULT_SAMPLES_TO_RECEIVE = 5; +constexpr const uint32_t DEFAULT_MILLISECONDS_PUBLISH_LOOP = 100; +constexpr const uint32_t DEFAULT_MESSAGE_SIZE = 1; // x50 bytes + +types::security::TlsConfiguration tls_configuration( + WanKind wan_kind) +{ + // TODO: test that using server with only Server required files works + // It fails when connecting to other server + if (is_server(wan_kind)) + { + return types::security::TlsConfiguration( + "../../resources/tls/ca.crt", // ca + "", // private key password + "../../resources/tls/ddsrouter.key", // private key + "../../resources/tls/ddsrouter.crt", // cert + "../../resources/tls/dh_params.pem" // dh params + ); + } + else + { + return types::security::TlsConfiguration( + "../../resources/tls/ca.crt" // ca + ); + } +} + +std::shared_ptr wan_participant_configuration( + bool this_server_id_is_1, + WanKind wan_kind, + types::TransportProtocol transport_protocol, + types::IpVersion ip_version, + bool tls = false) +{ + std::set listening_addresses; + std::set connection_addresses; + types::DomainId domain(60u); + + if (is_client(wan_kind)) + { + connection_addresses.insert( + types::Address( + (ip_version == types::IpVersion::v4 ? "127.0.0.1" : "::1"), + 11666 + (this_server_id_is_1 ? 0u : 1u), + ip_version, + transport_protocol) + ); + } + + if (is_server(wan_kind)) + { + listening_addresses.insert( + types::Address( + (ip_version == types::IpVersion::v4 ? "127.0.0.1" : "::1"), + 11666 + (this_server_id_is_1 ? 1u : 0u), + ip_version, + transport_protocol) + ); + } + + if (tls) + { + return std::make_shared( + types::ParticipantId("InitialPeersParticipant_" + std::to_string((this_server_id_is_1 ? 1 : 0))), + types::ParticipantKind::wan_initial_peers, + false, + domain, + listening_addresses, + connection_addresses, + tls_configuration(wan_kind)); + + } + else + { + return std::make_shared( + types::ParticipantId("InitialPeersParticipant_" + std::to_string((this_server_id_is_1 ? 1 : 0))), + types::ParticipantKind::wan_initial_peers, + false, + domain, + listening_addresses, + connection_addresses, + types::security::TlsConfiguration()); + } +} + +/** + * @brief Create a simple configuration for a DDS Router + * + * Create a configuration with 1 topic + * Create 1 simple participants with domains \c domain + * Create 1 custom participant by the configuration in \c participant_configuration + * + * @return configuration::DDSRouterConfiguration + */ +configuration::DDSRouterConfiguration router_configuration( + std::shared_ptr participant_configuration, + types::DomainIdType domain) +{ + // One topic + std::set> allowlist( + { + std::make_shared(TOPIC_NAME, "HelloWorld"), + }); + + std::set> blocklist; // empty + + std::set> builtin_topics; // empty + + // Two participants, one custom and other simple. If server, simple will work in 0, if not in 1 + std::set> participants_configurations( + { + // custom + participant_configuration, + + // simple + std::make_shared( + types::ParticipantId("simple_participant_" + std::to_string(domain)), + types::ParticipantKind(types::ParticipantKind::simple_rtps), + false, + types::DomainId(domain) + ), + } + ); + + configuration::DDSRouterConfiguration configuration; + configuration.allowlist = allowlist; + configuration.participants_configurations = participants_configurations; + + return configuration; +} + +/** + * Test communication between two DDS Participants hosted in the same device, but which are at different DDS domains. + * This is accomplished by connecting two InitialPeers Participants belonging to different DDS Router instances. These router + * instances communicate with the DDS Participants through Simple Participants deployed at those domains. + */ +void test_InitialPeers_communication( + configuration::DDSRouterConfiguration ddsrouter_server_configuration, + configuration::DDSRouterConfiguration ddsrouter_client_configuration, + uint32_t samples_to_receive = DEFAULT_SAMPLES_TO_RECEIVE, + uint32_t time_between_samples = DEFAULT_MILLISECONDS_PUBLISH_LOOP, + uint32_t msg_size = DEFAULT_MESSAGE_SIZE) +{ + // Check there are no warnings/errors + // TODO: Uncomment when having no listening addresses is no longer considered an error by the middleware + // TODO: Change threshold to \c Log::Kind::Warning once middleware warnings are solved + // test::TestLogHandler test_log_handler(Log::Kind::Error); + + uint32_t samples_sent = 0; + std::atomic samples_received(0); + + // Create a message with size specified by repeating the same string + HelloWorld msg; + std::string msg_str; + + // Add this string as many times as the msg size requires + for (uint32_t i = 0; i < msg_size; i++) + { + msg_str += "Testing DDSRouter Blackbox Local Communication ..."; + } + msg.message(msg_str); + + // Create DDS Publisher in domain 0 + TestPublisher publisher; + ASSERT_TRUE(publisher.init(0)); + + // Create DDS Subscriber in domain 1 + TestSubscriber subscriber; + ASSERT_TRUE(subscriber.init(1, &msg, &samples_received)); + + // Create DDSRouter entity whose InitialPeers Participant is configured as server + DDSRouter server_router(ddsrouter_server_configuration); + server_router.start(); + + // Create DDSRouter entity whose InitialPeers Participant is configured as client + DDSRouter client_router(ddsrouter_client_configuration); + client_router.start(); + + // Start publishing + while (samples_received.load() < samples_to_receive) + { + msg.index(++samples_sent); + publisher.publish(msg); + + // If time is 0 do not wait + if (time_between_samples > 0) + { + std::this_thread::sleep_for(std::chrono::milliseconds(time_between_samples)); + } + } + + client_router.stop(); + server_router.stop(); +} + +/** + * Test communication between InitialPeers participants by running \c test_InitialPeers_communication for different configurations. + * Different combinations of server/client configurations are tested. + * + * CASES: + * server <-> client + * server <-> server-client + * server-client <-> server-client (only when basic_only is deactivate) + */ +void test_InitialPeers_communication_all( + types::TransportProtocol transport_protocol, + types::IpVersion ip_version, + bool basic_only = false, + bool tls = false) +{ + // Test architecture server <-> client + test::test_InitialPeers_communication( + test::router_configuration( + test::wan_participant_configuration( + true, // is server 1 + WanKind::server, + transport_protocol, // transport protocol + ip_version, // ip version + tls // tls + ), + 0 // domain + ), + + test::router_configuration( + test::wan_participant_configuration( + false, // is server 1 + WanKind::client, + transport_protocol, // transport protocol + ip_version, // ip version + tls // tls + ), + 1 // domain + ) + ); + + // Test architecture server <-> server-client + test::test_InitialPeers_communication( + test::router_configuration( + test::wan_participant_configuration( + true, // is server 1 + WanKind::server, + transport_protocol, // transport protocol + ip_version, // ip version + tls // tls + ), + 0 // domain + ), + + test::router_configuration( + test::wan_participant_configuration( + false, // is server 1 + WanKind::server_and_client, + transport_protocol, // transport protocol + ip_version, // ip version + tls // tls + ), + 1 // domain + ) + ); + + // This test is disabled for TCPv6 and TLSv6, as an underlying middleware issue resulting in no matching for this + // scenario exists. + // TODO: Test this as well for TCPv6 and TLSv6 cases when issue is fixed + if (!basic_only) + { + // Test architecture server-client <-> server-client + test::test_InitialPeers_communication( + test::router_configuration( + test::wan_participant_configuration( + true, // is server 1 + WanKind::server_and_client, + transport_protocol, // transport protocol + ip_version, // ip version + tls // tls + ), + 0 // domain + ), + + test::router_configuration( + test::wan_participant_configuration( + false, // is server 1 + WanKind::server_and_client, + transport_protocol, // transport protocol + ip_version, // ip version + tls // tls + ), + 1 // domain + ) + ); + } +} + +} /* namespace test */ +} /* namespace core */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ + +using namespace eprosima::ddsrouter::core; +using namespace eprosima::ddsrouter::core::types; + +/** + * Test communication in HelloWorld topic between two DDS participants created in different domains, + * by using two routers with two Simple Participants at each domain, and two InitialPeers Participants connected + * through UDPv4. + */ +TEST(DDSTestInitialPeers, end_to_end_InitialPeers_communication_UDPv4) +{ + test::test_InitialPeers_communication_all( + types::TransportProtocol::udp, + types::IpVersion::v4); +} + +/** + * Test communication in HelloWorld topic between two DDS participants created in different domains, + * by using two routers with two Simple Participants at each domain, and two InitialPeers Participants connected + * through UDPv6. + */ +TEST(DDSTestInitialPeers, end_to_end_InitialPeers_communication_UDPv6) +{ + test::test_InitialPeers_communication_all( + types::TransportProtocol::udp, + types::IpVersion::v6); +} + +/** + * Test communication in HelloWorld topic between two DDS participants created in different domains, + * by using two routers with two Simple Participants at each domain, and two InitialPeers Participants connected + * through TCPv4. + */ +TEST(DDSTestInitialPeers, end_to_end_InitialPeers_communication_TCPv4) +{ + test::test_InitialPeers_communication_all( + types::TransportProtocol::tcp, + types::IpVersion::v4); +} + +/** + * Test communication in HelloWorld topic between two DDS participants created in different domains, + * by using two routers with two Simple Participants at each domain, and two InitialPeers Participants connected + * through TCPv6. + */ +TEST(DDSTestInitialPeers, end_to_end_InitialPeers_communication_TCPv6) +{ + test::test_InitialPeers_communication_all( + types::TransportProtocol::tcp, + types::IpVersion::v6, + true); +} + +/** + * Test communication in HelloWorld topic between two DDS participants created in different domains, + * by using two routers with two Simple Participants at each domain, and two InitialPeers Participants connected + * through TLSv4. + */ +TEST(DDSTestInitialPeers, end_to_end_InitialPeers_communication_TLSv4) +{ + test::test_InitialPeers_communication_all( + types::TransportProtocol::tcp, + types::IpVersion::v4, + false, + true); +} + +/** + * Test communication in HelloWorld topic between two DDS participants created in different domains, + * by using two routers with two Simple Participants at each domain, and two InitialPeers Participants connected + * through TLSv6. + */ +TEST(DDSTestInitialPeers, end_to_end_InitialPeers_communication_TLSv6) +{ + test::test_InitialPeers_communication_all( + types::TransportProtocol::tcp, + types::IpVersion::v6, + true, + true); +} + +/** + * Test high throughput communication in HelloWorld topic between two DDS participants created in different domains, + * by using two routers with two Simple Participants at each domain, and two InitialPeers Participants connected + * through UDPv4. + * + * PARAMETERS: + * - Frequency: 1ms + * - Sample size: 50K + * -> Throughput: 50MBps + */ +TEST(DDSTestInitialPeers, end_to_end_InitialPeers_communication_high_throughput) +{ + test::test_InitialPeers_communication( + test::router_configuration( + test::wan_participant_configuration( + true, // is server 1 + test::WanKind::server, + types::TransportProtocol::udp, // transport protocol + types::IpVersion::v4 // ip version + ), + 0 // domain + ), + + test::router_configuration( + test::wan_participant_configuration( + false, // is server 1 + test::WanKind::client, + types::TransportProtocol::udp, // transport protocol + types::IpVersion::v4 // ip version + ), + 1 // domain + ), + + 500, + 1, + 1000); // 50K message size +} + +int main( + int argc, + char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + + // eprosima::ddsrouter::utils::Log::SetVerbosity(eprosima::ddsrouter::utils::Log::Kind::Info); + + return RUN_ALL_TESTS(); +} diff --git a/ddsrouter_core/test/blackbox/ddsrouter_core/dds/InitialPeers/README.md b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/InitialPeers/README.md new file mode 100644 index 000000000..6f842120c --- /dev/null +++ b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/InitialPeers/README.md @@ -0,0 +1,7 @@ +# DDS Test Initial Peers + +Test communication between two DDS Participants hosted in the same device, but which are at different DDS domains. +This is accomplished by connecting two Initial Peers Participants belonging to different DDS Router instances. +These router instances communicate with the DDS Participants through Simple Participants deployed at those domains. +Note that, although data transmission is accomplished by connecting two Initial Peers Participants, +the resulting communication is still local (i.e. WAN communication is not tested here). diff --git a/ddsrouter_core/test/blackbox/ddsrouter_core/dds/InitialPeers/TEST_XFAIL.list b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/InitialPeers/TEST_XFAIL.list new file mode 100644 index 000000000..3c0c9bd29 --- /dev/null +++ b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/InitialPeers/TEST_XFAIL.list @@ -0,0 +1 @@ +DDSTestInitialPeers.end_to_end_InitialPeers_communication_TLSv4 diff --git a/ddsrouter_core/test/blackbox/ddsrouter_core/dds/WAN/DDSTestWAN.cpp b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/WAN/DDSTestWAN.cpp index e9717709c..dc35cafdc 100644 --- a/ddsrouter_core/test/blackbox/ddsrouter_core/dds/WAN/DDSTestWAN.cpp +++ b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/WAN/DDSTestWAN.cpp @@ -119,8 +119,9 @@ std::shared_ptr wan_participant_configu if (tls) { return std::make_shared( - types::ParticipantId("WanParticipant_" + std::to_string((this_server_id_is_1 ? 1 : 0))), - types::ParticipantKind::wan, + types::ParticipantId("WanDsParticipant_" + std::to_string((this_server_id_is_1 ? 1 : 0))), + types::ParticipantKind::wan_discovery_server, + false, types::DomainId(0u), types::GuidPrefix((this_server_id_is_1 ? 1u : 0u)), listening_addresses, @@ -131,8 +132,9 @@ std::shared_ptr wan_participant_configu else { return std::make_shared( - types::ParticipantId("WanParticipant_" + std::to_string((this_server_id_is_1 ? 1 : 0))), - types::ParticipantKind::wan, + types::ParticipantId("WanDsParticipant_" + std::to_string((this_server_id_is_1 ? 1 : 0))), + types::ParticipantKind::wan_discovery_server, + false, types::DomainId(0u), types::GuidPrefix((this_server_id_is_1 ? 1u : 0u)), listening_addresses, @@ -174,6 +176,7 @@ configuration::DDSRouterConfiguration router_configuration( std::make_shared( types::ParticipantId("simple_participant"), types::ParticipantKind(types::ParticipantKind::simple_rtps), + false, types::DomainId(domain) ), } diff --git a/ddsrouter_core/test/blackbox/ddsrouter_core/dds/local/DDSTestLocal.cpp b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/local/DDSTestLocal.cpp index 790ae1486..8901ceddb 100644 --- a/ddsrouter_core/test/blackbox/ddsrouter_core/dds/local/DDSTestLocal.cpp +++ b/ddsrouter_core/test/blackbox/ddsrouter_core/dds/local/DDSTestLocal.cpp @@ -69,11 +69,13 @@ configuration::DDSRouterConfiguration dds_test_simple_configuration( std::make_shared( types::ParticipantId("participant_0"), types::ParticipantKind(types::ParticipantKind::simple_rtps), + false, types::DomainId(0u) ), std::make_shared( types::ParticipantId("participant_1"), types::ParticipantKind(types::ParticipantKind::simple_rtps), + false, types::DomainId(1u) ) } diff --git a/ddsrouter_core/test/blackbox/ddsrouter_core/trivial/TrivialTest.cpp b/ddsrouter_core/test/blackbox/ddsrouter_core/trivial/TrivialTest.cpp index dea53d3dd..3f59a2d37 100644 --- a/ddsrouter_core/test/blackbox/ddsrouter_core/trivial/TrivialTest.cpp +++ b/ddsrouter_core/test/blackbox/ddsrouter_core/trivial/TrivialTest.cpp @@ -45,22 +45,22 @@ std::vector random_payload( configuration::DDSRouterConfiguration void_configuration() { - return configuration::DDSRouterConfiguration( - std::set>(), - std::set>(), - std::set>(), - std::set>( + configuration::DDSRouterConfiguration configuration; + configuration.participants_configurations = { std::make_shared( ParticipantId("ParticipantVoid1"), - ParticipantKind::blank + ParticipantKind::blank, + false ), std::make_shared( ParticipantId("ParticipantVoid2"), - ParticipantKind::blank + ParticipantKind::blank, + false ) - }), - 1); + }; + + return configuration; } /** @@ -74,22 +74,28 @@ configuration::DDSRouterConfiguration simple_configuration( const std::string& topic_name = "topic_dummy", const std::string& topic_type = "type_dummy") { - return configuration::DDSRouterConfiguration( - std::set>(), - std::set>(), + configuration::DDSRouterConfiguration configuration; + + configuration.builtin_topics = + { std::set>({std::make_shared(topic_name, topic_type)}), - std::set>( + }; + + configuration.participants_configurations = { std::make_shared( ParticipantId(participant_1_name), - ParticipantKind::dummy + ParticipantKind::dummy, + false ), std::make_shared( ParticipantId(participant_2_name), - ParticipantKind::dummy + ParticipantKind::dummy, + false ) - }), - 1); + }; + + return configuration; } /** diff --git a/ddsrouter_core/test/blackbox/implementations/CMakeLists.txt b/ddsrouter_core/test/blackbox/implementations/CMakeLists.txt index 84bf82ab6..fc76ab846 100644 --- a/ddsrouter_core/test/blackbox/implementations/CMakeLists.txt +++ b/ddsrouter_core/test/blackbox/implementations/CMakeLists.txt @@ -27,7 +27,6 @@ set(TEST_LIST pair_implementation pair_implementation_with_topic all_implementations - solo_participant_implementation duplicated_ids ) diff --git a/ddsrouter_core/test/blackbox/implementations/ImplementationsTest.cpp b/ddsrouter_core/test/blackbox/implementations/ImplementationsTest.cpp index f9fdbd097..d9cb8b3b4 100644 --- a/ddsrouter_core/test/blackbox/implementations/ImplementationsTest.cpp +++ b/ddsrouter_core/test/blackbox/implementations/ImplementationsTest.cpp @@ -49,32 +49,6 @@ using namespace eprosima::ddsrouter; using namespace eprosima::ddsrouter::core; using namespace eprosima::ddsrouter::core::types; -/** - * Test that tries to create a DDSRouter with only one Participant. - * - * It expects to receive an exception - */ -TEST(ImplementationsTest, solo_participant_implementation) -{ - // For each Participant Kind - for (ParticipantKind kind : ALL_VALID_PARTICIPANT_KINDS) - { - std::set> participant_configurations; - participant_configurations.insert(test::random_participant_configuration(kind)); - - // Generate configuration - configuration::DDSRouterConfiguration configuration( - std::set>(), - std::set>(), - std::set>(), - participant_configurations, - test::DEFAULT_THREAD_POOL_SIZE); - - // Create DDSRouter entity - ASSERT_THROW(DDSRouter router(configuration), utils::ConfigurationException) << kind; - } -} - /** * Test that creates a DDSRouter with a Pair of Participants of same kind. * It creates a DDSRouter with two Participants of same kind, starts it, then stops it and finally destroys it. diff --git a/ddsrouter_core/test/unittest/_configuration/CMakeLists.txt b/ddsrouter_core/test/unittest/_configuration/CMakeLists.txt new file mode 100644 index 000000000..4cd8f8aa6 --- /dev/null +++ b/ddsrouter_core/test/unittest/_configuration/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################ +# DDSRouter Configuration Test # +################################ + +set(TEST_NAME ValidConfigurationTest) + +set(TEST_SOURCES + ValidConfigurationTest.cpp + ) +all_library_sources("${TEST_SOURCES}") + +set(TEST_LIST + ) + +set(TEST_EXTRA_LIBRARIES + ddsrouter_utils + ) + +add_unittest_executable( + "${TEST_NAME}" + "${TEST_SOURCES}" + "${TEST_LIST}" + "${TEST_EXTRA_LIBRARIES}") diff --git a/ddsrouter_core/test/unittest/_configuration/TODO.md b/ddsrouter_core/test/unittest/_configuration/TODO.md new file mode 100644 index 000000000..1b0c59243 --- /dev/null +++ b/ddsrouter_core/test/unittest/_configuration/TODO.md @@ -0,0 +1,5 @@ + +# CONFIGURATION TESTS + +These tests are developed using an old API. +They should be redo in the current API when possible. diff --git a/ddsrouter_core/test/unittest/configuration/ConfigurationTest.cpp b/ddsrouter_core/test/unittest/_configuration/_ConfigurationTest.cpp similarity index 100% rename from ddsrouter_core/test/unittest/configuration/ConfigurationTest.cpp rename to ddsrouter_core/test/unittest/_configuration/_ConfigurationTest.cpp diff --git a/ddsrouter_core/test/unittest/configuration/CMakeLists.txt b/ddsrouter_core/test/unittest/configuration/CMakeLists.txt deleted file mode 100644 index f6892530e..000000000 --- a/ddsrouter_core/test/unittest/configuration/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima). -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -################################ -# DDSRouter Configuration Test # -################################ - -set(TEST_NAME ConfigurationTest) - -set(TEST_SOURCES - ConfigurationTest.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/configuration/DDSRouterConfiguration.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/configuration/ParticipantConfiguration.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/types/participant/ParticipantId.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/types/participant/ParticipantKind.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/types/topic/FilterTopic.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/types/topic/RealTopic.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/types/topic/Topic.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/types/topic/WildcardTopic.cpp - ) - -set(TEST_LIST - constructor - participants_configurations - real_topics - allowlist_wildcard - blocklist_wildcard - allowlist_and_blocklist - constructor_fail - participants_configurations_fail - real_topics_fail - allowlist_wildcard_fail - blocklist_wildcard_fail - ) - -set(TEST_EXTRA_LIBRARIES - ddsrouter_utils - ) - -add_unittest_executable( - "${TEST_NAME}" - "${TEST_SOURCES}" - "${TEST_LIST}" - "${TEST_EXTRA_LIBRARIES}") diff --git a/ddsrouter_core/test/unittest/core/participant_factory/ParticipantFactoryTest.cpp b/ddsrouter_core/test/unittest/core/participant_factory/ParticipantFactoryTest.cpp index a05fe0cb7..56b19d9c8 100644 --- a/ddsrouter_core/test/unittest/core/participant_factory/ParticipantFactoryTest.cpp +++ b/ddsrouter_core/test/unittest/core/participant_factory/ParticipantFactoryTest.cpp @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include #include diff --git a/ddsrouter_core/test/unittest/efficiency/CMakeLists.txt b/ddsrouter_core/test/unittest/efficiency/CMakeLists.txt index 57bb74a3c..419489142 100644 --- a/ddsrouter_core/test/unittest/efficiency/CMakeLists.txt +++ b/ddsrouter_core/test/unittest/efficiency/CMakeLists.txt @@ -20,8 +20,8 @@ set(TEST_NAME PayloadPoolTest) set(TEST_SOURCES PayloadPoolTest.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/PayloadPool.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/PayloadPool.hpp + ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/payload/PayloadPool.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/payload/PayloadPool.hpp ${PROJECT_SOURCE_DIR}/src/cpp/types/dds/Data.cpp ) @@ -56,10 +56,10 @@ set(TEST_NAME MapPayloadPoolTest) set(TEST_SOURCES MapPayloadPoolTest.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/PayloadPool.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/PayloadPool.hpp - ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/MapPayloadPool.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/MapPayloadPool.hpp + ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/payload/PayloadPool.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/payload/PayloadPool.hpp + ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/payload/MapPayloadPool.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/payload/MapPayloadPool.hpp ${PROJECT_SOURCE_DIR}/src/cpp/types/dds/Data.cpp ) @@ -93,10 +93,10 @@ set(TEST_NAME FastPayloadPoolTest) set(TEST_SOURCES FastPayloadPoolTest.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/PayloadPool.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/PayloadPool.hpp - ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/FastPayloadPool.cpp - ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/FastPayloadPool.hpp + ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/payload/PayloadPool.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/payload/PayloadPool.hpp + ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/payload/FastPayloadPool.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/efficiency/payload/FastPayloadPool.hpp ${PROJECT_SOURCE_DIR}/src/cpp/types/dds/Data.cpp ) diff --git a/ddsrouter_core/test/unittest/efficiency/FastPayloadPoolTest.cpp b/ddsrouter_core/test/unittest/efficiency/FastPayloadPoolTest.cpp index 0dacf095a..cc05c9b84 100644 --- a/ddsrouter_core/test/unittest/efficiency/FastPayloadPoolTest.cpp +++ b/ddsrouter_core/test/unittest/efficiency/FastPayloadPoolTest.cpp @@ -17,8 +17,8 @@ #include -#include -#include +#include +#include #include using namespace eprosima::ddsrouter; diff --git a/ddsrouter_core/test/unittest/efficiency/MapPayloadPoolTest.cpp b/ddsrouter_core/test/unittest/efficiency/MapPayloadPoolTest.cpp index 9a3af84c9..1b875f4b1 100644 --- a/ddsrouter_core/test/unittest/efficiency/MapPayloadPoolTest.cpp +++ b/ddsrouter_core/test/unittest/efficiency/MapPayloadPoolTest.cpp @@ -17,8 +17,8 @@ #include -#include -#include +#include +#include #include using namespace eprosima::ddsrouter; diff --git a/ddsrouter_core/test/unittest/efficiency/PayloadPoolTest.cpp b/ddsrouter_core/test/unittest/efficiency/PayloadPoolTest.cpp index 86ece336b..daf28bc7d 100644 --- a/ddsrouter_core/test/unittest/efficiency/PayloadPoolTest.cpp +++ b/ddsrouter_core/test/unittest/efficiency/PayloadPoolTest.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include diff --git a/ddsrouter_core/test/unittest/types/participant/ParticipantKindTest.cpp b/ddsrouter_core/test/unittest/types/participant/ParticipantKindTest.cpp index 5510b75f5..145a8ac0b 100644 --- a/ddsrouter_core/test/unittest/types/participant/ParticipantKindTest.cpp +++ b/ddsrouter_core/test/unittest/types/participant/ParticipantKindTest.cpp @@ -52,11 +52,15 @@ TEST(ParticipantKindTest, string_conversions) "dummy")); ASSERT_EQ(std::string( PARTICIPANT_KIND_STRINGS[static_cast(ParticipantKind::simple_rtps)]), - std::string("simple_rtps")); + std::string("simple-rtps")); ASSERT_EQ(std::string(PARTICIPANT_KIND_STRINGS[static_cast(ParticipantKind:: - local_discovery_server)]), std::string("local_discovery_server")); - ASSERT_EQ(std::string(PARTICIPANT_KIND_STRINGS[static_cast(ParticipantKind::wan)]), - std::string("wan")); + local_discovery_server)]), std::string("local-discovery-server")); + ASSERT_EQ(std::string( + PARTICIPANT_KIND_STRINGS[static_cast(ParticipantKind::wan_initial_peers)]), + std::string("wan-initial-peers")); + ASSERT_EQ(std::string( + PARTICIPANT_KIND_STRINGS[static_cast(ParticipantKind::wan_discovery_server)]), + std::string("wan-ds")); // Test all possible aliases for each participant kind @@ -85,9 +89,13 @@ TEST(ParticipantKindTest, string_conversions) ASSERT_EQ(participant_kind_from_name("local-ds"), ParticipantKind::local_discovery_server); ASSERT_EQ(participant_kind_from_name("local-discovery-server"), ParticipantKind::local_discovery_server); - // Strings mapping to ParticipantKind::wan - ASSERT_EQ(participant_kind_from_name("wan"), ParticipantKind::wan); - ASSERT_EQ(participant_kind_from_name("router"), ParticipantKind::wan); + // Strings mapping to ParticipantKind::wan_initial_peers + ASSERT_EQ(participant_kind_from_name("wan"), ParticipantKind::wan_initial_peers); + ASSERT_EQ(participant_kind_from_name("router"), ParticipantKind::wan_initial_peers); + + // Strings mapping to ParticipantKind::wan_discovery_server + ASSERT_EQ(participant_kind_from_name("wan-ds"), ParticipantKind::wan_discovery_server); + ASSERT_EQ(participant_kind_from_name("wan-discovery-server"), ParticipantKind::wan_discovery_server); } int main( diff --git a/ddsrouter_utils/include/ddsrouter_utils/pool/IPool.hpp b/ddsrouter_utils/include/ddsrouter_utils/pool/IPool.hpp new file mode 100644 index 000000000..034d183d0 --- /dev/null +++ b/ddsrouter_utils/include/ddsrouter_utils/pool/IPool.hpp @@ -0,0 +1,134 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file IPool.hpp + */ + +#ifndef _DDSROUTERUTILS_POOL_IPOOL_HPP_ +#define _DDSROUTERUTILS_POOL_IPOOL_HPP_ + +namespace eprosima { +namespace ddsrouter { +namespace utils { + +//! Data structure to store values for a Memory Pool Configuration. +struct PoolConfiguration +{ + //! Default constructor with default values. + PoolConfiguration() = default; + + //! Constructor with parameters. + PoolConfiguration( + unsigned int initial_size, + unsigned int maximum_size, + unsigned int batch_size) noexcept; + + //! Initial number of elements when preallocating data. + unsigned int initial_size = 0; + //! Maximum of allocated elements. 0 = No limit. + unsigned int maximum_size = 0; + //! Number of elements to allocate when no free elements are available (without exceeding maximum). + unsigned int batch_size = 1; +}; + +/** + * @brief Memory Pool interface. + * + * A Pool of elements manage the memory allocation of the elements. + * Whenever a new element wants to be used, \c loan is called. + * Every element must be returned to the pool when it is not used anymore by \c return_loan . + * + * This object is meant to efficiently manage allocations and memory, so loan and return_loan + * does not force to allocate or free memory. + * Depending on the implementation, this memory could be allocated/freed or reused. + * + * @tparam T Type of elements that the Pool will manage. + */ +template +class IPool +{ +public: + + /** + * @brief Get a new element from the pool. + * + * @param [out] element reference to the ptr that will be filled with the new element. + * @return true if loan was successful. + * @return false otherwise. + */ + virtual bool loan( + T*& element) = 0; + + /** + * @brief Return an element to the pool. + * + * @param [in] element reference to the element belonging to this Pool that is being returned. + * @return true if release was successful. + * @return false otherwise. + * + * @warning After calling this method, \c element is not valid anymore. + * + * @pre \c element must have been reserved by this same Pool. + */ + virtual bool return_loan( + T* element) = 0; + +protected: + + /** + * @brief Construct a new non-initialized element. + * + * By default, it calls \c new with default constructor. + */ + virtual T* new_element_(); + + /** + * @brief Delete an element initialized with \c new_element_ . + * + * By default, it calls \c delete on the element. + */ + virtual void delete_element_( + T* element); + + /** + * @brief Reset internal element information to reuse it. + * + * By default, it does nothing. + */ + virtual void reset_element_( + T* element); +}; + +/** + * @brief Create a pool object depending on the configuration given. + * + * It creates the IPool specialization that better implements the given configuration. + * + * @tparam T Type of elements that the Pool will manage. + * @param configuration Pool Configuration + * @return IPool* new Pool object. + */ +template +static IPool* create_pool( + PoolConfiguration configuration); + +} /* namespace utils */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ + +// Include implementation template file +#include + +#endif /* _DDSROUTERUTILS_POOL_IPOOL_HPP_ */ diff --git a/ddsrouter_utils/include/ddsrouter_utils/pool/UnboundedPool.hpp b/ddsrouter_utils/include/ddsrouter_utils/pool/UnboundedPool.hpp new file mode 100644 index 000000000..6f3611fed --- /dev/null +++ b/ddsrouter_utils/include/ddsrouter_utils/pool/UnboundedPool.hpp @@ -0,0 +1,131 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file UnboundedPool.hpp + */ + +#ifndef _DDSROUTERUTILS_POOL_UNBOUNDEDPOOL_HPP_ +#define _DDSROUTERUTILS_POOL_UNBOUNDEDPOOL_HPP_ + +#include + +#include + +namespace eprosima { +namespace ddsrouter { +namespace utils { + +/** + * @brief This class implements a generic not-thread-safe reusable Pool without size limit. + * + * ATTRIBUTES: + * - Reuse freed elements without allocation. + * - Not thread safe + * - No pool size limit + * + * This implementation uses an internal vector where new elements are stored. + * Whenever it runs out of free (not loaned) elements, it allocates more following configuration batch. + * Whenever an element is returned, it turns back to the vector to be reused. + * + * @warning This class is not thread safe. + * + * @tparam T Type of the elements in the pool. + */ +template +class UnboundedPool : IPool +{ +public: + + /** + * @brief Create a new UnboundedPool object by a Pool Configuration given. + * + * It initializes the internal vector with the given initial size, using \c new_element_ . + * + * @note Whenever this class is inherited, the constructor must call \c initialize_vector_ , + * as this class cannot because \c new_element_ must be overriden by the child class. + * + * @param configuration Pool Configuration + * + * @throw InitializationException if the pool configuration is not correct. + */ + UnboundedPool( + PoolConfiguration configuration); + + /** + * @brief Destroy the Limitless Pool object and all its reserved elements. + */ + ~UnboundedPool(); + + /** + * @brief Override IPool::loan + * + * If there are elements not in use in the vector, it returns one of them in \c element . + * Otherwise, it allocates more elements and takes the next free one. + */ + virtual bool loan( + T*& element) override; + + /** + * @brief Override IPool::return_loan + * + * Return the element to the vector. + * + * @throw InconsistencyException if there have been more released than reserved calls. + */ + virtual bool return_loan( + T* element) override; + +protected: + + /** + * @brief Initialize the internal vector with the given initial size in configuration. + * + * This method must be called in every final child class constructor. + */ + virtual void initialize_vector_(); + + /** + * @brief Augment the internal vector with \c batch new elements using \c new_element_ function for each of them. + */ + void augment_free_values_(); + + /** + * @brief vector where elements are stored. + * + * Each element of the vector has been initialized with \c new_element_ + * or returned to the pool after calling \c reset_element_ . + * The elements are added and consumed at the back. + */ + std::vector elements_; + + /** + * @brief Total number of elements reserved by the pool. + * + * This is only a debugging variable that may be deleted for performance reasons. + */ + unsigned int reserved_; + + //! Pool configuration. + const PoolConfiguration configuration_; +}; + +} /* namespace utils */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ + +// Include implementation template file +#include + +#endif /* _DDSROUTERUTILS_POOL_UNBOUNDEDPOOL_HPP_ */ diff --git a/ddsrouter_utils/include/ddsrouter_utils/pool/impl/IPool.ipp b/ddsrouter_utils/include/ddsrouter_utils/pool/impl/IPool.ipp new file mode 100644 index 000000000..21066ca30 --- /dev/null +++ b/ddsrouter_utils/include/ddsrouter_utils/pool/impl/IPool.ipp @@ -0,0 +1,65 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file IPool.ipp + */ + +#ifndef __DDSROUTERUTILS_POOL_IPOOL_IMPL_IPP_ +#define __DDSROUTERUTILS_POOL_IPOOL_IMPL_IPP_ + +#include + +namespace eprosima { +namespace ddsrouter { +namespace utils { + +template +class UnboundedPool; + +template +static IPool* create_pool( + PoolConfiguration configuration) +{ + // Create pool depending on the configuration + // TODO: change it depending on the configuration + // So far only one specialization exists + return new UnboundedPool(configuration); +} + +template +T* IPool::new_element_() +{ + return new T(); +} + +template +void IPool::delete_element_( + T* element) +{ + delete element; +} + +template +void IPool::reset_element_( + T* element) +{ + // Do nothing +} + +} /* namespace utils */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ + +#endif /* __DDSROUTERUTILS_POOL_IPOOL_IMPL_IPP_ */ diff --git a/ddsrouter_utils/include/ddsrouter_utils/pool/impl/UnboundedPool.ipp b/ddsrouter_utils/include/ddsrouter_utils/pool/impl/UnboundedPool.ipp new file mode 100644 index 000000000..d36167bc5 --- /dev/null +++ b/ddsrouter_utils/include/ddsrouter_utils/pool/impl/UnboundedPool.ipp @@ -0,0 +1,127 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @file UnboundedPool.ipp + */ + +#ifndef __DDSROUTERUTILS_POOL_UnboundedPool_IMPL_IPP_ +#define __DDSROUTERUTILS_POOL_UnboundedPool_IMPL_IPP_ + +#include +#include +#include +#include + +namespace eprosima { +namespace ddsrouter { +namespace utils { + +template +UnboundedPool::UnboundedPool( + PoolConfiguration configuration) + : reserved_(0) + , configuration_(configuration) +{ + // Call initialize_vector_ in every child constructor + + // Check Configuration consistency + // Check batch size + if (configuration.batch_size < 1) + { + throw utils::InitializationException("Batch size must be at least 1."); + } +} + +template +UnboundedPool::~UnboundedPool() +{ + // Check that every element has been released + if (elements_.size() != reserved_) + { + logDevError(LIMITLESS_POOL, "More Elements reserved than released."); + } + + // Delete the values + for (unsigned int i = 0; i < elements_.size(); ++i) + { + auto& element = elements_.back(); + elements_.pop_back(); + this->delete_element_(element); + } +} + +template +bool UnboundedPool::loan( + T*& element) +{ + if (elements_.size() == 0) + { + // It requires to allocate new values + augment_free_values_(); + } + + // There are already free values available + // It uses an existing already allocated value + element = elements_.back(); + elements_.pop_back(); + + return true; +} + +template +bool UnboundedPool::return_loan( + T* element) +{ + // This only could happen if more elements are released than reserved. + // TODO: this should be a performance test, not in production. It does not affect behaviour. + if (reserved_ == elements_.size()) + { + throw InconsistencyException("return_loan: More elements are released than reserved."); + } + + // Return it to the vector + this->reset_element_(element); + elements_.push_back(element); + + return true; +} + +template +void UnboundedPool::augment_free_values_() +{ + for (unsigned int i = 0; i < this->configuration_.batch_size; ++i) + { + this->elements_.push_back(this->new_element_()); + } + reserved_ += this->configuration_.batch_size; + logDebug(LIMITLESS_POOL, "Pool " << TYPE_NAME(T) << " augmented to " << reserved_ << " elements."); +} + +template +void UnboundedPool::initialize_vector_() +{ + for (unsigned int i = 0; i < this->configuration_.initial_size; ++i) + { + elements_.push_back(this->new_element_()); + } + reserved_ = this->configuration_.initial_size; + logDebug(LIMITLESS_POOL, "Pool " << TYPE_NAME(T) << " initialized with " << reserved_ << " elements."); +} + +} /* namespace utils */ +} /* namespace ddsrouter */ +} /* namespace eprosima */ + +#endif /* __DDSROUTERUTILS_POOL_UnboundedPool_IMPL_IPP_ */ diff --git a/ddsrouter_yaml/include/ddsrouter_yaml/YamlReader.hpp b/ddsrouter_yaml/include/ddsrouter_yaml/YamlReader.hpp index 537d576e6..36225319d 100644 --- a/ddsrouter_yaml/include/ddsrouter_yaml/YamlReader.hpp +++ b/ddsrouter_yaml/include/ddsrouter_yaml/YamlReader.hpp @@ -58,7 +58,7 @@ enum YamlReaderVersion V_1_0, /** - * @brief Latest version. + * @brief Version 2.0 * * @version 0.3.0 * @@ -69,6 +69,15 @@ enum YamlReaderVersion */ V_2_0, + /** + * @brief Latest version. + * + * @version 0.5.0 + * + * - Change wan to initial peers participant + */ + V_3_0, + /** * @brief Main version. * diff --git a/ddsrouter_yaml/include/ddsrouter_yaml/yaml_configuration_tags.hpp b/ddsrouter_yaml/include/ddsrouter_yaml/yaml_configuration_tags.hpp index cee651334..3761688b9 100644 --- a/ddsrouter_yaml/include/ddsrouter_yaml/yaml_configuration_tags.hpp +++ b/ddsrouter_yaml/include/ddsrouter_yaml/yaml_configuration_tags.hpp @@ -39,6 +39,7 @@ bool is_tag( constexpr const char* VERSION_TAG("version"); //! Version to parse the yaml with constexpr const char* VERSION_TAG_V_1_0("v1.0"); //! Version v1.0 constexpr const char* VERSION_TAG_V_2_0("v2.0"); //! Version v2.0 +constexpr const char* VERSION_TAG_V_3_0("v3.0"); //! Version v3.0 // Topics related tags constexpr const char* ALLOWLIST_TAG("allowlist"); //! List of allowed topics @@ -52,6 +53,7 @@ constexpr const char* TOPIC_RELIABLE_TAG("reliable"); //! The DataReaders of tha constexpr const char* PARTICIPANT_KIND_TAG("kind"); //! Participant Kind constexpr const char* PARTICIPANT_NAME_TAG("name"); //! Participant Name constexpr const char* COLLECTION_PARTICIPANTS_TAG("participants"); //! TODO: add comment +constexpr const char* IS_REPEATER_TAG("repeater"); //! Is participant a repeater // RTPS related tags // Simple RTPS related tags diff --git a/ddsrouter_yaml/src/cpp/YamlReader.cpp b/ddsrouter_yaml/src/cpp/YamlReader.cpp index 3ea7534fd..82ee920fd 100644 --- a/ddsrouter_yaml/src/cpp/YamlReader.cpp +++ b/ddsrouter_yaml/src/cpp/YamlReader.cpp @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -88,6 +89,7 @@ YamlReaderVersion YamlReader::get( { {VERSION_TAG_V_1_0, YamlReaderVersion::V_1_0}, {VERSION_TAG_V_2_0, YamlReaderVersion::V_2_0}, + {VERSION_TAG_V_3_0, YamlReaderVersion::V_3_0}, }); } @@ -111,6 +113,15 @@ unsigned int YamlReader::get( return get_scalar(yml); } +template <> +bool YamlReader::get( + const Yaml& yml, + const YamlReaderVersion version /* version */) +{ + bool value = get_scalar(yml); + return get_scalar(yml); +} + /************************ * ENTITIES * ************************/ @@ -171,10 +182,18 @@ ParticipantId YamlReader::get( template <> ParticipantKind YamlReader::get( const Yaml& yml, - const YamlReaderVersion /* version */) + const YamlReaderVersion version) { // Participant kind required - return participant_kind_from_name(get_scalar(yml)); + ParticipantKind kind = participant_kind_from_name(get_scalar(yml)); + + // In version lower than 3.0 wan means wan_discovery_server + if (version <= V_2_0 && kind == ParticipantKind::wan_initial_peers) + { + kind = ParticipantKind::wan_discovery_server; + } + + return kind; } template <> @@ -653,6 +672,55 @@ configuration::DiscoveryServerParticipantConfiguration YamlReader::get( return object; } +////////////////////////////////// +// InitialPeersParticipantConfiguration +template <> +void YamlReader::fill( + configuration::InitialPeersParticipantConfiguration& object, + const Yaml& yml, + const YamlReaderVersion version) +{ + // Parent class fill + fill(object, yml, version); + + // Optional listening addresses + if (YamlReader::is_tag_present(yml, LISTENING_ADDRESSES_TAG)) + { + object.listening_addresses = YamlReader::get_set(yml, LISTENING_ADDRESSES_TAG, version); + } + + // Optional connection addresses + if (YamlReader::is_tag_present(yml, CONNECTION_ADDRESSES_TAG)) + { + object.connection_addresses = YamlReader::get_set( + yml, + CONNECTION_ADDRESSES_TAG, + version); + } + + // Optional TLS + if (YamlReader::is_tag_present(yml, TLS_TAG)) + { + object.tls_configuration = YamlReader::get(yml, TLS_TAG, version); + } + + // Optional Repeater + if (YamlReader::is_tag_present(yml, IS_REPEATER_TAG)) + { + object.is_repeater = YamlReader::get(yml, IS_REPEATER_TAG, version); + } +} + +template <> +configuration::InitialPeersParticipantConfiguration YamlReader::get( + const Yaml& yml, + const YamlReaderVersion version) +{ + configuration::InitialPeersParticipantConfiguration object; + fill(object, yml, version); + return object; +} + /*************************** * DDS ROUTER CONFIGURATION * ****************************/ @@ -681,10 +749,14 @@ YamlReader::get>( YamlReader::get(yml, version)); case types::ParticipantKind::local_discovery_server: - case types::ParticipantKind::wan: + case types::ParticipantKind::wan_discovery_server: return std::make_shared( YamlReader::get(yml, version)); + case types::ParticipantKind::wan_initial_peers: + return std::make_shared( + YamlReader::get(yml, version)); + default: throw utils::ConfigurationException( utils::Formatter() << "Unkown or non valid Participant kind:" << kind << "."); @@ -767,7 +839,7 @@ void _fill_ddsrouter_configuration_v1( participant_yml[PARTICIPANT_KIND_TAG] = participant_yml[PARTICIPANT_KIND_TAG_V1]; // Add new Participant with its configuration - object.participants_configurations_.insert( + object.participants_configurations.insert( YamlReader::get>( participant_yml, version)); @@ -819,7 +891,7 @@ void _fill_ddsrouter_configuration_latest( for (auto conf : participants_configurations_yml) { - object.participants_configurations_.insert( + object.participants_configurations.insert( YamlReader::get>(conf, version)); } @@ -865,8 +937,12 @@ std::ostream& operator <<( os << VERSION_TAG_V_2_0; break; + case V_3_0: + os << VERSION_TAG_V_3_0; + break; + case LATEST: - os << VERSION_TAG_V_2_0; + os << VERSION_TAG_V_3_0; break; default: diff --git a/ddsrouter_yaml/src/cpp/yaml_configuration_tags.cpp b/ddsrouter_yaml/src/cpp/yaml_configuration_tags.cpp index 4b835a9dd..a2575ef13 100644 --- a/ddsrouter_yaml/src/cpp/yaml_configuration_tags.cpp +++ b/ddsrouter_yaml/src/cpp/yaml_configuration_tags.cpp @@ -64,6 +64,7 @@ std::set ddsrouter_tags() noexcept VERSION_TAG, VERSION_TAG_V_1_0, VERSION_TAG_V_2_0, + VERSION_TAG_V_3_0, PARTICIPANT_KIND_TAG_V1, }; } diff --git a/ddsrouter_yaml/test/TestUtils/test_utils.cpp b/ddsrouter_yaml/test/TestUtils/test_utils.cpp index a92506694..927ae2989 100644 --- a/ddsrouter_yaml/test/TestUtils/test_utils.cpp +++ b/ddsrouter_yaml/test/TestUtils/test_utils.cpp @@ -220,10 +220,11 @@ std::shared_ptr random_participan return std::make_shared( id, kind, + false, random_domain(seed)); case ParticipantKind::local_discovery_server: - case ParticipantKind::wan: + case ParticipantKind::wan_discovery_server: { // TODO get random values @@ -235,6 +236,7 @@ std::shared_ptr random_participan return std::make_shared( id, kind, + false, random_domain(seed), random_guid_prefix(seed), std::set
(), @@ -242,9 +244,22 @@ std::shared_ptr random_participan security::TlsConfiguration()); } + case ParticipantKind::wan_initial_peers: + + { + return std::make_shared( + id, + kind, + false, + random_domain(seed), + std::set
(), + std::set
({Address()}), + security::TlsConfiguration()); + } + // Add cases where Participants need specific arguments default: - return std::make_shared(id, kind); + return std::make_shared(id, kind, false); } } diff --git a/ddsrouter_yaml/test/TestUtils/test_utils.hpp b/ddsrouter_yaml/test/TestUtils/test_utils.hpp index cf6d70601..cd8dd5038 100644 --- a/ddsrouter_yaml/test/TestUtils/test_utils.hpp +++ b/ddsrouter_yaml/test/TestUtils/test_utils.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/ddsrouter_yaml/test/unittest/YamlConfigurationTestUtils.hpp b/ddsrouter_yaml/test/unittest/YamlConfigurationTestUtils.hpp index 7ecffc380..4f5eeeaa5 100644 --- a/ddsrouter_yaml/test/unittest/YamlConfigurationTestUtils.hpp +++ b/ddsrouter_yaml/test/unittest/YamlConfigurationTestUtils.hpp @@ -164,6 +164,16 @@ void domain_to_yaml( DOMAIN_ID_TAG); } +void repeater_to_yaml( + Yaml& yml, + const bool& repeater) +{ + test::add_field_to_yaml( + yml, + test::YamlField(repeater), + IS_REPEATER_TAG); +} + } /* namespace test */ } /* namespace yaml */ } /* namespace ddsrouter */ diff --git a/ddsrouter_yaml/test/unittest/entities/ddsrouter/YamlGetConfigurationDDSRouterTest.cpp b/ddsrouter_yaml/test/unittest/entities/ddsrouter/YamlGetConfigurationDDSRouterTest.cpp index 7825c868e..38fc4710a 100644 --- a/ddsrouter_yaml/test/unittest/entities/ddsrouter/YamlGetConfigurationDDSRouterTest.cpp +++ b/ddsrouter_yaml/test/unittest/entities/ddsrouter/YamlGetConfigurationDDSRouterTest.cpp @@ -59,7 +59,7 @@ TEST(YamlGetConfigurationDDSRouterTest, get_ddsrouter_configuration_trivial) // Check Participant configurations std::set> - participant_configurations = configuration_result.participants_configurations_; + participant_configurations = configuration_result.participants_configurations; ASSERT_EQ(participant_configurations.size(), 2); @@ -118,7 +118,7 @@ TEST(YamlGetConfigurationDDSRouterTest, get_ddsrouter_configuration_ros_case) // Check Participant configurations std::set> - participant_configurations = configuration_result.participants_configurations_; + participant_configurations = configuration_result.participants_configurations; ASSERT_EQ(participant_configurations.size(), 3); @@ -160,7 +160,7 @@ TEST(YamlGetConfigurationDDSRouterTest, get_ddsrouter_configuration_trivial_v1) // Check Participant configurations std::set> - participant_configurations = configuration_result.participants_configurations_; + participant_configurations = configuration_result.participants_configurations; ASSERT_EQ(participant_configurations.size(), 2); @@ -217,7 +217,7 @@ TEST(YamlGetConfigurationDDSRouterTest, get_ddsrouter_configuration_builtin_v1) // Check Participant configurations std::set> - participant_configurations = configuration_result.participants_configurations_; + participant_configurations = configuration_result.participants_configurations; ASSERT_EQ(participant_configurations.size(), 2); @@ -266,7 +266,7 @@ TEST(YamlGetConfigurationDDSRouterTest, get_ddsrouter_configuration_discovery_se // Check Participant configurations std::set> - participant_configurations = configuration_result.participants_configurations_; + participant_configurations = configuration_result.participants_configurations; ASSERT_EQ(participant_configurations.size(), 2); diff --git a/ddsrouter_yaml/test/unittest/participants/CMakeLists.txt b/ddsrouter_yaml/test/unittest/participants/CMakeLists.txt index a6bf2e8da..2835073e4 100644 --- a/ddsrouter_yaml/test/unittest/participants/CMakeLists.txt +++ b/ddsrouter_yaml/test/unittest/participants/CMakeLists.txt @@ -23,7 +23,6 @@ set(TEST_SOURCES ${PROJECT_SOURCE_DIR}/src/cpp/YamlReader.cpp ${PROJECT_SOURCE_DIR}/test/TestUtils/test_utils.cpp YamlGetCommonParticipantConfigurationTest.cpp - YamlGetCommonParticipantConfigurationTest.cpp ) set(TEST_LIST @@ -36,7 +35,6 @@ set(TEST_EXTRA_LIBRARIES fastcdr fastrtps ddsrouter_utils - ddsrouter_core ) @@ -111,7 +109,38 @@ set(TEST_EXTRA_LIBRARIES fastcdr fastrtps ddsrouter_utils + ddsrouter_core + ) +add_unittest_executable( + "${TEST_NAME}" + "${TEST_SOURCES}" + "${TEST_LIST}" + "${TEST_EXTRA_LIBRARIES}") + +########################################################## +# Yaml GetConfigurations WanInitialPeersParticipant Test # +########################################################## + +set(TEST_NAME YamlGetInitialPeersParticipantConfigurationTest) + +set(TEST_SOURCES + ${PROJECT_SOURCE_DIR}/src/cpp/yaml_configuration_tags.cpp + ${PROJECT_SOURCE_DIR}/src/cpp/YamlReader.cpp + ${PROJECT_SOURCE_DIR}/test/TestUtils/test_utils.cpp + YamlGetInitialPeersParticipantConfigurationTest.cpp + ) + +set(TEST_LIST + get_participant_minimum + get_participant_repeater + ) + +set(TEST_EXTRA_LIBRARIES + yaml-cpp + fastcdr + fastrtps + ddsrouter_utils ddsrouter_core ) diff --git a/ddsrouter_yaml/test/unittest/participants/YamlGetCommonParticipantConfigurationTest.cpp b/ddsrouter_yaml/test/unittest/participants/YamlGetCommonParticipantConfigurationTest.cpp index b31a262ef..e14af06ad 100644 --- a/ddsrouter_yaml/test/unittest/participants/YamlGetCommonParticipantConfigurationTest.cpp +++ b/ddsrouter_yaml/test/unittest/participants/YamlGetCommonParticipantConfigurationTest.cpp @@ -118,6 +118,7 @@ TEST(YamlGetCommonParticipantConfigurationTest, get_participant_negative) utils::ConfigurationException); } } + int main( int argc, char** argv) diff --git a/ddsrouter_yaml/test/unittest/participants/YamlGetInitialPeersParticipantConfigurationTest.cpp b/ddsrouter_yaml/test/unittest/participants/YamlGetInitialPeersParticipantConfigurationTest.cpp new file mode 100644 index 000000000..4c60167d5 --- /dev/null +++ b/ddsrouter_yaml/test/unittest/participants/YamlGetInitialPeersParticipantConfigurationTest.cpp @@ -0,0 +1,185 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../YamlConfigurationTestUtils.hpp" + +using namespace eprosima::ddsrouter; +using namespace eprosima::ddsrouter::yaml; + +/** + * Test get Participant Configuration from yaml + * with id, kind + * + * Try random ids + */ +TEST(YamlGetInitialPeersParticipantConfigurationTest, get_participant_minimum) +{ + core::types::ParticipantKind kind(core::types::ParticipantKind::wan_initial_peers); + for (int i = 0; i < eprosima::ddsrouter::test::TEST_NUMBER_ITERATIONS; i++) + { + core::types::ParticipantId id = eprosima::ddsrouter::test::random_participant_id(i); + for (int j = 0; j < eprosima::ddsrouter::test::TEST_NUMBER_ITERATIONS; j++) + { + // Create a configuration with this kind and this id + Yaml yml; + Yaml yml_participant; + + yaml::test::participantid_to_yaml(yml_participant, id); + yaml::test::participantkind_to_yaml(yml_participant, kind); + + yml["participant"] = yml_participant; + + // Read Yaml + core::configuration::InitialPeersParticipantConfiguration result = + YamlReader::get( + yml, + "participant", + LATEST); + + // Check result + ASSERT_EQ(id, result.id); + ASSERT_EQ(kind, result.kind); + + // Check default values + ASSERT_EQ(0, result.connection_addresses.size()); + ASSERT_EQ(0, result.listening_addresses.size()); + ASSERT_FALSE(result.tls_configuration.is_active()); + ASSERT_EQ( + core::configuration::InitialPeersParticipantConfiguration().domain, + result.domain); + } + } +} + +/** + * Test get Participant Configuration from yaml specifing domain + * + * POSITIVE CASES: + * - default + * - true + * - false + * + * NEGATIVE CASES: + * - incorrect bool format + */ +TEST(YamlGetInitialPeersParticipantConfigurationTest, get_participant_repeater) +{ + core::types::ParticipantKind kind(core::types::ParticipantKind::wan_initial_peers); + core::types::ParticipantId id = eprosima::ddsrouter::test::random_participant_id(); + + // default + { + Yaml yml; + Yaml yml_participant; + + // Add required fields + yaml::test::participantid_to_yaml(yml_participant, id); + yaml::test::participantkind_to_yaml(yml_participant, kind); + + yml["participant"] = yml_participant; + + // Get configuration object from yaml + core::configuration::InitialPeersParticipantConfiguration result = + YamlReader::get(yml, "participant", + LATEST); + + // Check result + ASSERT_FALSE(result.is_repeater); + } + + // true + { + Yaml yml; + Yaml yml_participant; + + // Add required fields + yaml::test::participantid_to_yaml(yml_participant, id); + yaml::test::participantkind_to_yaml(yml_participant, kind); + + // Add repeater attribute + yaml::test::repeater_to_yaml(yml_participant, true); + + yml["participant"] = yml_participant; + + // Get configuration object from yaml + core::configuration::InitialPeersParticipantConfiguration result = + YamlReader::get(yml, "participant", + LATEST); + + // Check result + ASSERT_TRUE(result.is_repeater); + } + + // false + { + Yaml yml; + Yaml yml_participant; + + // Add required fields + yaml::test::participantid_to_yaml(yml_participant, id); + yaml::test::participantkind_to_yaml(yml_participant, kind); + + // Add repeater attribute + yaml::test::repeater_to_yaml(yml_participant, false); + + yml["participant"] = yml_participant; + + // Get configuration object from yaml + core::configuration::InitialPeersParticipantConfiguration result = + YamlReader::get(yml, "participant", + LATEST); + + // Check result + ASSERT_FALSE(result.is_repeater); + } + + // incorrect bool format + { + Yaml yml; + Yaml yml_participant; + + // Add required fields + yaml::test::participantid_to_yaml(yml_participant, id); + yaml::test::participantkind_to_yaml(yml_participant, kind); + + // Add incorrect repeater + yml_participant[IS_REPEATER_TAG] = "ERROR"; + + yml["participant"] = yml_participant; + + // Get configuration object from yaml and expect fail + ASSERT_THROW( + core::configuration::InitialPeersParticipantConfiguration result = + YamlReader::get(yml, "participant", LATEST), + utils::ConfigurationException); + } +} + +int main( + int argc, + char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/ddsrouter_yaml/test/unittest/yaml_tags/YamlTagsTest.cpp b/ddsrouter_yaml/test/unittest/yaml_tags/YamlTagsTest.cpp index b529ca560..abd1cf5e0 100644 --- a/ddsrouter_yaml/test/unittest/yaml_tags/YamlTagsTest.cpp +++ b/ddsrouter_yaml/test/unittest/yaml_tags/YamlTagsTest.cpp @@ -62,6 +62,7 @@ TEST(YamlTagsTest, yaml_tags) VERSION_TAG, VERSION_TAG_V_1_0, VERSION_TAG_V_2_0, + VERSION_TAG_V_3_0, PARTICIPANT_KIND_TAG_V1, }; diff --git a/docs/index.rst b/docs/index.rst index 669d7cdf4..7395ce73b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -66,6 +66,7 @@ /rst/examples/change_domain_example /rst/examples/ros_discovery_server_example /rst/examples/wan_example + /rst/examples/repeater_example .. _index_use_cases: @@ -76,7 +77,8 @@ :numbered: 5 :hidden: - /rst/use_cases/ros_cloud.rst + /rst/use_cases/ros_cloud + /rst/use_cases/repeater .. _index_developer_manual: diff --git a/docs/resources/examples/change_domain.yaml b/docs/resources/examples/change_domain.yaml index bc63db7ed..c974e7edc 100644 --- a/docs/resources/examples/change_domain.yaml +++ b/docs/resources/examples/change_domain.yaml @@ -3,7 +3,7 @@ ############################# # Yaml configuration file version -version: v2.0 +version: v3.0 # DDS Router participants participants: diff --git a/docs/resources/examples/change_domain_allowlist.yaml b/docs/resources/examples/change_domain_allowlist.yaml index 56abc3f95..64ce3e101 100644 --- a/docs/resources/examples/change_domain_allowlist.yaml +++ b/docs/resources/examples/change_domain_allowlist.yaml @@ -4,7 +4,7 @@ ################################## # CONFIGURATION VERSION -version: v2.0 # 0 +version: v3.0 # 0 ################################## # ALLOWED TOPICS @@ -43,7 +43,7 @@ participants: # This configuration example configures a DDS Router to listen to every message published in two different domains # and transmit those messages through the other domain. -# 0: Use YAML configuration version v2.0 +# 0: Use YAML configuration version v3.0 # 1: Allow DDS Topic Name with type . diff --git a/docs/resources/examples/echo.yaml b/docs/resources/examples/echo.yaml index f4bc4e801..77e75bae3 100644 --- a/docs/resources/examples/echo.yaml +++ b/docs/resources/examples/echo.yaml @@ -4,7 +4,7 @@ ################################## # CONFIGURATION VERSION -version: v2.0 # 0 +version: v3.0 # 0 ################################## # ALLOWED TOPICS @@ -43,7 +43,7 @@ participants: # HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to print the received # messages in stdout. -# 0: Use YAML configuration version v2.0 +# 0: Use YAML configuration version v3.0 # 1: Allow DDS Topic Name with type . diff --git a/docs/resources/examples/repeater_client.yaml b/docs/resources/examples/repeater_client.yaml new file mode 100644 index 000000000..6448f2e73 --- /dev/null +++ b/docs/resources/examples/repeater_client.yaml @@ -0,0 +1,67 @@ +############### +# WAN EXAMPLE # +############### + +################################## +# CONFIGURATION VERSION +version: v3.0 # 0 + +################################## +# ALLOWED TOPICS +# Allowing ROS2 HelloWorld demo_nodes + +allowlist: + - name: rt/chatter # 1 + type: std_msgs::msg::dds_::String_ # 1 + +################################## +# PARTICIPANTS +participants: + +################################## +# SIMPLE PARTICIPANT +# This participant will subscribe to topics in allowlist in domain 0 and listen every message published there + + - name: SimpleROS2 # 2 + kind: local # 3 + domain: 0 # 4 + +################################## +# WAN CLIENT +# This participant will subscribe to topics in allowlist using Initial Peers Participant + + - name: Client # 5 + kind: wan # 6 + connection-addresses: + - domain: 1.1.1.1 + port: 11666 + transport: tcp + + +################################## +# CONFIGURATION DESCRIPTION + +# This configuration example configures a DDS Router to listen to every message published in domain 0 in topic +# rt/chatter from ROS2 demo_nodes, and to transmit these messages through a WAN +# to a WAN DDS Router (this configuration is independent to the remote Participant to be repeater or not). +# The other direction of communication is also possible; receive messages at the WAN Participant and locally +# publish them in domain 0. + +# 0: Use YAML configuration version v3.0 + +# 1: Allow ROS 2 specific Topic Name with type . +# Insert new topics in order to route them. + +# 2: New Participant with name . + +# 3: Kind of SimpleROS2: . +# LAN UDP communication with default simple multicast discovery. +# Remember that every ROS 2 Node relays the middleware communication to DDS, as a standard Participant. + +# 4: SimpleROS2 will use DDS Domain ID <0>. + +# 5: New Participant with name . + +# 6: Kind of ClientROS2: . + +# 7: Add the configuration to connect with the WAN Repeater Participant raised in the other side. diff --git a/docs/resources/examples/repeater_server.yaml b/docs/resources/examples/repeater_server.yaml new file mode 100644 index 000000000..51edd39ce --- /dev/null +++ b/docs/resources/examples/repeater_server.yaml @@ -0,0 +1,57 @@ +#################### +# REPEATER EXAMPLE # +#################### + +################################## +# CONFIGURATION VERSION +version: v3.0 # 0 + +################################## +# ALLOWED TOPICS +# Allowing FastDDS and ROS2 HelloWorld demo examples topics + +allowlist: + - name: HelloWorldTopic # 1 + type: HelloWorld # 1 + - name: rt/chatter # 2 + type: std_msgs::msg::dds_::String_ + +################################## +# PARTICIPANTS +participants: + +################################## +# WAN REPEATER +# This participant will repeat the messages that arrive to it. + + - name: RepeaterParticipant # 3 + kind: wan # 4 + repeater: true # 5 + listening-addresses: + - ip: 1.1.1.1 + port: 11666 + transport: tcp + +################################## +# CONFIGURATION DESCRIPTION + +# This configuration example configures a DDS Router to listen to every message published in domain 0 in topics +# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages +# through a WAN Participant (configured as Server) to another WAN Participant. +# The other direction of communication is also possible; receive messages at the WAN Participant and locally +# publish them in domain 0. +# Server specifies which DDS Router starts the communication with the other, and after communication has been +# established, both routers behave in the same way. + +# 0: Use YAML configuration version v3.0 + +# 1: Allow DDS Topic Name with type . + +# 2: Insert new topics in order to route them. + +# 3: New Participant with name . + +# 4: Kind of RepeaterParticipant: . +# WAN communication with other DDS Routers. + +# 5: RepeaterParticipant will repeat messages that arrive to it to the rest of DDS Routers connected. diff --git a/docs/resources/examples/ros_discovery_client.yaml b/docs/resources/examples/ros_discovery_client.yaml index 9f5058722..d7e1b6fa1 100644 --- a/docs/resources/examples/ros_discovery_client.yaml +++ b/docs/resources/examples/ros_discovery_client.yaml @@ -4,7 +4,7 @@ ################################## # CONFIGURATION VERSION -version: v2.0 # 0 +version: v3.0 # 0 ################################## # ALLOWED TOPICS @@ -53,7 +53,7 @@ participants: # The other direction of communication is also possible; receive messages at the Discovery Server and locally # publish them in domain 0. -# 0: Use YAML configuration version v2.0 +# 0: Use YAML configuration version v3.0 # 1: Allow ROS 2 specific Topic Name with type . # Insert new topics in order to route them. diff --git a/docs/resources/examples/ros_discovery_server.yaml b/docs/resources/examples/ros_discovery_server.yaml index 3ef337fd6..35d019825 100644 --- a/docs/resources/examples/ros_discovery_server.yaml +++ b/docs/resources/examples/ros_discovery_server.yaml @@ -4,7 +4,7 @@ ################################## # CONFIGURATION VERSION -version: v2.0 # 0 +version: v3.0 # 0 ################################## # ALLOWED TOPICS @@ -49,7 +49,7 @@ participants: # The other direction of communication is also possible; receive messages at the Discovery Server and locally # publish them in domain 0. -# 0: Use YAML configuration version v2.0 +# 0: Use YAML configuration version v3.0 # 1: Allow DDS ROS 2 specific Topic Name with type . # Insert new topics in order to route them. diff --git a/docs/resources/examples/wan_client.yaml b/docs/resources/examples/wan_client.yaml index ca3cec999..b8a12c099 100644 --- a/docs/resources/examples/wan_client.yaml +++ b/docs/resources/examples/wan_client.yaml @@ -4,7 +4,7 @@ ################################## # CONFIGURATION VERSION -version: v2.0 # 0 +version: v3.0 # 0 ################################## # ALLOWED TOPICS @@ -34,18 +34,14 @@ participants: - name: WANClient # 6 kind: wan # 7 - discovery-server-guid: - id: 2 # 8 - connection-addresses: # 9 - - discovery-server-guid: - id: 1 # 10 - addresses: # 11 - - ip: 1.1.1.1 + connection-addresses: # 8 + addresses: # 9 + - ip: 1.1.1.1 # 10 port: 11666 - listening-addresses: # 12 - - ip: 2.2.2.2 # 13 - port: 11670 # 14 - transport: udp # 15 + listening-addresses: # 11 + - ip: 2.2.2.2 # 12 + port: 11670 # 13 + transport: udp # 14 ################################## # CONFIGURATION DESCRIPTION @@ -58,7 +54,7 @@ participants: # Client specifies which DDS Router starts the communication with the other, and after communication has been # established, both routers behave in the same way. -# 0: Use YAML configuration version v2.0 +# 0: Use YAML configuration version v3.0 # 1: Allow DDS Topic Name with type . @@ -76,26 +72,22 @@ participants: # 7: Kind of WANClient: . # WAN communication with another DDS Router. -# 8: Set the Discovery Server GuidPrefix to <01.0f.02.00.00.00.00.00.00.00.ca.fe> for WANClient. - # 9: Add the addresses where to reach the remote DDS Routers that will connect to. # Add as many connection-addresses as needed. -# 10: Set the Remote Discovery Server GuidPrefix to <01.0f.01.00.00.00.00.00.00.00.ca.fe>. - -# 11: Connect to a Discovery Server in IP <1.1.1.1> listening in port 11666 over UDP transport (default). +# 10: Connect to a WAN Participant in IP <1.1.1.1> listening in port 11666 over UDP transport (default). # This is the same configuration that must be set in the DDS Router that works as a Server in its listening-addresses. # Add every other address where trying to reach this same remote WAN Discovery Server. -# 12: Add the interfaces where this Participant will listen in WAN. +# 11: Add the interfaces where this Participant will listen in WAN. # This is only needed if Remote WAN Server is using only UDP. # Add as many listening-addresses as needed. -# 13: Listen in public IP (2.2.2.2) for remote traffic. +# 12: Listen in public IP (2.2.2.2) for remote traffic. # This IP must be set to the public IP of the host where this DDS Router will run. -# 14: Listening port is 11670. +# 13: Listening port is 11670. # Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network # router to this host to the same port. -# 15: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". +# 14: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/docs/resources/examples/wan_ds_client.yaml b/docs/resources/examples/wan_ds_client.yaml new file mode 100644 index 000000000..757ba58b0 --- /dev/null +++ b/docs/resources/examples/wan_ds_client.yaml @@ -0,0 +1,101 @@ +####################################### +# WAN DISCOVERY SERVER CLIENT EXAMPLE # +####################################### + +################################## +# CONFIGURATION VERSION +version: v3.0 # 0 + +################################## +# ALLOWED TOPICS +# Allowing FastDDS and ROS2 HelloWorld demo examples topics + +allowlist: + - name: HelloWorldTopic # 1 + type: HelloWorld # 1 + - name: rt/chatter # 2 + type: std_msgs::msg::dds_::String_ + +################################## +# PARTICIPANTS +participants: + +################################## +# SIMPLE PARTICIPANT +# This participant will subscribe to topics in allowlist in domain 1 and listen every message published there + + - name: SimpleParticipant # 3 + kind: local # 4 + domain: 1 # 5 + +################################## +# WAN CLIENT +# This participant will subscribe to topics in allowlist using Discovery Server protocol as SuperClient. + + - name: WANClient # 6 + kind: wan-ds # 7 + discovery-server-guid: + id: 2 # 8 + connection-addresses: # 9 + - discovery-server-guid: + id: 1 # 10 + addresses: # 11 + - ip: 1.1.1.1 + port: 11666 + listening-addresses: # 12 + - ip: 2.2.2.2 # 13 + port: 11670 # 14 + transport: udp # 15 + +################################## +# CONFIGURATION DESCRIPTION + +# This configuration example configures a DDS Router to listen to every message published in domain 1 in topics +# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages +# through a WAN Participant (configured as Super Client) to another WAN Participant. +# The other direction of communication is also possible; receive messages at the Discovery Server WAN Participant +# and locally publish them in domain 1. +# Client specifies which DDS Router starts the communication with the other, and after communication has been +# established, both routers behave in the same way. + +# 0: Use YAML configuration version v3.0 + +# 1: Allow DDS Topic Name with type . + +# 2: Insert new topics in order to route them. + +# 3: New Participant with name . + +# 4: Kind of SimpleParticipant: . +# LAN UDP communication with default simple multicast discovery. + +# 5: SimpleParticipant will use DDS Domain ID <1>. + +# 6: New Participant with name . + +# 7: Kind of WANClient: . +# Discovery Server WAN communication with another DDS Router. + +# 8: Set the Discovery Server GuidPrefix to <01.0f.02.00.00.00.00.00.00.00.ca.fe> for WANClient. + +# 9: Add the addresses where to reach the remote DDS Routers that will connect to. +# Add as many connection-addresses as needed. + +# 10: Set the Remote Discovery Server GuidPrefix to <01.0f.01.00.00.00.00.00.00.00.ca.fe>. + +# 11: Connect to a Discovery Server in IP <1.1.1.1> listening in port 11666 over UDP transport (default). +# This is the same configuration that must be set in the DDS Router that works as a Server in its listening-addresses. +# Add every other address where trying to reach this same remote WAN Discovery Server. + +# 12: Add the interfaces where this Participant will listen in WAN. +# This is only needed if Remote WAN Server is using only UDP. +# Add as many listening-addresses as needed. + +# 13: Listen in public IP (2.2.2.2) for remote traffic. +# This IP must be set to the public IP of the host where this DDS Router will run. + +# 14: Listening port is 11670. +# Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network +# router to this host to the same port. + +# 15: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/docs/resources/examples/wan_ds_server.yaml b/docs/resources/examples/wan_ds_server.yaml new file mode 100644 index 000000000..b2147a3a2 --- /dev/null +++ b/docs/resources/examples/wan_ds_server.yaml @@ -0,0 +1,86 @@ +####################################### +# WAN DISCOVERY SERVER SERVER EXAMPLE # +####################################### + +################################## +# CONFIGURATION VERSION +version: v3.0 # 0 + +################################## +# ALLOWED TOPICS +# Allowing FastDDS and ROS2 HelloWorld demo examples topics + +allowlist: + - name: HelloWorldTopic # 1 + type: HelloWorld # 1 + - name: rt/chatter # 2 + type: std_msgs::msg::dds_::String_ + +################################## +# PARTICIPANTS +participants: + +################################## +# SIMPLE PARTICIPANT +# This participant will subscribe to topics in allowlist in domain 0 and listen every message published there + + - name: SimpleParticipant # 3 + kind: local # 4 + domain: 0 # 5 + +################################## +# WAN SERVER +# This participant will subscribe to topics in allowlist using Discovery Server protocol as Server + + - name: WANServer # 6 + kind: wan-ds # 7 + discovery-server-guid: + id: 1 # 8 + listening-addresses: # 9 + - ip: 1.1.1.1 # 10 + port: 11666 # 11 + transport: udp # 12 + +################################## +# CONFIGURATION DESCRIPTION + +# This configuration example configures a DDS Router to listen to every message published in domain 0 in topics +# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages +# through a WAN Participant (configured as Server) to another WAN Participant. +# The other direction of communication is also possible; receive messages at the Discovery Server WAN Participant +# and locally publish them in domain 0. +# Server specifies which DDS Router starts the communication with the other, and after communication has been +# established, both routers behave in the same way. + +# 0: Use YAML configuration version v3.0 + +# 1: Allow DDS Topic Name with type . + +# 2: Insert new topics in order to route them. + +# 3: New Participant with name . + +# 4: Kind of SimpleParticipant: . +# LAN UDP communication with default simple multicast discovery. + +# 5: SimpleParticipant will use DDS Domain ID <0>. + +# 6: New Participant with name . + +# 7: Kind of WANServer: . +# Discovery Server WAN communication with another DDS Router. + +# 8: Set this Discovery Server GuidPrefix to <01.0f.01.00.00.00.00.00.00.00.ca.fe> for WANServer. +# This GuidPrefix is needed in order from a remote DDS Router to connect with this one. + +# 9: Add the interfaces where this Participant will listen in WAN. +# Add as many listening-addresses as needed. + +# 10: Listen in public IP (1.1.1.1) for remote traffic. +# This IP must be set to the public IP of the host where this DDS Router will run. + +# 11: Listening port is 11666. +# Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network +# router to this host to the same port. + +# 12: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/docs/resources/examples/wan_server.yaml b/docs/resources/examples/wan_server.yaml index 87e1b1c19..705b8c931 100644 --- a/docs/resources/examples/wan_server.yaml +++ b/docs/resources/examples/wan_server.yaml @@ -4,7 +4,7 @@ ################################## # CONFIGURATION VERSION -version: v2.0 # 0 +version: v3.0 # 0 ################################## # ALLOWED TOPICS @@ -34,12 +34,10 @@ participants: - name: WANServer # 6 kind: wan # 7 - discovery-server-guid: - id: 1 # 8 - listening-addresses: # 9 - - ip: 1.1.1.1 # 10 - port: 11666 # 11 - transport: udp # 12 + listening-addresses: # 8 + - ip: 1.1.1.1 # 9 + port: 11666 # 10 + transport: udp # 11 ################################## # CONFIGURATION DESCRIPTION @@ -52,7 +50,7 @@ participants: # Server specifies which DDS Router starts the communication with the other, and after communication has been # established, both routers behave in the same way. -# 0: Use YAML configuration version v2.0 +# 0: Use YAML configuration version v3.0 # 1: Allow DDS Topic Name with type . @@ -70,17 +68,14 @@ participants: # 7: Kind of WANServer: . # WAN communication with another DDS Router. -# 8: Set this Discovery Server GuidPrefix to <01.0f.01.00.00.00.00.00.00.00.ca.fe> for WANServer. -# This GuidPrefix is needed in order from a remote DDS Router to connect with this one. - -# 9: Add the interfaces where this Participant will listen in WAN. +# 8: Add the interfaces where this Participant will listen in WAN. # Add as many listening-addresses as needed. -# 10: Listen in public IP (1.1.1.1) for remote traffic. +# 9: Listen in public IP (1.1.1.1) for remote traffic. # This IP must be set to the public IP of the host where this DDS Router will run. -# 11: Listening port is 11666. +# 10: Listening port is 11666. # Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network # router to this host to the same port. -# 12: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". +# 11: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/docs/resources/getting_started/client-ddsrouter.yaml b/docs/resources/getting_started/client-ddsrouter.yaml index 71910b3f0..0652784a6 100644 --- a/docs/resources/getting_started/client-ddsrouter.yaml +++ b/docs/resources/getting_started/client-ddsrouter.yaml @@ -1,6 +1,6 @@ # client-ddsrouter.yaml -version: v2.0 +version: v3.0 allowlist: - name: Square @@ -12,7 +12,7 @@ participants: domain: 0 - name: ClientWAN - kind: wan + kind: wan-ds discovery-server-guid: id: 1 connection-addresses: diff --git a/docs/resources/getting_started/server-ddsrouter.yaml b/docs/resources/getting_started/server-ddsrouter.yaml index ed297a4a6..b0754acbf 100644 --- a/docs/resources/getting_started/server-ddsrouter.yaml +++ b/docs/resources/getting_started/server-ddsrouter.yaml @@ -1,6 +1,6 @@ # server-ddsrouter.yaml -version: v2.0 +version: v3.0 allowlist: - name: Square @@ -13,7 +13,7 @@ participants: domain: 1 - name: ServerWAN - kind: wan + kind: wan-ds discovery-server-guid: id: 0 listening-addresses: diff --git a/docs/resources/use_cases/ros_cloud/ConfigMap.yaml b/docs/resources/use_cases/ros_cloud/ConfigMap.yaml index 139537eaf..d63212406 100644 --- a/docs/resources/use_cases/ros_cloud/ConfigMap.yaml +++ b/docs/resources/use_cases/ros_cloud/ConfigMap.yaml @@ -4,7 +4,7 @@ metadata: name: ddsrouter-config data: ddsrouter.config.file: |- - version: v2.0 + version: v3.0 allowlist: - name: rt/chatter diff --git a/docs/resources/use_cases/ros_cloud/local-ddsrouter.yaml b/docs/resources/use_cases/ros_cloud/local-ddsrouter.yaml index 203c85bac..904594635 100644 --- a/docs/resources/use_cases/ros_cloud/local-ddsrouter.yaml +++ b/docs/resources/use_cases/ros_cloud/local-ddsrouter.yaml @@ -1,6 +1,6 @@ # local-ddsrouter.yaml -version: v2.0 +version: v3.0 allowlist: - name: rt/chatter diff --git a/docs/rst/appendixes/glossary.rst b/docs/rst/appendixes/glossary.rst index cbfb62b81..3b727625f 100644 --- a/docs/rst/appendixes/glossary.rst +++ b/docs/rst/appendixes/glossary.rst @@ -21,6 +21,12 @@ Glossary TCP **Transmission Control Protocol** + TURN + **Traversal Using Relays around NAT** + A TURN server is a network element that supports a common point of redirection of messages. + It redirect messages between N nodes connected to it. + This is a very common technique in order to traverse a NAT or an unreachable network. + UDP **User Datagram Protocol** diff --git a/docs/rst/examples/repeater_example.rst b/docs/rst/examples/repeater_example.rst new file mode 100644 index 000000000..c52ca4ae6 --- /dev/null +++ b/docs/rst/examples/repeater_example.rst @@ -0,0 +1,134 @@ +.. include:: ../exports/alias.include + +.. _example_repeater: + +################ +Repeater Example +################ + +A |ddsrouter| could work as a :term:`TURN` **Repeater** to forward messages by the same Participant. +If you are interested in understanding the use case of a Repeater please refer to the following +section :ref:`use_case_repeater`. + +Configuration +============= + +Version +------- + +The version attribute is required, as the :code:`repeater` tag is only supported from v3.0 configuration version. + +.. literalinclude:: ../../resources/examples/repeater_server.yaml + :language: yaml + :lines: 7-7 + +Allowed Topics +-------------- + +This section lists the :term:`Topics ` that the DDS Router will route from +one Participant to the other. +Topic ``HelloWorldTopic`` with datatype ``HelloWorld``, +and ROS 2 topic ``rt/chatter`` with datatype ``std_msgs::msg::dds_::String_`` will be forwarded from +one domain to the other, allowing different DDS domains to interact with each other. + +.. literalinclude:: ../../resources/examples/repeater_server.yaml + :language: yaml + :lines: 13-17 + + +Repeater Participant +-------------------- + +The **Repeater Participant** is the one that will be used to forward messages by the same Participant. +It must be a :code:`WAN` Participant and be configured as so with *Discovery Server* configuration. + +.. literalinclude:: ../../resources/examples/repeater_server.yaml + :language: yaml + :lines: 27-33 + + +Client Participants +------------------- + +Every *Discovery Server Client* can connect to a Repeater Participant as if it was a normal :code:`WAN` Participant. +The Repeater admits as many edge |ddsrouter| connections as desired, so several |ddsrouter| can use the same +or similar configuration to communicate across it. + +.. literalinclude:: ../../resources/examples/repeater_client.yaml + :language: yaml + :lines: 33-39 + + +Execute example +=============== + +Please refer to this :ref:`section ` for a detailed explanation on how to execute the +|ddsrouter|. + +.. todo: + + Add link when BasicConfiguration Example is added to Fast DDS (if it happens) + + Execute with Fast DDS HelloWorld Example + ---------------------------------------- + +Execute with ROS 2 demo nodes +----------------------------- + +In order to run this example, there must be three different hosts located in different local networks: + +* host *H*:sub:`A` with private IP ``192.168.1.2`` connected to network router *R*:sub:`A` with public IP ``1.1.1.1``. +* host *H*:sub:`B` with private IP ``192.168.2.2`` connected to network router *R*:sub:`B` with public IP ``2.2.2.2``. +* host *H*:sub:`C` with private IP ``192.168.2.3`` connected to network router *R*:sub:`C` with public IP ``3.3.3.3``. + +This example could be run in localhost or with two hosts in the same LAN, but it will not use the WAN +communication features of the |ddsrouter|. + +Host *H*:sub:`A` +---------------- + +This host runs the |ddsrouter| Repeater Server, which will receive data from both edges and redirect the messages +between them. +Execute |ddsrouter| using file +``/share/resources/configurations/examples/repeater_server.yaml``. +Remember to change the IP and port on the configuration file to the actual public IP of *R*:sub:`A`, and be sure that +the port forwarding rules are configured in *R*:sub:`A` so *H*:sub:`A` is accessible from the outside. + + +Hosts *H*:sub:`B` and *H*:sub:`C` +--------------------------------- + +These hosts run the |ddsrouter| WAN Clients, which will connect to the previously launched Repeater Server. +Execute |ddsrouter| using file +``/share/resources/configurations/examples/repeater_client.yaml``. +Remember to change the IPs and ports on the configuration file to the actual public IPs of *R*:sub:`A` and *R*:sub:`B`. +**In this example the port forwarding is not required, as the Repeater will allow the communication through it, +and TCP protocol is being used.**. + +Both clients can execute ROS 2 demo nodes, which will publish and subscribe in topic ``rt/chatter``. +Execute a ``talker`` in one of them and a ``listener`` in the other. +It is recommended to use different ``ROS_DOMAIN_ID`` in each node, so in case both nodes are accessible +(under same network) no loop is created. +In order to do so, change the YAML configuration files to use different domains, and use the following ROS2 commands: + +.. code-block:: bash + + # Hb + ROS_DOMAIN_ID=0 ros2 run demo_nodes_cpp talker + + # Hc + ROS_DOMAIN_ID=1 ros2 run demo_nodes_cpp listener + + +Result +------ + +After executing the three |ddsrouter| applications in hosts, and *talker* and *listener* applications, +the *listener* in *H*:sub:`C` will start receiving and printing data from the *talker* in *H*:sub:`B`. +**You are communicating DDS via WAN**. + +.. note:: + + If *H*:sub:`B` can access *H*:sub:`C` due to port forwarding or because both are under the same network, + the ``listener`` will receive duplicated messages, as one of them will arrive from *H*:sub:`B` and the other + from *H*:sub:`A`. diff --git a/docs/rst/examples/wan_example.rst b/docs/rst/examples/wan_example.rst index 6357a5b17..6c2aa2394 100644 --- a/docs/rst/examples/wan_example.rst +++ b/docs/rst/examples/wan_example.rst @@ -12,7 +12,7 @@ In the following snippet we see a yaml file to configure a DDS Router to create .. literalinclude:: ../../resources/examples/wan_server.yaml :language: yaml - :lines: 5-42 + :lines: 5-40 Configuration ============= @@ -52,7 +52,7 @@ this Participant will work as TCP Server). .. literalinclude:: ../../resources/examples/wan_server.yaml :language: yaml - :lines: 35-42 + :lines: 35-40 WAN Participant Client ---------------------- @@ -62,7 +62,7 @@ In order to create a WAN Participant Client, check the configuration file .. literalinclude:: ../../resources/examples/wan_client.yaml :language: yaml - :lines: 35-48 + :lines: 35-44 Execute example diff --git a/docs/rst/figures/repeater.png b/docs/rst/figures/repeater.png new file mode 100644 index 000000000..a4b1786a6 Binary files /dev/null and b/docs/rst/figures/repeater.png differ diff --git a/docs/rst/notes/forthcoming_version.rst b/docs/rst/notes/forthcoming_version.rst index 26553cbf4..8d4eeaa63 100644 --- a/docs/rst/notes/forthcoming_version.rst +++ b/docs/rst/notes/forthcoming_version.rst @@ -1,14 +1,29 @@ -.. todo: - remove orphan tag when new info added to this file - - :orphan: +.. add orphan tag when new info added to this file +.. :orphan: ################### Forthcoming Version ################### -Next version will add the following **features**: +Next release will include the following **features**: + +* New :ref:`Repeater behaviour `, + a new configuration to create :term:`TURN` servers. +* Timeout argument ``--timeout`` to close the application after the time set has passed. + Check section :ref:`user_manual_user_interface_timeout_argument` for more information. + +Next release will include the following **Fast DDS features**: + +* New :term:`Initial Peers` Participant that allows to create a fast WAN communication + avoiding the Discovery Server configuration. + +Next release will include the following **configuration changes**: + +* New Configuration Version ``v3.0`` that allow Repeater and initial peers configuration. +* Yaml Validator only validates ``v3.0`` configurations. + +Next release will include the following **major changes**: - - Timeout argument ``--timeout`` to close the application after the time set has passed. - Check section :ref:`user_manual_user_interface_timeout_argument` for more information. +* ``wan`` Participant Kind uses now Initial Peers Discovery Protocol, while Discovery Server + requires a new Participant Kind ``wan-discovery-server``. diff --git a/docs/rst/notes/notes.rst b/docs/rst/notes/notes.rst index 302bd1b40..012f4ed40 100644 --- a/docs/rst/notes/notes.rst +++ b/docs/rst/notes/notes.rst @@ -2,9 +2,9 @@ .. _release_notes: -.. todo: - uncomment the include of forthcoming when new info is added - .. include:: forthcoming_version.rst +.. comment the include of forthcoming when new info is added + +.. include:: forthcoming_version.rst .. include:: forthcoming_version.rst diff --git a/docs/rst/use_cases/repeater.rst b/docs/rst/use_cases/repeater.rst new file mode 100644 index 000000000..d13323527 --- /dev/null +++ b/docs/rst/use_cases/repeater.rst @@ -0,0 +1,38 @@ +.. include:: ../exports/alias.include + +.. _use_case_repeater: + +################### +Repeater DDS Router +################### + +A |ddsrouter| could work as a :term:`TURN` **Repeater**. +This means that a |ddsrouter| can be used to repeat messages between networks. + +Use case +======== + +The use of a :term:`TURN` Server is very useful in the following scenarios: + +- **NAT Traversal**: If the edge devices are under different NATs, they cannot access each other if no + ports are opened in their respective internet access points. +- **Unreachable Network**: If edge devices work under different networks (e.g. using different transport protocols, + connected in different private networks, etc.) cannot reach each other. + +The following figure exemplifies these use cases. +When the communication between edge routers is not possible, a Repeater can be set in the middle to forward data +and make the communication possible. + +.. figure:: /rst/figures/repeater.png + + +How to configure +================ + +This |ddsrouter| configuration is very simple, as all it needs is a :ref:`user_manual_participants_wan` and +adding to its configuration the tag `repeater: true`. +There could be more Participants in this |ddsrouter| and topic filtering is also available. +The Repeater Participant only works as other normal Participant, +with the particularity that resend forward the data that receives. + +In order to see an example of this configuration, access to the following example :ref:`example_repeater`. diff --git a/docs/rst/user_manual/configuration.rst b/docs/rst/user_manual/configuration.rst index f97b1f638..691381262 100644 --- a/docs/rst/user_manual/configuration.rst +++ b/docs/rst/user_manual/configuration.rst @@ -270,6 +270,25 @@ Be aware that some Participants (e.g. Discovery Servers) does not need a Domain domain: 101 +.. _user_manual_configuration_repeater: + +Repeater Participant +==================== + +Optional tag ``repeater`` configures a :ref:`WAN Participant ` as a *Repeater* point. +This means that this Participant will forward all the information received from its Readers by its Writer. + +Check the following :ref:`use_case_repeater` to know how to use the ``repeater`` Participant attribute. + +.. code-block:: yaml + + repeater: true + +.. note:: + + This tag is only supported in configuration versions above v2.0. + + .. _user_manual_configuration_network_address: Network Address @@ -364,13 +383,13 @@ Default value for ``id`` is ``0``. id: 13 # GuidPrefix = 44.53.0d.5f.45.50.52.4f.53.49.4d.41 -.. _user_manual_configuration_discovery_server_listening_addresses: +.. _user_manual_configuration_listening_addresses: -Discovery Server Listening Addresses -==================================== +Listening Addresses +=================== -Tag ``listening-addresses`` configures the network addresses where the Discovery Server configured is going to -listen for remote clients or servers. +Tag ``listening-addresses`` configures the network addresses where this Participant is going to +listen for remote Participants. ``listening-addresses`` is *key* for an array of :ref:`Network Addresses `. .. code-block:: yaml @@ -383,6 +402,24 @@ listen for remote clients or servers. transport: tcp +.. _user_manual_configuration_initial_peers_connection_addresses: + +Initial Peers Connection Addresses +================================== + +Tag ``connection-addresses`` configure a connection with one or multiple remote WAN Participants. +``connection-addresses`` is *key* for an array of :ref:`Network Addresses `. + +.. code-block:: yaml + + connection-addresses: + - ip: 127.0.0.1 + port: 11666 + - ip: 2001:4860:4860::8844 + port: 11668 + transport: tcp + + .. _user_manual_configuration_discovery_server_connection_addresses: Discovery Server Connection Addresses @@ -422,7 +459,7 @@ A complete example of all the configurations described on this page can be found .. code-block:: yaml # Version Latest - version: v2.0 + version: v3.0 # Relay topic rt/chatter and type std_msgs::msg::dds_::String_ # Relay topic HelloWorldTopic and type HelloWorld @@ -471,7 +508,9 @@ A complete example of all the configurations described on this page can be found # Participant that will communicate with a DDS Router in a different LAN. # This Participant will work as the remote DDS Router Client, so it set the connection address of the remote one. - - name: Wan # Participant Name = Wan ; if kind is not specified, this value is used to determine the Participant Kind + - name: Wan # Participant Name = Wan + + kind: wan-ds # Participant Kind = Discovery Server WAN discovery-server-guid: id: 2 # Internal WAN Discovery Server id => GuidPrefix = 01.0f.02.00.00.00.00.00.00.00.ca.fe diff --git a/docs/rst/user_manual/participants/local_discovery_server.rst b/docs/rst/user_manual/participants/local_discovery_server.rst index c74b8556a..3942087ab 100644 --- a/docs/rst/user_manual/participants/local_discovery_server.rst +++ b/docs/rst/user_manual/participants/local_discovery_server.rst @@ -35,7 +35,7 @@ Local Discovery Server Participant allow configure the standard attributes of a * To configure the Discovery Server :term:`GuidPrefix`, check the following section :ref:`Configuration section `. * To configure the Discovery Server listening addresses, check the following section - :ref:`Configuration section `. + :ref:`Configuration section `. * To configure the Discovery Server connection addresses to connect with other Discovery Servers, check the following section :ref:`Configuration section `. diff --git a/docs/rst/user_manual/participants/participant.rst b/docs/rst/user_manual/participants/participant.rst index 23d67721c..94c0240c9 100644 --- a/docs/rst/user_manual/participants/participant.rst +++ b/docs/rst/user_manual/participants/participant.rst @@ -130,4 +130,5 @@ Below is the list with all the available Participant Kinds. echo simple local_discovery_server + wan_discovery_server wan diff --git a/docs/rst/user_manual/participants/wan.rst b/docs/rst/user_manual/participants/wan.rst index 05ec570e4..1d5a4cca2 100644 --- a/docs/rst/user_manual/participants/wan.rst +++ b/docs/rst/user_manual/participants/wan.rst @@ -6,7 +6,7 @@ WAN Participant ############### -This type of :term:`Participant` refers to a :term:`Discovery Server` :term:`DomainParticipant` that communicates +This type of :term:`Participant` refers to a :term:`Initial Peers` :term:`DomainParticipant` that communicates with other **WAN** Participants in different networks. This Participant will work as bridge for every Participant working locally in the LAN and any other LAN that has a |ddsrouter| with an active WAN Participant. @@ -29,26 +29,32 @@ Kind aliases * ``wan`` * ``router`` +* ``initial-peers`` Configuration ============= -WAN Discovery Server Participant allow configure the standard attributes of a Discovery Server. +WAN Participant allow configure the listening and connection addresses, whether if it should be located from +remote Participants or it should locate others remote Participants: -* To configure the Discovery Server :term:`GuidPrefix`, check the following section - :ref:`Configuration section `. -* To configure the Discovery Server listening addresses, check the following section - :ref:`Configuration section `. -* To configure the Discovery Server connection addresses to connect with other Discovery Servers, +* To configure the listening addresses, check the following section + :ref:`Configuration section `. +* To configure the connection addresses to connect with other Wan Participant, check the following section - :ref:`Configuration section `. + :ref:`Configuration section `. .. note:: The network addresses set in *listening-addresses* and *connection-addresses* use ``UDP`` transport by default if the transport is not specified in the address configuration. +Repeater +-------- + +This Participant allows a tag ``repeater`` to be used as a :term:`TURN` server. +Please refer to section :ref:`use_case_repeater` for more information. + WAN Configuration ----------------- @@ -58,10 +64,10 @@ the |ddsrouter| for WAN communication. Configuration Example ===================== -Configure a WAN Discovery Server with GuidPrefix id ``2`` (``01.0f.02.00.00.00.00.00.00.00.ca.fe``). +Configure a WAN Participant. It listens for clients in public IP ``82.0.0.1`` in port ``11600`` in ``TCP``. -It connects with a remote WAN Participant in IPv6 address ``2001:4860:4860::8888`` and port ``11666`` which Discovery -Server GuidPrefix is ``01.0f.04.00.00.00.00.00.00.00.ca.fe`` using ``UDP`` transport. +It connects with a remote Participant in IPv6 address ``2001:4860:4860::8888`` and port ``11666`` +using ``TCP`` transport. .. code-block:: yaml @@ -69,17 +75,11 @@ Server GuidPrefix is ``01.0f.04.00.00.00.00.00.00.00.ca.fe`` using ``UDP`` trans kind: wan - discovery-server-guid: - id: 2 # GuidPrefix = 01.0f.02.00.00.00.00.00.00.00.ca.fe - - listening-addresses: # WAN Discovery Server Listening Addresses + listening-addresses: # WAN Participant Listening Addresses - ip: 82.0.0.1 # Use UDP by default port: 11600 connection-addresses: # Another WAN Participant Listening Addresses - - discovery-server-guid: - id: 4 # External Discovery Server id => GuidPrefix = 01.0f.04.00.00.00.00.00.00.00.ca.fe - addresses: - - ip: 2001:4860:4860::8888 - port: 11666 - transport: udp # Use UDP transport + - ip: 2001:4860:4860::8888 + port: 11666 + transport: tcp # Use UDP transport diff --git a/docs/rst/user_manual/participants/wan_discovery_server.rst b/docs/rst/user_manual/participants/wan_discovery_server.rst new file mode 100644 index 000000000..5cd594a30 --- /dev/null +++ b/docs/rst/user_manual/participants/wan_discovery_server.rst @@ -0,0 +1,85 @@ +.. include:: ../../exports/alias.include + +.. _user_manual_participants_discovery_server_wan: + +################################ +Discovery Server WAN Participant +################################ + +This type of :term:`Participant` refers to a :term:`Discovery Server` :term:`DomainParticipant` that communicates +with other **WAN** Participants in different networks. +This Participant will work as bridge for every Participant working locally in the LAN and any other LAN that has +a |ddsrouter| with an active WAN Participant. + +.. warning:: + + Do not try to communicate a WAN Participant with any other kind of Participant that is not of type + WAN Participant. + +Use case +======== + +Use this Participant to communicate an internal DDS network with other LANs through a WAN communication. +Each of the networks to be connected require a running |ddsrouter|, and the messages will be relay from one to +another depending on the topics filtered by each of them. + + +Kind aliases +============ + +* ``wan-discovery-server`` +* ``wan-ds`` + + +Configuration +============= + +WAN Discovery Server Participant allow configure the standard attributes of a Discovery Server. + +* To configure the Discovery Server :term:`GuidPrefix`, check the following section + :ref:`Configuration section `. +* To configure the Discovery Server listening addresses, check the following section + :ref:`Configuration section `. +* To configure the Discovery Server connection addresses to connect with other Discovery Servers, + check the following section + :ref:`Configuration section `. + +.. note:: + + The network addresses set in *listening-addresses* and *connection-addresses* use ``UDP`` transport by default + if the transport is not specified in the address configuration. + +WAN Configuration +----------------- + +Refer to section :ref:`user_manual_wan_configuration` for detailed explanation on how to correctly configure +the |ddsrouter| for WAN communication. + +Configuration Example +===================== + +Configure a WAN Discovery Server with GuidPrefix id ``2`` (``01.0f.02.00.00.00.00.00.00.00.ca.fe``). +It listens for clients in public IP ``82.0.0.1`` in port ``11600`` in ``TCP``. +It connects with a remote WAN Participant in IPv6 address ``2001:4860:4860::8888`` and port ``11666`` which Discovery +Server GuidPrefix is ``01.0f.04.00.00.00.00.00.00.00.ca.fe`` using ``UDP`` transport. + +.. code-block:: yaml + + - name: wan_participant # Participant Name = wan_participant + + kind: wan + + discovery-server-guid: + id: 2 # GuidPrefix = 01.0f.02.00.00.00.00.00.00.00.ca.fe + + listening-addresses: # WAN Discovery Server Listening Addresses + - ip: 82.0.0.1 # Use UDP by default + port: 11600 + + connection-addresses: # Another WAN Participant Listening Addresses + - discovery-server-guid: + id: 4 # External Discovery Server id => GuidPrefix = 01.0f.04.00.00.00.00.00.00.00.ca.fe + addresses: + - ip: 2001:4860:4860::8888 + port: 11666 + transport: udp # Use UDP transport diff --git a/docs/rst/user_manual/user_manual_glossary.rst b/docs/rst/user_manual/user_manual_glossary.rst index 5a65c5503..6f67d5245 100644 --- a/docs/rst/user_manual/user_manual_glossary.rst +++ b/docs/rst/user_manual/user_manual_glossary.rst @@ -95,6 +95,14 @@ DDS nomenclature Global Unique Identifier shared by a Participant and all its sub-entities. Identifies uniquely a DDS Participant. + Initial Peers + It is a Fast DDS Discovery Protocol that allows to send the discovery information directly + to the participants configured. + This is highly recommended for static networks where multicast is not available (e.g. WAN). + + See `Fast DDS documentation `__ + for further information. + Topic DDS isolation abstraction to encapsulate subscriptions and publications. Each Topic is uniquely identified by a topic name and a topic type name (name of the data type it transmits). diff --git a/resources/configurations/examples/change_domain.yaml b/resources/configurations/examples/change_domain.yaml index bc63db7ed..c974e7edc 100644 --- a/resources/configurations/examples/change_domain.yaml +++ b/resources/configurations/examples/change_domain.yaml @@ -3,7 +3,7 @@ ############################# # Yaml configuration file version -version: v2.0 +version: v3.0 # DDS Router participants participants: diff --git a/resources/configurations/examples/change_domain_allowlist.yaml b/resources/configurations/examples/change_domain_allowlist.yaml index 56abc3f95..64ce3e101 100644 --- a/resources/configurations/examples/change_domain_allowlist.yaml +++ b/resources/configurations/examples/change_domain_allowlist.yaml @@ -4,7 +4,7 @@ ################################## # CONFIGURATION VERSION -version: v2.0 # 0 +version: v3.0 # 0 ################################## # ALLOWED TOPICS @@ -43,7 +43,7 @@ participants: # This configuration example configures a DDS Router to listen to every message published in two different domains # and transmit those messages through the other domain. -# 0: Use YAML configuration version v2.0 +# 0: Use YAML configuration version v3.0 # 1: Allow DDS Topic Name with type . diff --git a/resources/configurations/examples/echo.yaml b/resources/configurations/examples/echo.yaml index f4bc4e801..77e75bae3 100644 --- a/resources/configurations/examples/echo.yaml +++ b/resources/configurations/examples/echo.yaml @@ -4,7 +4,7 @@ ################################## # CONFIGURATION VERSION -version: v2.0 # 0 +version: v3.0 # 0 ################################## # ALLOWED TOPICS @@ -43,7 +43,7 @@ participants: # HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to print the received # messages in stdout. -# 0: Use YAML configuration version v2.0 +# 0: Use YAML configuration version v3.0 # 1: Allow DDS Topic Name with type . diff --git a/resources/configurations/examples/repeater.yaml b/resources/configurations/examples/repeater.yaml new file mode 100644 index 000000000..ee5ae9121 --- /dev/null +++ b/resources/configurations/examples/repeater.yaml @@ -0,0 +1,59 @@ +###################### +# WAN SERVER EXAMPLE # +###################### + +################################## +# CONFIGURATION VERSION +version: v3.0 # 0 + +################################## +# ALLOWED TOPICS +# Allowing FastDDS and ROS2 HelloWorld demo examples topics + +allowlist: + - name: HelloWorldTopic # 1 + type: HelloWorld # 1 + - name: rt/chatter # 2 + type: std_msgs::msg::dds_::String_ + +################################## +# PARTICIPANTS +participants: + +################################## +# WAN SERVER REPEATER +# This participant will repeat the messages that arrive to it. + + - name: RepeaterParticipant # 3 + kind: wan # 4 + repeater: true # 5 + listening-addresses: # 6 + - ip: 1.1.1.1 + port: 11666 + transport: tcp + +################################## +# CONFIGURATION DESCRIPTION + +# This configuration example configures a DDS Router to listen to every message published in domain 0 in topics +# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages +# through a WAN Participant (configured as Server) to another WAN Participant. +# The other direction of communication is also possible; receive messages at the WAN Participant and locally +# publish them in domain 0. +# Server specifies which DDS Router starts the communication with the other, and after communication has been +# established, both routers behave in the same way. + +# 0: Use YAML configuration version v3.0 + +# 1: Allow DDS Topic Name with type . + +# 2: Insert new topics in order to route them. + +# 3: New Participant with name . + +# 4: Kind of RepeaterParticipant: . +# WAN communication with other DDS Routers. + +# 5: RepeaterParticipant will repeat messages that arrive to it to the rest of DDS Routers connected. + +# 6: Addresses where this Repeater will be listening to WAN participants diff --git a/resources/configurations/examples/ros_discovery_client.yaml b/resources/configurations/examples/ros_discovery_client.yaml index 9f5058722..d7e1b6fa1 100644 --- a/resources/configurations/examples/ros_discovery_client.yaml +++ b/resources/configurations/examples/ros_discovery_client.yaml @@ -4,7 +4,7 @@ ################################## # CONFIGURATION VERSION -version: v2.0 # 0 +version: v3.0 # 0 ################################## # ALLOWED TOPICS @@ -53,7 +53,7 @@ participants: # The other direction of communication is also possible; receive messages at the Discovery Server and locally # publish them in domain 0. -# 0: Use YAML configuration version v2.0 +# 0: Use YAML configuration version v3.0 # 1: Allow ROS 2 specific Topic Name with type . # Insert new topics in order to route them. diff --git a/resources/configurations/examples/ros_discovery_server.yaml b/resources/configurations/examples/ros_discovery_server.yaml index 3ef337fd6..35d019825 100644 --- a/resources/configurations/examples/ros_discovery_server.yaml +++ b/resources/configurations/examples/ros_discovery_server.yaml @@ -4,7 +4,7 @@ ################################## # CONFIGURATION VERSION -version: v2.0 # 0 +version: v3.0 # 0 ################################## # ALLOWED TOPICS @@ -49,7 +49,7 @@ participants: # The other direction of communication is also possible; receive messages at the Discovery Server and locally # publish them in domain 0. -# 0: Use YAML configuration version v2.0 +# 0: Use YAML configuration version v3.0 # 1: Allow DDS ROS 2 specific Topic Name with type . # Insert new topics in order to route them. diff --git a/resources/configurations/examples/wan_client.yaml b/resources/configurations/examples/wan_client.yaml index ca3cec999..6d88f51d5 100644 --- a/resources/configurations/examples/wan_client.yaml +++ b/resources/configurations/examples/wan_client.yaml @@ -4,7 +4,7 @@ ################################## # CONFIGURATION VERSION -version: v2.0 # 0 +version: v3.0 # 0 ################################## # ALLOWED TOPICS @@ -29,23 +29,17 @@ participants: domain: 1 # 5 ################################## -# WAN CLIENT -# This participant will subscribe to topics in allowlist using Discovery Server protocol as SuperClient. +# INITIAL PEERS CLIENT +# This participant will subscribe to topics in allowlist using Initial Peers Discovery protocol connecting to remote. - - name: WANClient # 6 + - name: WanParticipant # 6 kind: wan # 7 - discovery-server-guid: - id: 2 # 8 - connection-addresses: # 9 - - discovery-server-guid: - id: 1 # 10 - addresses: # 11 - - ip: 1.1.1.1 - port: 11666 - listening-addresses: # 12 - - ip: 2.2.2.2 # 13 - port: 11670 # 14 - transport: udp # 15 + connection-addresses: # 8 + - ip: 1.1.1.1 + port: 12666 + listening-addresses: # 9 + - ip: 2.2.2.2 + port: 12670 ################################## # CONFIGURATION DESCRIPTION @@ -58,7 +52,7 @@ participants: # Client specifies which DDS Router starts the communication with the other, and after communication has been # established, both routers behave in the same way. -# 0: Use YAML configuration version v2.0 +# 0: Use YAML configuration version v3.0 # 1: Allow DDS Topic Name with type . @@ -71,31 +65,13 @@ participants: # 5: SimpleParticipant will use DDS Domain ID <1>. -# 6: New Participant with name . +# 6: New Participant with name . # 7: Kind of WANClient: . -# WAN communication with another DDS Router. +# InitialPeers discovery to discover and communicate with another WAN DDS Router. -# 8: Set the Discovery Server GuidPrefix to <01.0f.02.00.00.00.00.00.00.00.ca.fe> for WANClient. - -# 9: Add the addresses where to reach the remote DDS Routers that will connect to. +# 8: Add the connection addresses where to reach the remote DDS Routers to connect with_ +# In this case using localhost (127.0.0.1) port 12666 (UDP by default). # Add as many connection-addresses as needed. -# 10: Set the Remote Discovery Server GuidPrefix to <01.0f.01.00.00.00.00.00.00.00.ca.fe>. - -# 11: Connect to a Discovery Server in IP <1.1.1.1> listening in port 11666 over UDP transport (default). -# This is the same configuration that must be set in the DDS Router that works as a Server in its listening-addresses. -# Add every other address where trying to reach this same remote WAN Discovery Server. - -# 12: Add the interfaces where this Participant will listen in WAN. -# This is only needed if Remote WAN Server is using only UDP. -# Add as many listening-addresses as needed. - -# 13: Listen in public IP (2.2.2.2) for remote traffic. -# This IP must be set to the public IP of the host where this DDS Router will run. - -# 14: Listening port is 11670. -# Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network -# router to this host to the same port. - -# 15: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". +# 9: In case of using UDP in WAN, at least one listening address is required diff --git a/resources/configurations/examples/wan_ds_client.yaml b/resources/configurations/examples/wan_ds_client.yaml new file mode 100644 index 000000000..f5a6301d1 --- /dev/null +++ b/resources/configurations/examples/wan_ds_client.yaml @@ -0,0 +1,101 @@ +###################### +# WAN CLIENT EXAMPLE # +###################### + +################################## +# CONFIGURATION VERSION +version: v3.0 # 0 + +################################## +# ALLOWED TOPICS +# Allowing FastDDS and ROS2 HelloWorld demo examples topics + +allowlist: + - name: HelloWorldTopic # 1 + type: HelloWorld # 1 + - name: rt/chatter # 2 + type: std_msgs::msg::dds_::String_ + +################################## +# PARTICIPANTS +participants: + +################################## +# SIMPLE PARTICIPANT +# This participant will subscribe to topics in allowlist in domain 1 and listen every message published there + + - name: SimpleParticipant # 3 + kind: local # 4 + domain: 1 # 5 + +################################## +# WAN CLIENT +# This participant will subscribe to topics in allowlist using Discovery Server protocol as SuperClient. + + - name: WANClient # 6 + kind: wan-discovery-server # 7 + discovery-server-guid: + id: 2 # 8 + connection-addresses: # 9 + - discovery-server-guid: + id: 1 # 10 + addresses: # 11 + - ip: 1.1.1.1 + port: 11666 + listening-addresses: # 12 + - ip: 2.2.2.2 # 13 + port: 11670 # 14 + transport: udp # 15 + +################################## +# CONFIGURATION DESCRIPTION + +# This configuration example configures a DDS Router to listen to every message published in domain 1 in topics +# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages +# through a WAN Participant (configured as Super Client) to another WAN Participant. +# The other direction of communication is also possible; receive messages at the WAN Participant and locally +# publish them in domain 1. +# Client specifies which DDS Router starts the communication with the other, and after communication has been +# established, both routers behave in the same way. + +# 0: Use YAML configuration version v3.0 + +# 1: Allow DDS Topic Name with type . + +# 2: Insert new topics in order to route them. + +# 3: New Participant with name . + +# 4: Kind of SimpleParticipant: . +# LAN UDP communication with default simple multicast discovery. + +# 5: SimpleParticipant will use DDS Domain ID <1>. + +# 6: New Participant with name . + +# 7: Kind of WANClient: . +# WAN communication with another DDS Router via Discovery Server. + +# 8: Set the Discovery Server GuidPrefix to <01.0f.02.00.00.00.00.00.00.00.ca.fe> for WANClient. + +# 9: Add the addresses where to reach the remote DDS Routers that will connect to. +# Add as many connection-addresses as needed. + +# 10: Set the Remote Discovery Server GuidPrefix to <01.0f.01.00.00.00.00.00.00.00.ca.fe>. + +# 11: Connect to a Discovery Server in IP <1.1.1.1> listening in port 11666 over UDP transport (default). +# This is the same configuration that must be set in the DDS Router that works as a Server in its listening-addresses. +# Add every other address where trying to reach this same remote WAN Discovery Server. + +# 12: Add the interfaces where this Participant will listen in WAN. +# This is only needed if Remote WAN Server is using only UDP. +# Add as many listening-addresses as needed. + +# 13: Listen in public IP (2.2.2.2) for remote traffic. +# This IP must be set to the public IP of the host where this DDS Router will run. + +# 14: Listening port is 11670. +# Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network +# router to this host to the same port. + +# 15: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/resources/configurations/examples/wan_ds_server.yaml b/resources/configurations/examples/wan_ds_server.yaml new file mode 100644 index 000000000..62d8fa4b9 --- /dev/null +++ b/resources/configurations/examples/wan_ds_server.yaml @@ -0,0 +1,86 @@ +###################### +# WAN SERVER EXAMPLE # +###################### + +################################## +# CONFIGURATION VERSION +version: v3.0 # 0 + +################################## +# ALLOWED TOPICS +# Allowing FastDDS and ROS2 HelloWorld demo examples topics + +allowlist: + - name: HelloWorldTopic # 1 + type: HelloWorld # 1 + - name: rt/chatter # 2 + type: std_msgs::msg::dds_::String_ + +################################## +# PARTICIPANTS +participants: + +################################## +# SIMPLE PARTICIPANT +# This participant will subscribe to topics in allowlist in domain 0 and listen every message published there + + - name: SimpleParticipant # 3 + kind: local # 4 + domain: 0 # 5 + +################################## +# WAN SERVER +# This participant will subscribe to topics in allowlist using Discovery Server protocol as Server + + - name: WANServer # 6 + kind: wan-discovery-server # 7 + discovery-server-guid: + id: 1 # 8 + listening-addresses: # 9 + - ip: 1.1.1.1 # 10 + port: 11666 # 11 + transport: udp # 12 + +################################## +# CONFIGURATION DESCRIPTION + +# This configuration example configures a DDS Router to listen to every message published in domain 0 in topics +# HelloWorldTopic (from Fast DDS HelloWorld) and rt/chatter from ROS2 demo_nodes, and to transmit these messages +# through a WAN Participant (configured as Server) to another WAN Participant. +# The other direction of communication is also possible; receive messages at the WAN Participant and locally +# publish them in domain 0. +# Server specifies which DDS Router starts the communication with the other, and after communication has been +# established, both routers behave in the same way. + +# 0: Use YAML configuration version v3.0 + +# 1: Allow DDS Topic Name with type . + +# 2: Insert new topics in order to route them. + +# 3: New Participant with name . + +# 4: Kind of SimpleParticipant: . +# LAN UDP communication with default simple multicast discovery. + +# 5: SimpleParticipant will use DDS Domain ID <0>. + +# 6: New Participant with name . + +# 7: Kind of WANClient: . +# WAN communication with another DDS Router via Discovery Server. + +# 8: Set this Discovery Server GuidPrefix to <01.0f.01.00.00.00.00.00.00.00.ca.fe> for WANServer. +# This GuidPrefix is needed in order from a remote DDS Router to connect with this one. + +# 9: Add the interfaces where this Participant will listen in WAN. +# Add as many listening-addresses as needed. + +# 10: Listen in public IP (1.1.1.1) for remote traffic. +# This IP must be set to the public IP of the host where this DDS Router will run. + +# 11: Listening port is 11666. +# Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network +# router to this host to the same port. + +# 12: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/resources/configurations/examples/wan_server.yaml b/resources/configurations/examples/wan_server.yaml index 87e1b1c19..90665a7a2 100644 --- a/resources/configurations/examples/wan_server.yaml +++ b/resources/configurations/examples/wan_server.yaml @@ -4,7 +4,7 @@ ################################## # CONFIGURATION VERSION -version: v2.0 # 0 +version: v3.0 # 0 ################################## # ALLOWED TOPICS @@ -30,16 +30,13 @@ participants: ################################## # WAN SERVER -# This participant will subscribe to topics in allowlist using Discovery Server protocol as Server +# This participant will subscribe to topics in allowlist using Initial Peers Discovery protocol awaiting connections. - - name: WANServer # 6 + - name: WanParticipant # 6 kind: wan # 7 - discovery-server-guid: - id: 1 # 8 - listening-addresses: # 9 - - ip: 1.1.1.1 # 10 - port: 11666 # 11 - transport: udp # 12 + listening-addresses: # 8 + - ip: 1.1.1.1 + port: 12666 ################################## # CONFIGURATION DESCRIPTION @@ -52,7 +49,7 @@ participants: # Server specifies which DDS Router starts the communication with the other, and after communication has been # established, both routers behave in the same way. -# 0: Use YAML configuration version v2.0 +# 0: Use YAML configuration version v3.0 # 1: Allow DDS Topic Name with type . @@ -65,22 +62,11 @@ participants: # 5: SimpleParticipant will use DDS Domain ID <0>. -# 6: New Participant with name . +# 6: New Participant with name . -# 7: Kind of WANServer: . -# WAN communication with another DDS Router. +# 7: Kind of WANClient: . +# InitialPeers discovery to discover and communicate with another WAN DDS Router. -# 8: Set this Discovery Server GuidPrefix to <01.0f.01.00.00.00.00.00.00.00.ca.fe> for WANServer. -# This GuidPrefix is needed in order from a remote DDS Router to connect with this one. - -# 9: Add the interfaces where this Participant will listen in WAN. +# 8: Add the listening addresses where this DDS Routers will be available +# In this case using localhost (127.0.0.1) port 12666 (UDP by default). # Add as many listening-addresses as needed. - -# 10: Listen in public IP (1.1.1.1) for remote traffic. -# This IP must be set to the public IP of the host where this DDS Router will run. - -# 11: Listening port is 11666. -# Remember that if the host is under a NAT, the IP must be the public one and must be forwarded from network -# router to this host to the same port. - -# 12: It uses UDP transport by default if not set. Could be set to "udp" or "tcp". diff --git a/tools/ddsrouter_tool/test/application/CMakeLists.txt b/tools/ddsrouter_tool/test/application/CMakeLists.txt index 7a0c9b897..d0fd41d95 100644 --- a/tools/ddsrouter_tool/test/application/CMakeLists.txt +++ b/tools/ddsrouter_tool/test/application/CMakeLists.txt @@ -23,9 +23,11 @@ set(TEST_CONFIGURATIONS void_configuration simple_configuration ds_configuration - complex_configuration default_version_configuration v1_configuration + complex_configuration_v1 + complex_configuration_v2 + complex_configuration_v3 ) # Whether one or other signal in test diff --git a/tools/ddsrouter_tool/test/application/configurations/complex_configuration_v1.yaml b/tools/ddsrouter_tool/test/application/configurations/complex_configuration_v1.yaml new file mode 100644 index 000000000..4a4a4a213 --- /dev/null +++ b/tools/ddsrouter_tool/test/application/configurations/complex_configuration_v1.yaml @@ -0,0 +1,33 @@ + +# 1 Echo Participant +# 2 Simple Participants in domains 0 and 1 +# 1 Local Discovery Server Participant with listening address +# 1 WAN Participant with connection address +# 2 topics, one with key and one without + + +version: v1.0 + +participant1: + type: "echo" + +participant2: + type: "discovery-server" + id: 3 + ros-discovery-server: true + connection-addresses: + - guid: "01.0f.00.00.00.00.00.00.00.00.00.00" + addresses: + - ip: 127.0.0.1 + port: 3333 + +simple_participant: + type: simple + domain: 1 + +wan: + type: wan + id: 2 + listening-addresses: + - ip: 127.0.0.1 + port: 3334 diff --git a/tools/ddsrouter_tool/test/application/configurations/complex_configuration.yaml b/tools/ddsrouter_tool/test/application/configurations/complex_configuration_v2.yaml similarity index 100% rename from tools/ddsrouter_tool/test/application/configurations/complex_configuration.yaml rename to tools/ddsrouter_tool/test/application/configurations/complex_configuration_v2.yaml diff --git a/tools/ddsrouter_tool/test/application/configurations/complex_configuration_v3.yaml b/tools/ddsrouter_tool/test/application/configurations/complex_configuration_v3.yaml new file mode 100644 index 000000000..2f3b87641 --- /dev/null +++ b/tools/ddsrouter_tool/test/application/configurations/complex_configuration_v3.yaml @@ -0,0 +1,57 @@ + +# 1 Echo Participant +# 2 Simple Participants in domains 0 and 1 +# 1 Local Discovery Server Participant with listening address +# 1 WAN DS Participant with connection address +# 1 Initial Peers repeater Participant with connection and listening addresses +# 2 topics, one with key and one without + +version: v3.0 + +builtin-topics: + - name: "rt/chatter" + type: "std_msgs::msg::dds_::String_" + - name: "rt/chatter/key" + type: "std_msgs::msg::dds_::String_" + keyed: true + +participants: + + - name: simple_0 + kind: simple + domain: 0 + + - name: simple_1 + kind: simple + domain: 1 + + - name: local-ds + kind: local-discovery-server + discovery-server-guid: + id: 0 + listening-addresses: + - ip: "127.0.0.1" + port: 11666 + + - name: wan + kind: wan-ds + discovery-server-guid: + id: 1 + connection-addresses: + - discovery-server-guid: + id: 2 + addresses: + - ip: "127.0.0.1" + port: 11667 + transport: tcp + + - name: initial-peers + kind: router + repeater: true + connection-addresses: + - ip: "127.0.0.1" + port: 11668 + transport: tcp + listening-addresses: + - ip: "127.0.0.1" + port: 11669 diff --git a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/ddsrouter_config_schema.json b/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/ddsrouter_config_schema.json index 199445822..81049ae72 100644 --- a/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/ddsrouter_config_schema.json +++ b/tools/ddsrouter_yaml_validator/ddsrouter_yaml_validator/ddsrouter_config_schema.json @@ -12,7 +12,7 @@ "version":{ "type":"string", "enum":[ - "v2.0" + "v3.0" ] }, "allowlist":{ @@ -35,7 +35,7 @@ }, "participants":{ "type":"array", - "minItems":2, + "minItems":1, "items":{ "$ref":"#/definitions/Participant" }, @@ -111,6 +111,8 @@ "ds", "local-ds", "local-discovery-server", + "wan-ds", + "wan-discovery-server", "wan", "router" ] @@ -120,6 +122,9 @@ "minimum":0, "maximum":230 }, + "repeater":{ + "type":"boolean" + }, "discovery-server-guid":{ "$ref":"#/definitions/DiscoveryServerGUID" }, @@ -133,7 +138,14 @@ "connection-addresses":{ "type":"array", "items":{ - "$ref":"#/definitions/ConnectionAddress" + "anyOf":[ + { + "$ref":"#/definitions/DsConnectionAddress" + }, + { + "$ref":"#/definitions/Address" + } + ] }, "minItems": 1 }, @@ -184,6 +196,11 @@ "tls":{ "not":{ + } + }, + "repeater":{ + "not":{ + } } } @@ -213,6 +230,11 @@ "tls":{ "not":{ + } + }, + "repeater":{ + "not":{ + } } } @@ -230,8 +252,8 @@ "ds", "local-ds", "local-discovery-server", - "wan", - "router" + "wan-ds", + "wan-discovery-server" ] } } @@ -268,6 +290,46 @@ } ] } + }, + { + "if":{ + "properties":{ + "kind":{ + "type":"string", + "enum":[ + "wan", + "router" + ] + } + } + }, + "then":{ + "allOf":[ + { + "properties":{ + "discovery-server-guid":{ + "not":{ + + } + } + } + }, + { + "anyOf":[ + { + "required":[ + "listening-addresses" + ] + }, + { + "required":[ + "connection-addresses" + ] + } + ] + } + ] + } } ], "title":"Participant" @@ -300,7 +362,7 @@ ], "title":"DiscoveryServerGUID" }, - "ConnectionAddress":{ + "DsConnectionAddress":{ "type":"object", "additionalProperties":false, "properties":{ @@ -318,7 +380,7 @@ "addresses", "discovery-server-guid" ], - "title":"ConnectionAddress" + "title":"DsConnectionAddress" }, "TLS":{ "type":"object", diff --git a/tools/ddsrouter_yaml_validator/tests/ddsrouter_yaml_validator_test.py b/tools/ddsrouter_yaml_validator/tests/ddsrouter_yaml_validator_test.py index 4293ef31d..9210ccac7 100644 --- a/tools/ddsrouter_yaml_validator/tests/ddsrouter_yaml_validator_test.py +++ b/tools/ddsrouter_yaml_validator/tests/ddsrouter_yaml_validator_test.py @@ -37,7 +37,10 @@ def test_valid_yamls(): """Assert given configuration files are valid.""" validator = YamlValidator() for valid_files_dir in VALID_CONFIGURATION_FILES: - assert validator.validate(valid_files_dir, SCHEMA_PATH, logout=False) + for root, dirs, files in os.walk(valid_files_dir): + for file in files: + file_path = os.path.join(root, file) + assert validator.validate(file_path, SCHEMA_PATH, logout=False), 'Test error: ' + file_path def test_invalid_yamls(): @@ -45,4 +48,4 @@ def test_invalid_yamls(): validator = YamlValidator() for invalid_files_dir in INVALID_CONFIGURATION_FILES: assert not validator.validate( - invalid_files_dir, SCHEMA_PATH, logout=False) + invalid_files_dir, SCHEMA_PATH, logout=False), 'Negative test error: ' + invalid_files_dir diff --git a/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/initial_peers_no_addresses.yaml b/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/initial_peers_no_addresses.yaml new file mode 100644 index 000000000..af1fa2d45 --- /dev/null +++ b/tools/ddsrouter_yaml_validator/tests/invalid_configuration_files/initial_peers_no_addresses.yaml @@ -0,0 +1,16 @@ +version: v2.0 + +allowlist: + - name: HelloWorldTopic + type: HelloWorld + - name: rt/chatter + type: std_msgs::msg::dds_::String_ + + +participants: + + - name: EchoParticipant + kind: echo + + - name: ip_participant + kind: initial-peers