diff --git a/dds/DCPS/NetworkResource.cpp b/dds/DCPS/NetworkResource.cpp index eebb6c39c0e..58949cffc93 100644 --- a/dds/DCPS/NetworkResource.cpp +++ b/dds/DCPS/NetworkResource.cpp @@ -1,16 +1,15 @@ /* - * - * * Distributed under the OpenDDS License. * See: http://www.opendds.org/license.html */ -#include "DCPS/DdsDcps_pch.h" //Only the _pch include should start with DCPS/ +#include // Only the _pch include should start with DCPS/ #include "NetworkResource.h" #include "LogAddr.h" #include "TimeTypes.h" +#include "debug.h" #include #include @@ -435,6 +434,29 @@ bool set_socket_multicast_ttl(const ACE_SOCK_Dgram& socket, const unsigned char& return true; } +bool set_recvpktinfo(ACE_SOCK_Dgram& sock, bool ipv4) +{ + bool success = true; +#if defined ACE_RECVPKTINFO || defined ACE_RECVPKTINFO6 + if (ipv4) { +# ifdef ACE_RECVPKTINFO + success = set_sock_opt(sock, IPPROTO_IP, ACE_RECVPKTINFO, 1); +# endif + } else { +# ifdef ACE_RECVPKTINFO6 + success = set_sock_opt(sock, IPPROTO_IPV6, ACE_RECVPKTINFO6, 1); +# endif + } + if (!success && log_level >= LogLevel::Error) { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: set_recvpktinfo: failed to set RECVPKTINFO: %m\n")); + } +# else + ACE_UNUSED_ARG(sock); + ACE_UNUSED_ARG(ipv4); +# endif + return success; +} + bool open_appropriate_socket_type(ACE_SOCK_Dgram& socket, const ACE_INET_Addr& local_address, int* proto_family) { #if defined (ACE_HAS_IPV6) && defined (IPV6_V6ONLY) diff --git a/dds/DCPS/NetworkResource.h b/dds/DCPS/NetworkResource.h index 539bf79cd71..214a698afd4 100644 --- a/dds/DCPS/NetworkResource.h +++ b/dds/DCPS/NetworkResource.h @@ -88,6 +88,19 @@ void get_interface_addrs(OPENDDS_VECTOR(ACE_INET_Addr)& addrs); extern OpenDDS_Dcps_Export bool set_socket_multicast_ttl(const ACE_SOCK_Dgram& socket, const unsigned char& ttl); +template +bool set_sock_opt(ACE_SOCK_Dgram& sock, + int level, int option, T value, bool ignore_notsup = false) +{ + if (sock.set_option(level, option, (void*) &value, sizeof(T)) < 0) { + return ignore_notsup && errno == ENOTSUP; + } + return true; +} + +OpenDDS_Dcps_Export +bool set_recvpktinfo(ACE_SOCK_Dgram& sock, bool ipv4); + /// Helper function to create dual stack socket to support IPV4 and IPV6, /// for IPV6 builds allows for setting IPV6_V6ONLY socket option to 0 before binding /// Otherwise defaults to opening a socket based on the type of local_address diff --git a/dds/DCPS/RTPS/MessageUtils.cpp b/dds/DCPS/RTPS/MessageUtils.cpp index 6802fd9fce9..13a805c3504 100644 --- a/dds/DCPS/RTPS/MessageUtils.cpp +++ b/dds/DCPS/RTPS/MessageUtils.cpp @@ -145,14 +145,15 @@ bool get_rtps_port(DDS::UInt16& port_result, const char* what, { const DDS::UInt32 port = static_cast(port_base) + domain * domain_gain + part * part_gain + offset; - ACE_DEBUG((LM_DEBUG, "HERE %C %u + %u * %u + %u * %u + %u = %u\n", what, port_base, domain, domain_gain, part, part_gain, offset, port)); + port_result = static_cast(port); if (port > 65535) { - if (log_level >= LogLevel::Error) { - ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: rtps_port: %C port %u is too high\n", what, port)); + if (log_level >= LogLevel::Warning) { + ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: rtps_port: " + "%C port %u is going to be truncated to %u. This behavior is deprecated, please reduce " + "domain ID or other RTPS port parameters.\n", + what, port, port_result)); } - return false; } - port_result = static_cast(port); return true; } diff --git a/dds/DCPS/RTPS/Sedp.cpp b/dds/DCPS/RTPS/Sedp.cpp index 6f64c38492c..49f66f6d44e 100644 --- a/dds/DCPS/RTPS/Sedp.cpp +++ b/dds/DCPS/RTPS/Sedp.cpp @@ -417,6 +417,7 @@ Sedp::init(const GUID_t& guid, DCPS::TransportRegistry::DEFAULT_INST_PREFIX + OPENDDS_STRING("_SEDPTransportInst_") + key + domainStr, "rtps_udp"); + DCPS::RtpsUdpInst_rch inst = DCPS::static_rchandle_cast(transport_inst_); // Be careful to not call any function that causes the transport be // to created before the configuration is complete. @@ -454,12 +455,17 @@ Sedp::init(const GUID_t& guid, config_store_->set(transport_inst_->config_key("MULTICAST_INTERFACE").c_str(), disco.multicast_interface()); } - DCPS::NetworkAddress addr4; - if (!disco.config()->sedp_unicast_address(addr4, domainId, ipv4_participant_port_id)) { - return DDS::RETCODE_ERROR; - } + inst->port_mode(disco.config()->sedp_port_mode()); + inst->pb(disco.config()->pb()); + inst->dg(disco.config()->dg()); + inst->pg(disco.config()->pg()); + inst->d2(disco.config()->dx()); + inst->d3(disco.config()->dy()); + inst->d3(disco.config()->dy()); + + inst->init_participant_port_id(ipv4_participant_port_id); config_store_->set(transport_inst_->config_key("LOCAL_ADDRESS").c_str(), - addr4, + disco.config()->sedp_local_address(), ConfigStoreImpl::Format_Required_Port, ConfigStoreImpl::Kind_IPV4); config_store_->set(transport_inst_->config_key("ADVERTISED_ADDRESS").c_str(), @@ -467,12 +473,9 @@ Sedp::init(const GUID_t& guid, ConfigStoreImpl::Format_Required_Port, ConfigStoreImpl::Kind_IPV4); #ifdef ACE_HAS_IPV6 - DCPS::NetworkAddress addr6; - if (!disco.config()->ipv6_sedp_unicast_address(addr6, domainId, ipv6_participant_port_id)) { - return DDS::RETCODE_ERROR; - } + inst->ipv6_init_participant_port_id(ipv6_participant_port_id); config_store_->set(transport_inst_->config_key("IPV6_LOCAL_ADDRESS").c_str(), - addr6, + disco.config()->ipv6_sedp_local_address(), ConfigStoreImpl::Format_Required_Port, ConfigStoreImpl::Kind_IPV6); config_store_->set(transport_inst_->config_key("IPV6_ADVERTISED_ADDRESS").c_str(), diff --git a/dds/DCPS/RTPS/Sedp.h b/dds/DCPS/RTPS/Sedp.h index a705f75657b..a32ed0628cc 100644 --- a/dds/DCPS/RTPS/Sedp.h +++ b/dds/DCPS/RTPS/Sedp.h @@ -587,6 +587,7 @@ class Sedp : public virtual DCPS::RcEventHandler { public: Endpoint(const DCPS::GUID_t& repo_id, Sedp& sedp) : repo_id_(repo_id) + , domain_id_(sedp.get_domain_id()) , sedp_(sedp) , shutting_down_(false) #ifdef OPENDDS_SECURITY @@ -612,7 +613,7 @@ class Sedp : public virtual DCPS::RcEventHandler { DDS::DomainId_t domain_id() const { - return 0; // not used for SEDP + return domain_id_; } CORBA::Long get_priority_value(const DCPS::AssociationData&) const @@ -665,6 +666,7 @@ class Sedp : public virtual DCPS::RcEventHandler { protected: DCPS::GUID_t repo_id_; + DDS::DomainId_t domain_id_; Sedp& sedp_; AtomicBool shutting_down_; #ifdef OPENDDS_SECURITY diff --git a/dds/DCPS/RTPS/Spdp.cpp b/dds/DCPS/RTPS/Spdp.cpp index c3a16b6d596..35ba9d0d7b2 100644 --- a/dds/DCPS/RTPS/Spdp.cpp +++ b/dds/DCPS/RTPS/Spdp.cpp @@ -47,6 +47,7 @@ using DCPS::ENDIAN_LITTLE; using DCPS::LogLevel; using DCPS::log_level; using DCPS::LogAddr; +using DCPS::set_sock_opt; namespace { const Encoding encoding_plain_big(Encoding::KIND_XCDR1, ENDIAN_BIG); @@ -2384,10 +2385,7 @@ Spdp::SpdpTransport::SpdpTransport(DCPS::RcHandle outer) const DCPS::NetworkAddressSet addrs = outer->config_->spdp_send_addrs(); send_addrs_.insert(addrs.begin(), addrs.end()); -#ifdef OPENDDS_SAFETY_PROFILE const DDS::UInt16 startingParticipantId = outer->ipv4_participant_port_id_; -#endif - const DDS::UInt16 max_part_id = 119; // RTPS 2.5 9.6.2.3 while (!open_unicast_socket(outer->ipv4_participant_port_id_)) { if (outer->ipv4_participant_port_id_ == max_part_id && log_level >= LogLevel::Warning) { @@ -2399,12 +2397,18 @@ Spdp::SpdpTransport::SpdpTransport(DCPS::RcHandle outer) // could use this as a hard limit, but that's much less of a concern. } ++outer->ipv4_participant_port_id_; + if (outer->ipv4_participant_port_id_ == startingParticipantId) { + throw std::runtime_error("could not find a free IPv4 unicast port for SPDP"); + } } #ifdef ACE_HAS_IPV6 outer->ipv6_participant_port_id_ = outer->ipv4_participant_port_id_; while (!open_unicast_ipv6_socket(outer->ipv6_participant_port_id_)) { ++outer->ipv6_participant_port_id_; + if (outer->ipv4_participant_port_id_ == outer->ipv6_participant_port_id_) { + throw std::runtime_error("could not find a free IPv6 unicast port for SPDP"); + } } #endif @@ -3447,18 +3451,6 @@ Spdp::SpdpTransport::open_unicast_socket(DDS::UInt16 participant_id) return true; } -namespace { - template - bool set_sock_opt(ACE_SOCK_Dgram& sock, - int level, int option, T value, bool ignore_notsup = false) - { - if (sock.set_option(level, option, (void*) &value, sizeof(T)) < 0) { - return ignore_notsup && errno == ENOTSUP; - } - return true; - } -} - void Spdp::SpdpTransport::set_unicast_socket_opts( DCPS::RcHandle& outer, ACE_SOCK_Dgram& sock, DDS::UInt16& port) { @@ -3467,18 +3459,13 @@ void Spdp::SpdpTransport::set_unicast_socket_opts( throw std::runtime_error("failed to get address from socket"); } port = addr.get_port_number(); - const bool ipv6 = -#ifdef ACE_HAS_IPV6 - addr.get_type () == AF_INET6; -#else - false; -#endif + const bool ipv4 = addr.get_type () == AF_INET; if (DCPS::DCPS_debug_level > 3) { ACE_DEBUG((LM_DEBUG, "(%P|%t) Spdp::SpdpTransport::set_unicast_socket_opts: " "opened %C unicast socket %d on port %d\n", - ipv6 ? "IPv6" : "IPv4", sock.get_handle(), port)); + ipv4 ? "IPv4" : "IPv6", sock.get_handle(), port)); } if (!DCPS::set_socket_multicast_ttl(sock, outer->config_->ttl())) { @@ -3509,21 +3496,7 @@ void Spdp::SpdpTransport::set_unicast_socket_opts( throw std::runtime_error("failed to set recv buffer size"); } - bool success = true; - if (ipv6) { -#ifdef ACE_RECVPKTINFO6 - success = set_sock_opt(sock, IPPROTO_IPV6, ACE_RECVPKTINFO6, 1); -#endif - } else { -#ifdef ACE_RECVPKTINFO - success = set_sock_opt(sock, IPPROTO_IP, ACE_RECVPKTINFO, 1); -#endif - } - if (!success) { - if (log_level >= LogLevel::Error) { - ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: Spdp::SpdpTransport::set_unicast_socket_opts: " - "failed to set RECVPKTINFO: %m\n")); - } + if (!DCPS::set_recvpktinfo(sock, ipv4)) { throw std::runtime_error("failed to set RECVPKTINFO"); } } diff --git a/dds/DCPS/transport/framework/TransportInst.cpp b/dds/DCPS/transport/framework/TransportInst.cpp index 50013b16f97..ac3f4467ae0 100644 --- a/dds/DCPS/transport/framework/TransportInst.cpp +++ b/dds/DCPS/transport/framework/TransportInst.cpp @@ -287,23 +287,23 @@ TransportInst::get_or_create_impl(DDS::DomainId_t domain, { ACE_GUARD_RETURN(ACE_SYNCH_MUTEX, g, lock_, TransportImpl_rch()); - // Only use the domain if the inst is a template. + // Only use the domain to find the impl is if this inst is a template. // Furthermore, only use the client if the instantiation rule is per_participant. - + DDS::DomainId_t find_domain = domain; if (is_template_) { if (instantiation_rule() != "per_participant") { participant = 0; } } else { - domain = 0; + find_domain = 0; participant = 0; } if (!shutting_down_) { try { - DomainMap::iterator pos = domain_map_.find(domain); + DomainMap::iterator pos = domain_map_.find(find_domain); if (pos == domain_map_.end()) { - pos = domain_map_.insert(std::make_pair(domain, ParticipantMap())).first; + pos = domain_map_.insert(std::make_pair(find_domain, ParticipantMap())).first; } ParticipantMap::iterator pos2 = pos->second.find(participant); if (pos2 == pos->second.end()) { diff --git a/dds/DCPS/transport/rtps_udp/RtpsUdpInst.cpp b/dds/DCPS/transport/rtps_udp/RtpsUdpInst.cpp index 122a09ba2b5..a965d753c64 100644 --- a/dds/DCPS/transport/rtps_udp/RtpsUdpInst.cpp +++ b/dds/DCPS/transport/rtps_udp/RtpsUdpInst.cpp @@ -1,12 +1,11 @@ /* - * - * * Distributed under the OpenDDS License. * See: http://www.opendds.org/license.html */ -#include "RtpsSampleHeader.h" #include "RtpsUdpInst.h" + +#include "RtpsSampleHeader.h" #include "RtpsUdpLoader.h" #include "RtpsUdpTransport.h" #include "RtpsUdpSendStrategy.h" @@ -235,6 +234,86 @@ RtpsUdpInst::send_delay() const ConfigStoreImpl::Format_IntegerMilliseconds); } +RTPS::PortMode RtpsUdpInst::port_mode() const +{ + return get_port_mode(config_key("PORT_MODE"), RTPS::PortMode_System); +} + +void RtpsUdpInst::port_mode(RTPS::PortMode value) +{ + set_port_mode(config_key("PORT_MODE"), value); +} + +void RtpsUdpInst::pb(DDS::UInt16 port_base) +{ + TheServiceParticipant->config_store()->set_uint32(config_key("PB").c_str(), + port_base); +} + +DDS::UInt16 RtpsUdpInst::pb() const +{ + return TheServiceParticipant->config_store()->get_uint32(config_key("PB").c_str(), + RTPS::default_port_base); +} + +void RtpsUdpInst::dg(DDS::UInt16 domain_gain) +{ + TheServiceParticipant->config_store()->set_uint32(config_key("DG").c_str(), + domain_gain); +} + +DDS::UInt16 RtpsUdpInst::dg() const +{ + return TheServiceParticipant->config_store()->get_uint32(config_key("DG").c_str(), + RTPS::default_domain_gain); +} + +void RtpsUdpInst::pg(DDS::UInt16 participant_gain) +{ + TheServiceParticipant->config_store()->set_uint32(config_key("PG").c_str(), + participant_gain); +} + +DDS::UInt16 RtpsUdpInst::pg() const +{ + return TheServiceParticipant->config_store()->get_uint32(config_key("PG").c_str(), + RTPS::default_part_gain); +} + +void RtpsUdpInst::d2(DDS::UInt16 multicast_offset) +{ + TheServiceParticipant->config_store()->set_uint32(config_key("D2").c_str(), + multicast_offset); +} + +DDS::UInt16 RtpsUdpInst::d2() const +{ + return TheServiceParticipant->config_store()->get_uint32(config_key("D2").c_str(), + RTPS::default_user_multicast_offset); +} + +void RtpsUdpInst::d3(DDS::UInt16 unicast_offset) +{ + TheServiceParticipant->config_store()->set_uint32(config_key("D3").c_str(), + unicast_offset); +} + +DDS::UInt16 RtpsUdpInst::d3() const +{ + return TheServiceParticipant->config_store()->get_uint32(config_key("D3").c_str(), + RTPS::default_user_unicast_offset); +} + +bool RtpsUdpInst::multicast_port(DDS::UInt16& port, DDS::UInt16 domain) const +{ + return RTPS::get_rtps_port(port, "RTPS/UDP multicast", pb(), d2(), domain, dg()); +} + +bool RtpsUdpInst::unicast_port(DDS::UInt16& port, DDS::UInt16 domain, DDS::UInt16 part) const +{ + return RTPS::get_rtps_port(port, "RTPS/UDP unicast", pb(), d3(), domain, dg(), part, pg()); +} + void RtpsUdpInst::multicast_group_address(const NetworkAddress& addr) { @@ -247,10 +326,23 @@ RtpsUdpInst::multicast_group_address(const NetworkAddress& addr) NetworkAddress RtpsUdpInst::multicast_group_address(DDS::DomainId_t domain) const { - NetworkAddress na = TheServiceParticipant->config_store()->get(config_key("MULTICAST_GROUP_ADDRESS").c_str(), - NetworkAddress(7401, "239.255.0.2"), - ConfigStoreImpl::Format_Optional_Port, - ConfigStoreImpl::Kind_IPV4); + NetworkAddress addr; + return multicast_address(addr, domain) ? addr : NetworkAddress(); +} + +bool RtpsUdpInst::multicast_address(DCPS::NetworkAddress& na, DDS::DomainId_t domain) const +{ + na = TheServiceParticipant->config_store()->get(config_key("MULTICAST_GROUP_ADDRESS").c_str(), + NetworkAddress(0, "239.255.0.2"), + ConfigStoreImpl::Format_Optional_Port, + ConfigStoreImpl::Kind_IPV4); + DDS::UInt16 default_port = 0; + if (!multicast_port(default_port, domain)) { + return false; + } + if (na.get_port_number() == 0) { + na.set_port_number(default_port); + } const NetworkAddress na_original = na; if (is_template()) { @@ -275,7 +367,7 @@ RtpsUdpInst::multicast_group_address(DDS::DomainId_t domain) const "could not convert %C to integer\n", last_octet.c_str())); } - return na; + return false; } val += domain; @@ -289,10 +381,10 @@ RtpsUdpInst::multicast_group_address(DDS::DomainId_t domain) const "could not add_domain_id_to_ip_addr for address %C\n", addr.c_str())); } - return na; + return false; } - if (log_level >= LogLevel::Debug && DCPS_debug_level > 0) { + if (DCPS_debug_level > 0) { ACE_DEBUG((LM_DEBUG, "(%P|%t) DEBUG: RtpsUdpInst::multicast_group_address: " "processing add_domain_id_to_ip_addr: %C=%C => %C\n", @@ -302,17 +394,14 @@ RtpsUdpInst::multicast_group_address(DDS::DomainId_t domain) const if (directive.find("add_domain_id_to_port") != directive.npos) { if (na.get_port_number() == 0) { - // use default port + domainId. See 9.6.1.3 in the RTPS 2.2 protocol specification. - const int PB = 7400; - const int DG = 250; - const int D2 = 1; - na.set_port_number(PB + DG * domain + D2 + domain); + // use default port + domainId + na.set_port_number(default_port + domain); } else { // address has a port supplied na.set_port_number(na.get_port_number() + domain); } - if (log_level >= LogLevel::Debug && DCPS_debug_level > 0) { + if (DCPS_debug_level > 0) { ACE_DEBUG((LM_DEBUG, "(%P|%t) DEBUG: RtpsUdpInst::multicast_group_address: " "processing add_domain_id_to_port: %C=%C => %C\n", @@ -322,7 +411,19 @@ RtpsUdpInst::multicast_group_address(DDS::DomainId_t domain) const } } - return na; + return true; +} + +void RtpsUdpInst::init_participant_port_id(DDS::UInt16 part_id) +{ + TheServiceParticipant->config_store()->set_uint32(config_key("INIT_PARTICIPANT_PORT_ID").c_str(), + part_id); +} + +DDS::UInt16 RtpsUdpInst::init_participant_port_id() const +{ + return TheServiceParticipant->config_store()->get_uint32(config_key("INIT_PARTICIPANT_PORT_ID").c_str(), + 0); } void @@ -343,6 +444,21 @@ RtpsUdpInst::local_address() const ConfigStoreImpl::Kind_IPV4); } +bool RtpsUdpInst::unicast_address(DCPS::NetworkAddress& addr, bool& fixed_port, + DDS::DomainId_t domain, DDS::UInt16 part_id) const +{ + addr = local_address(); + fixed_port = addr.get_port_number() > 0; + if (!fixed_port && port_mode() == RTPS::PortMode_Probe) { + DDS::UInt16 port; + if (!unicast_port(port, domain, part_id)) { + return false; + } + addr.set_port_number(port); + } + return true; +} + void RtpsUdpInst::advertised_address(const NetworkAddress& addr) { @@ -372,12 +488,39 @@ RtpsUdpInst::ipv6_multicast_group_address(const NetworkAddress& addr) } NetworkAddress -RtpsUdpInst::ipv6_multicast_group_address() const +RtpsUdpInst::ipv6_multicast_group_address(DDS::DomainId_t domain) const { - return TheServiceParticipant->config_store()->get(config_key("IPV6_MULTICAST_GROUP_ADDRESS").c_str(), - NetworkAddress(7401, "FF03::2"), - ConfigStoreImpl::Format_Optional_Port, - ConfigStoreImpl::Kind_IPV6); + NetworkAddress addr; + return ipv6_multicast_address(addr, domain) ? addr : NetworkAddress(); +} + +bool RtpsUdpInst::ipv6_multicast_address(DCPS::NetworkAddress& addr, DDS::DomainId_t domain) const +{ + NetworkAddress addr = TheServiceParticipant->config_store()->get( + config_key("IPV6_MULTICAST_GROUP_ADDRESS").c_str(), + NetworkAddress(0, "FF03::2"), ConfigStoreImpl::Format_Optional_Port, + ConfigStoreImpl::Kind_IPV6); + + if (na.get_port_number() == 0) { + DDS::UInt16 default_port = 0; + if (!multicast_port(default_port, domain)) { + return false; + } + na.set_port_number(default_port); + } + return +} + +void RtpsUdpInst::ipv6_init_participant_port_id(DDS::UInt16 part_id) +{ + TheServiceParticipant->config_store()->set_uint32(config_key("IPV6_INIT_PARTICIPANT_PORT_ID").c_str(), + part_id); +} + +DDS::UInt16 RtpsUdpInst::ipv6_init_participant_port_id() const +{ + return TheServiceParticipant->config_store()->get_uint32(config_key("IPV6_INIT_PARTICIPANT_PORT_ID").c_str(), + 0); } void @@ -398,6 +541,21 @@ RtpsUdpInst::ipv6_local_address() const ConfigStoreImpl::Kind_IPV6); } +bool RtpsUdpInst::ipv6_unicast_address(DCPS::NetworkAddress& addr, bool& fixed_port, + DDS::DomainId_t domain, DDS::UInt16 part_id) const +{ + addr = ipv6_local_address(); + fixed_port = addr.get_port_number() > 0; + if (!fixed_port && port_mode() == RTPS::PortMode_Probe) { + DDS::UInt16 port; + if (!unicast_port(port, domain, part_id)) { + return false; + } + addr.set_port_number(port); + } + return true; +} + void RtpsUdpInst::ipv6_advertised_address(const NetworkAddress& addr) { @@ -514,7 +672,7 @@ RtpsUdpInst::dump_to_str(DDS::DomainId_t domain) const ret += formatNameForDump("local_address") + LogAddr(local_address()).str() + '\n'; ret += formatNameForDump("advertised_address") + LogAddr(advertised_address()).str() + '\n'; #ifdef ACE_HAS_IPV6 - ret += formatNameForDump("ipv6_multicast_group_address") + LogAddr(ipv6_multicast_group_address()).str() + '\n'; + ret += formatNameForDump("ipv6_multicast_group_address") + LogAddr(ipv6_multicast_group_address(domain)).str() + '\n'; ret += formatNameForDump("ipv6_local_address") + LogAddr(ipv6_local_address()).str() + '\n'; ret += formatNameForDump("ipv6_advertised_address") + LogAddr(ipv6_advertised_address()).str() + '\n'; #endif diff --git a/dds/DCPS/transport/rtps_udp/RtpsUdpInst.h b/dds/DCPS/transport/rtps_udp/RtpsUdpInst.h index e648cd2ba8e..5c39013a8a9 100644 --- a/dds/DCPS/transport/rtps_udp/RtpsUdpInst.h +++ b/dds/DCPS/transport/rtps_udp/RtpsUdpInst.h @@ -1,6 +1,4 @@ /* - * - * * Distributed under the OpenDDS License. * See: http://www.opendds.org/license.html */ @@ -14,6 +12,7 @@ #include #include #include +#include #include OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL @@ -97,21 +96,54 @@ class OpenDDS_Rtps_Udp_Export RtpsUdpInst : public TransportInst { DDS::DomainId_t domain) const; const TransportBLOB* get_blob(const OpenDDS::DCPS::TransportLocatorSeq& trans_info) const; + RTPS::PortMode port_mode() const; + void port_mode(RTPS::PortMode value); + + void pb(DDS::UInt16 port_base); + DDS::UInt16 pb() const; + + void dg(DDS::UInt16 domain_gain); + DDS::UInt16 dg() const; + + void pg(DDS::UInt16 participant_gain); + DDS::UInt16 pg() const; + + void d2(DDS::UInt16 multicast_offset); + DDS::UInt16 d2() const; + + void d3(DDS::UInt16 unicast_offset); + DDS::UInt16 d3() const; + + bool multicast_port(DDS::UInt16& port, DDS::UInt16 domain) const; + bool unicast_port(DDS::UInt16& port, DDS::UInt16 domain, DDS::UInt16 part) const; + + bool multicast_address(DCPS::NetworkAddress& addr, DDS::DomainId_t domain) const; void multicast_group_address(const NetworkAddress& addr); NetworkAddress multicast_group_address(DDS::DomainId_t domain) const; + void init_participant_port_id(DDS::UInt16 part_id); + DDS::UInt16 init_participant_port_id() const; + void local_address(const NetworkAddress& addr); NetworkAddress local_address() const; + bool unicast_address(DCPS::NetworkAddress& addr, bool& fixed_port, + DDS::DomainId_t domain, DDS::UInt16 part_id) const; void advertised_address(const NetworkAddress& addr); NetworkAddress advertised_address() const; #ifdef ACE_HAS_IPV6 + bool ipv6_multicast_address(DCPS::NetworkAddress& addr, DDS::DomainId_t domain) const; void ipv6_multicast_group_address(const NetworkAddress& addr); NetworkAddress ipv6_multicast_group_address() const; + void ipv6_init_participant_port_id(DDS::UInt16 part_id); + DDS::UInt16 ipv6_init_participant_port_id() const; + void ipv6_local_address(const NetworkAddress& addr); NetworkAddress ipv6_local_address() const; + bool ipv6_unicast_address(DCPS::NetworkAddress& addr, bool& fixed_port, + DDS::DomainId_t domain, DDS::UInt16 part_id) const; void ipv6_advertised_address(const NetworkAddress& addr); NetworkAddress ipv6_advertised_address() const; diff --git a/dds/DCPS/transport/rtps_udp/RtpsUdpTransport.cpp b/dds/DCPS/transport/rtps_udp/RtpsUdpTransport.cpp index 46686827a05..097fb6a4665 100644 --- a/dds/DCPS/transport/rtps_udp/RtpsUdpTransport.cpp +++ b/dds/DCPS/transport/rtps_udp/RtpsUdpTransport.cpp @@ -512,26 +512,41 @@ RtpsUdpTransport::append_transport_statistics(TransportStatisticsSequence& seq) core_.append_transport_statistics(seq); } -bool -RtpsUdpTransport::configure_i(const RtpsUdpInst_rch& config) +bool RtpsUdpTransport::open_socket( + const RtpsUdpInst_rch& config, ACE_SOCK_Dgram& sock, int protocol, DDS::UInt16 part_port_id, + NetworkAddress& actual, bool& fail) { - if (!config) { + fail = true; + const bool ipv4 = protocol == PF_INET; + + NetworkAddress address; + bool fixed_port; + if (ipv4) { + if (!config->unicast_address(address, fixed_port, domain_, part_port_id)) { + return false; + } +#ifdef ACE_HAS_IPV6 + } else if (!config->ipv6_unicast_address(address, fixed_port, domain_, part_port_id)) { return false; +#endif } - // Open the socket here so that any addresses/ports left - // unspecified in the RtpsUdpInst are known by the time we get to - // connection_info_i(). Opening the sockets here also allows us to - // detect and report errors during DataReader/Writer setup instead - // of during association. - - const NetworkAddress address4 = config->local_address(); - - if (unicast_socket_.open(address4.to_addr(), PF_INET) != 0) { - ACE_ERROR_RETURN((LM_ERROR, - ACE_TEXT("(%P|%t) ERROR: RtpsUdpTransport::configure_i: open4 %C: %m\n"), - LogAddr(address4).c_str()), - false); + if (sock.open(address.to_addr(), protocol) != 0) { + if (fixed_port) { + if (log_level >= LogLevel::Error) { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: RtpsUdpTransport::open_socket: " + "failed to open unicast %C socket for %C: %m\n", + ipv4 ? "IPv4" : "IPv6", LogAddr(address).c_str())); + } + } else { + if (DCPS::DCPS_debug_level > 3) { + ACE_DEBUG((LM_DEBUG, "(%P|%t) RtpsUdpTransport::open_socket: " + "failed to open unicast %C socket for %C: %m, trying next participant ID...\n", + ipv4 ? "IPv4" : "IPv6", LogAddr(address).c_str())); + } + fail = false; + } + return false; } #ifdef ACE_WIN32 @@ -542,73 +557,88 @@ RtpsUdpTransport::configure_i(const RtpsUdpInst_rch& config) // which in this case is used to receive from multiple peers. { BOOL recv_udp_connreset = FALSE; - unicast_socket_.control(SIO_UDP_CONNRESET, &recv_udp_connreset); + sock.control(SIO_UDP_CONNRESET, &recv_udp_connreset); } #endif - ACE_INET_Addr actual4; - if (unicast_socket_.get_local_addr(actual4) != 0) { - ACE_ERROR_RETURN((LM_ERROR, - ACE_TEXT("(%P|%t) ERROR: RtpsUdpTransport::configure_i: get_local_addr4 %C: %m\n"), - LogAddr(address4).c_str()), - false); + ACE_INET_Addr ace_actual; + if (sock.get_local_addr(ace_actual) != 0) { + if (log_level >= LogLevel::Error) { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: RtpsUdpTransport::open_socket: " + "failed to get actual address from %C socket for %C: %m\n", + ipv4 ? "IPv4" : "IPv6", LogAddr(address).c_str())); + } + return false; } + actual = ace_actual; - config->actual_local_address_ = NetworkAddress(actual4); - -#ifdef ACE_RECVPKTINFO - int sockopt = 1; - if (unicast_socket_.set_option(IPPROTO_IP, ACE_RECVPKTINFO, &sockopt, sizeof sockopt) == -1) { - ACE_ERROR_RETURN((LM_ERROR, - ACE_TEXT("(%P|%t) ERROR: RtpsUdpTransport::configure_i: set_option4 %C: %m\n"), - LogAddr(address4).c_str()), false); + if (!set_recvpktinfo(sock, ipv4)) { + if (log_level >= LogLevel::Error) { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: RtpsUdpTransport::open_socket: " + "failed to set RECVPKTINFO on %C socket for %C\n", + ipv4 ? "IPv4" : "IPv6", LogAddr(address).c_str())); + } + return false; } -#endif -#ifdef ACE_HAS_IPV6 - const NetworkAddress address6 = config->ipv6_local_address(); + fail = false; + return true; +} - if (ipv6_unicast_socket_.open(address6.to_addr(), PF_INET6) != 0) { - ACE_ERROR_RETURN((LM_ERROR, - ACE_TEXT("(%P|%t) ERROR: RtpsUdpTransport::configure_i: open6 %C: %m\n"), - LogAddr(address6).c_str()), - false); +bool +RtpsUdpTransport::configure_i(const RtpsUdpInst_rch& config) +{ + if (!config) { + return false; } -#ifdef ACE_WIN32 - // By default Winsock will cause reads to fail with "connection reset" - // when UDP sends result in ICMP "port unreachable" messages. - // The transport framework is not set up for this since returning <= 0 - // from our receive_bytes causes the framework to close down the datalink - // which in this case is used to receive from multiple peers. - { - BOOL recv_udp_connreset = FALSE; - ipv6_unicast_socket_.control(SIO_UDP_CONNRESET, &recv_udp_connreset); - } -#endif + // Open the socket here so that any addresses/ports left + // unspecified in the RtpsUdpInst are known by the time we get to + // connection_info_i(). Opening the sockets here also allows us to + // detect and report errors during DataReader/Writer setup instead + // of during association. - ACE_INET_Addr actual6; - if (ipv6_unicast_socket_.get_local_addr(actual6) != 0) { - ACE_ERROR_RETURN((LM_ERROR, - ACE_TEXT("(%P|%t) ERROR: RtpsUdpTransport::configure_i: get_local_addr6 %C: %m\n"), - LogAddr(address6).c_str()), - false); + bool error = false; + const DDS::UInt16 init_part_port_id4 = config->init_participant_port_id(); + DDS::UInt16 part_port_id4 = init_part_port_id4; + NetworkAddress actual4; + while (!open_socket(config, unicast_socket_, PF_INET, part_port_id4, actual4, error) && !error) { + ++part_port_id4; + if (part_port_id4 == init_part_port_id4) { + if (log_level >= LogLevel::Error) { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: RtpsUdpTransport::configure_i: " + "could not find a free IPv4 unicast port\n")); + } + return false; + } } + if (error) { + return false; + } + config->actual_local_address_ = actual4; +#ifdef ACE_HAS_IPV6 + const DDS::UInt16 init_part_port_id6 = config->ipv6_init_participant_port_id(); + DDS::UInt16 part_port_id6 = init_part_port_id6; + NetworkAddress actual6; + while (!open_socket(config, ipv6_unicast_socket_, PF_INET6, part_port_id, actual6, error) && !error) { + ++part_port_id6; + if (part_port_id6 == init_part_port_id6) { + if (log_level >= LogLevel::Error) { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: RtpsUdpTransport::configure_i: " + "could not find a free IPv6 unicast port\n")); + } + return false; + } + } + if (error) { + return false; + } NetworkAddress temp(actual6); if (actual6.is_ipv4_mapped_ipv6() && temp.is_any()) { temp = NetworkAddress(actual6.get_port_number(), "::"); } config->ipv6_actual_local_address_ = temp; - -#ifdef ACE_RECVPKTINFO6 - if (ipv6_unicast_socket_.set_option(IPPROTO_IPV6, ACE_RECVPKTINFO6, &sockopt, sizeof sockopt) == -1) { - ACE_ERROR_RETURN((LM_ERROR, - ACE_TEXT("(%P|%t) ERROR: RtpsUdpTransport::configure_i: set_option4 %C: %m\n"), - LogAddr(address6).c_str()), - false); - } -#endif #endif create_reactor_task(false, "RtpsUdpTransport" + config->name()); diff --git a/dds/DCPS/transport/rtps_udp/RtpsUdpTransport.h b/dds/DCPS/transport/rtps_udp/RtpsUdpTransport.h index b30fcd43eeb..197ea73e53d 100644 --- a/dds/DCPS/transport/rtps_udp/RtpsUdpTransport.h +++ b/dds/DCPS/transport/rtps_udp/RtpsUdpTransport.h @@ -288,6 +288,10 @@ class OpenDDS_Rtps_Udp_Export RtpsUdpTransport : public TransportImpl, public Co bool disassociate, bool association_failed); + bool open_socket( + const RtpsUdpInst_rch& config, ACE_SOCK_Dgram& sock, int protocol, DDS::UInt16 part_port_id, + NetworkAddress& actual, bool& fail); + bool configure_i(const RtpsUdpInst_rch& config); void client_stop(const GUID_t& localId); diff --git a/tests/security/ConcurrentAuthLimit/ConcurrentAuthLimit.cpp b/tests/security/ConcurrentAuthLimit/ConcurrentAuthLimit.cpp index f73b7bd66ad..5efc5107369 100644 --- a/tests/security/ConcurrentAuthLimit/ConcurrentAuthLimit.cpp +++ b/tests/security/ConcurrentAuthLimit/ConcurrentAuthLimit.cpp @@ -264,8 +264,11 @@ int ACE_TMAIN(int argc, ACE_TCHAR* argv[]) return EXIT_FAILURE; } - const u_short port_common = disc->config()->port_common(domain); - const NetworkAddress multicast_address = disc->config()->multicast_address(port_common, domain); + NetworkAddress multicast_address; + if (!disc->config()->spdp_multicast_address(multicast_address, domain)) { + ACE_ERROR((LM_ERROR, "ERROR: failed to get SPDP multicast address\n")); + return EXIT_FAILURE; + } ACE_DEBUG((LM_DEBUG, "multicast_address = %C\n", LogAddr(multicast_address).c_str())); ACE_SOCK_Dgram_Mcast multicast_socket; #ifdef ACE_HAS_MAC_OSX diff --git a/tests/unit-tests/dds/DCPS/RTPS/RtpsDiscoveryConfig.cpp b/tests/unit-tests/dds/DCPS/RTPS/RtpsDiscoveryConfig.cpp index 5964e8e627a..3c58317c493 100644 --- a/tests/unit-tests/dds/DCPS/RTPS/RtpsDiscoveryConfig.cpp +++ b/tests/unit-tests/dds/DCPS/RTPS/RtpsDiscoveryConfig.cpp @@ -82,7 +82,9 @@ TEST(dds_DCPS_RTPS_RtpsDiscoveryConfig, sedp_unicast_address) t.rtps.dy(9999); LogRestore lr; log_level.set(LogLevel::None); - ASSERT_FALSE(t.rtps.sedp_unicast_address(t.addr, 9999, 9999)); + ASSERT_TRUE(t.rtps.sedp_unicast_address(t.addr, 9999, 9999)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(29664, "0.0.0.0")); + EXPECT_FALSE(t.fixed); } { @@ -149,7 +151,9 @@ TEST(dds_DCPS_RTPS_RtpsDiscoveryConfig, spdp_unicast_address) t.rtps.d1(9999); LogRestore lr; log_level.set(LogLevel::None); - ASSERT_FALSE(t.rtps.spdp_unicast_address(t.addr, t.fixed, 9999, 9999)); + ASSERT_TRUE(t.rtps.spdp_unicast_address(t.addr, t.fixed, 9999, 9999)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(29664, "0.0.0.0")); + EXPECT_FALSE(t.fixed); } { @@ -194,7 +198,9 @@ TEST(dds_DCPS_RTPS_RtpsDiscoveryConfig, spdp_multicast_address) t.rtps.d0(9999); LogRestore lr; log_level.set(LogLevel::None); - ASSERT_FALSE(t.rtps.spdp_multicast_address(t.addr, 9999)); + ASSERT_TRUE(t.rtps.spdp_multicast_address(t.addr, 9999)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(57599, "239.255.0.1")); + EXPECT_FALSE(t.fixed); } { @@ -239,7 +245,10 @@ TEST(dds_DCPS_RTPS_RtpsDiscoveryConfig, sedp_multicast_address) t.rtps.dx(9999); LogRestore lr; log_level.set(LogLevel::None); - ASSERT_FALSE(t.rtps.sedp_multicast_address(t.addr, 9999)); + ASSERT_TRUE(t.rtps.sedp_multicast_address(t.addr, 9999)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(57599, "239.255.0.1")); + + EXPECT_FALSE(t.fixed); } { @@ -306,7 +315,9 @@ TEST(dds_DCPS_RTPS_RtpsDiscoveryConfig, ipv6_sedp_unicast_address) t.rtps.dy(9999); LogRestore lr; log_level.set(LogLevel::None); - ASSERT_FALSE(t.rtps.ipv6_sedp_unicast_address(t.addr, 9999, 9999)); + ASSERT_TRUE(t.rtps.ipv6_sedp_unicast_address(t.addr, 9999, 9999)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(29664, "[::]")); + EXPECT_FALSE(t.fixed); } { @@ -373,7 +384,9 @@ TEST(dds_DCPS_RTPS_RtpsDiscoveryConfig, ipv6_spdp_unicast_address) t.rtps.d1(9999); LogRestore lr; log_level.set(LogLevel::None); - ASSERT_FALSE(t.rtps.ipv6_spdp_unicast_address(t.addr, t.fixed, 9999, 9999)); + ASSERT_TRUE(t.rtps.ipv6_spdp_unicast_address(t.addr, t.fixed, 9999, 9999)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(29664, "[::]")); + EXPECT_FALSE(t.fixed); } { @@ -418,7 +431,9 @@ TEST(dds_DCPS_RTPS_RtpsDiscoveryConfig, ipv6_spdp_multicast_address) t.rtps.d0(9999); LogRestore lr; log_level.set(LogLevel::None); - ASSERT_FALSE(t.rtps.ipv6_spdp_multicast_address(t.addr, 9999)); + ASSERT_TRUE(t.rtps.ipv6_spdp_multicast_address(t.addr, 9999)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(57599, "[FF03::1]")); + EXPECT_FALSE(t.fixed); } { @@ -463,7 +478,9 @@ TEST(dds_DCPS_RTPS_RtpsDiscoveryConfig, ipv6_sedp_multicast_address) t.rtps.dx(9999); LogRestore lr; log_level.set(LogLevel::None); - ASSERT_FALSE(t.rtps.ipv6_sedp_multicast_address(t.addr, 9999)); + ASSERT_TRUE(t.rtps.ipv6_sedp_multicast_address(t.addr, 9999)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(57599, "[FF03::1]")); + EXPECT_FALSE(t.fixed); } { diff --git a/tests/unit-tests/dds/DCPS/transport/rtps_udp/RtpsUdpInst.cpp b/tests/unit-tests/dds/DCPS/transport/rtps_udp/RtpsUdpInst.cpp new file mode 100644 index 00000000000..f7e22f36aae --- /dev/null +++ b/tests/unit-tests/dds/DCPS/transport/rtps_udp/RtpsUdpInst.cpp @@ -0,0 +1,276 @@ +#include + +#include + +using namespace OpenDDS::RTPS; +using namespace OpenDDS::DCPS; + +namespace { + struct RtpsUdpType { + RcHandle store; + RcHandle rtps_udp; + + RtpsUdpType() + : store(make_rch(TheServiceParticipant->config_topic())) + , rtps_udp(make_rch("RTPS_UDP_INST_UNIT_TEST", false)) + { + store->unset_section(rtps_udp->config_prefix()); + } + + ~RtpsUdpType() + { + store->unset_section(rtps_udp->config_prefix()); + } + }; + + struct AddressTest : public RtpsUdpType { + NetworkAddress addr; + bool fixed; + + AddressTest() + : addr() + , fixed(false) + { + } + }; +} + +TEST(dds_DCPS_RTPS_RtpsUdpInst, multicast_address) +{ + const char* const default_addr = "239.255.0.2"; + + { + AddressTest t; + ASSERT_TRUE(t.rtps_udp->multicast_address(t.addr, 1)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(7651, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + ASSERT_TRUE(t.rtps_udp->multicast_address(t.addr, 2)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(7901, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->pb(7500); + t.rtps_udp->dg(260); + t.rtps_udp->d2(17); + ASSERT_TRUE(t.rtps_udp->multicast_address(t.addr, 1)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(7777, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->pb(9999); + t.rtps_udp->dg(9999); + t.rtps_udp->d2(9999); + LogRestore lr; + log_level.set(LogLevel::None); + ASSERT_TRUE(t.rtps_udp->multicast_address(t.addr, 9999)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(57599, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->multicast_group_address(NetworkAddress(1234, "1.2.3.4")); + ASSERT_TRUE(t.rtps_udp->multicast_address(t.addr, 1)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(1234, "1.2.3.4")); + EXPECT_FALSE(t.fixed); + } +} + +TEST(dds_DCPS_RTPS_RtpsUdpInst, unicast_address) +{ + const char* const default_addr = "0.0.0.0"; + + { + AddressTest t; + ASSERT_TRUE(t.rtps_udp->unicast_address(t.addr, t.fixed, 1, 0)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress()); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->port_mode(PortMode_System); + ASSERT_TRUE(t.rtps_udp->unicast_address(t.addr, t.fixed, 1, 0)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress()); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->port_mode(PortMode_Probe); + ASSERT_TRUE(t.rtps_udp->unicast_address(t.addr, t.fixed, 1, 0)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(7661, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->port_mode(PortMode_Probe); + ASSERT_TRUE(t.rtps_udp->unicast_address(t.addr, t.fixed, 1, 3)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(7667, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->port_mode(PortMode_Probe); + t.rtps_udp->pb(7500); + t.rtps_udp->dg(260); + t.rtps_udp->pg(3); + t.rtps_udp->d3(8); + ASSERT_TRUE(t.rtps_udp->unicast_address(t.addr, t.fixed, 1, 3)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(7777, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->port_mode(PortMode_Probe); + t.rtps_udp->pb(9999); + t.rtps_udp->dg(9999); + t.rtps_udp->pg(9999); + t.rtps_udp->d3(9999); + LogRestore lr; + log_level.set(LogLevel::None); + ASSERT_TRUE(t.rtps_udp->unicast_address(t.addr, t.fixed, 9999, 9999)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(29664, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->local_address(NetworkAddress(1234, "1.2.3.4")); + ASSERT_TRUE(t.rtps_udp->unicast_address(t.addr, t.fixed, 1, 0)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(1234, "1.2.3.4")); + EXPECT_TRUE(t.fixed); + } +} + +#ifdef ACE_HAS_IPV6 +TEST(dds_DCPS_RTPS_RtpsUdpInst, ipv6_multicast_address) +{ + const char* const default_addr = "239.255.0.2"; + + { + AddressTest t; + ASSERT_TRUE(t.rtps_udp->ipv6_multicast_address(t.addr, 1)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(7651, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + ASSERT_TRUE(t.rtps_udp->ipv6_multicast_address(t.addr, 2)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(7901, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->pb(7500); + t.rtps_udp->dg(260); + t.rtps_udp->d2(17); + ASSERT_TRUE(t.rtps_udp->ipv6_multicast_address(t.addr, 1)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(7777, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->pb(9999); + t.rtps_udp->dg(9999); + t.rtps_udp->d2(9999); + LogRestore lr; + log_level.set(LogLevel::None); + ASSERT_TRUE(t.rtps_udp->ipv6_multicast_address(t.addr, 9999)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(57599, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->multicast_group_address(NetworkAddress(1234, "[1:2:3:4]")); + ASSERT_TRUE(t.rtps_udp->ipv6_multicast_address(t.addr, 1)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(1234, "[1:2:3:4]")); + EXPECT_FALSE(t.fixed); + } +} + +TEST(dds_DCPS_RTPS_RtpsUdpInst, ipv6_unicast_address) +{ + const char* const default_addr = "[::]"; + + { + AddressTest t; + ASSERT_TRUE(t.rtps_udp->ipv6_unicast_address(t.addr, t.fixed, 1, 0)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress()); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->port_mode(PortMode_System); + ASSERT_TRUE(t.rtps_udp->ipv6_unicast_address(t.addr, t.fixed, 1, 0)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress()); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->port_mode(PortMode_Probe); + ASSERT_TRUE(t.rtps_udp->ipv6_unicast_address(t.addr, t.fixed, 1, 0)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(7661, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->port_mode(PortMode_Probe); + ASSERT_TRUE(t.rtps_udp->ipv6_unicast_address(t.addr, t.fixed, 1, 3)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(7667, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->port_mode(PortMode_Probe); + t.rtps_udp->pb(7500); + t.rtps_udp->dg(260); + t.rtps_udp->pg(3); + t.rtps_udp->d3(8); + ASSERT_TRUE(t.rtps_udp->ipv6_unicast_address(t.addr, t.fixed, 1, 3)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(7777, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->port_mode(PortMode_Probe); + t.rtps_udp->pb(9999); + t.rtps_udp->dg(9999); + t.rtps_udp->pg(9999); + t.rtps_udp->d3(9999); + LogRestore lr; + log_level.set(LogLevel::None); + ASSERT_TRUE(t.rtps_udp->ipv6_unicast_address(t.addr, t.fixed, 9999, 9999)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(29664, default_addr)); + EXPECT_FALSE(t.fixed); + } + + { + AddressTest t; + t.rtps_udp->local_address(NetworkAddress(1234, "[1:2:3:4]")); + ASSERT_TRUE(t.rtps_udp->ipv6_unicast_address(t.addr, t.fixed, 1, 0)); + EXPECT_ADDR_EQ(t.addr, NetworkAddress(1234, "[1:2:3:4]")); + EXPECT_TRUE(t.fixed); + } +} +#endif