Skip to content

Commit

Permalink
Configure Discovery Server using names (eProsima#2140)
Browse files Browse the repository at this point in the history
* Refs 12349: Use cross-platform get_env

Signed-off-by: Eduardo Ponz Segrelles <eduardoponz@eprosima.com>

* Refs 12349: Specify locators as DNS in fastdds CLI

Signed-off-by: Eduardo Ponz Segrelles <eduardoponz@eprosima.com>

* Refs 12349: Specify locators as DNS in environment variable

Signed-off-by: Eduardo Ponz Segrelles <eduardoponz@eprosima.com>

* Refs 12349: Allow names in locators using XML

Signed-off-by: Eduardo Ponz Segrelles <eduardoponz@eprosima.com>

* Refs 12349: Fix ServerClientEnvironmentSetUp test

Signed-off-by: Eduardo Ponz Segrelles <eduardoponz@eprosima.com>

* Refs 12349: Apply suggestions

Signed-off-by: Eduardo Ponz Segrelles <eduardoponz@eprosima.com>

* Refs 12349: Update fds help

Signed-off-by: Eduardo Ponz Segrelles <eduardoponz@eprosima.com>

* Refs 12349: Apply suggestions

Signed-off-by: Eduardo Ponz Segrelles <eduardoponz@eprosima.com>
Signed-off-by: Samuel Wilhelmsson <samuel@halodi.com>
  • Loading branch information
EduPonz authored and SamuelWHalodi committed Oct 4, 2021
1 parent 2594ceb commit df8fbe0
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 65 deletions.
71 changes: 40 additions & 31 deletions src/cpp/rtps/builtin/discovery/participant/PDPClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,25 @@
*
*/

#include <rtps/builtin/discovery/participant/PDPClient.h>

#include <fastdds/dds/log/Log.hpp>
#include <fastdds/rtps/attributes/RTPSParticipantAttributes.h>
#include <fastdds/rtps/builtin/BuiltinProtocols.h>
#include <fastdds/rtps/builtin/discovery/participant/PDPListener.h>
#include <fastdds/rtps/builtin/liveliness/WLP.h>

#include <fastdds/rtps/history/ReaderHistory.h>
#include <fastdds/rtps/history/WriterHistory.h>
#include <fastdds/rtps/participant/RTPSParticipantListener.h>
#include <fastdds/rtps/reader/StatefulReader.h>
#include <fastdds/rtps/writer/StatefulWriter.h>

#include <fastdds/rtps/attributes/RTPSParticipantAttributes.h>

#include <fastdds/rtps/writer/ReaderProxy.h>

#include <fastdds/rtps/history/WriterHistory.h>
#include <fastdds/rtps/history/ReaderHistory.h>

#include <fastdds/rtps/writer/StatefulWriter.h>
#include <fastrtps/utils/TimeConversion.h>

#include <rtps/builtin/discovery/endpoint/EDPClient.h>
#include <rtps/builtin/discovery/participant/DirectMessageSender.hpp>
#include <rtps/participant/RTPSParticipantImpl.h>
#include <fastdds/rtps/builtin/discovery/participant/PDPListener.h>

#include <fastdds/dds/log/Log.hpp>

#include <rtps/builtin/discovery/participant/PDPClient.h>
#include <rtps/builtin/discovery/participant/timedevent/DSClientEvent.h>
#include <rtps/builtin/discovery/endpoint/EDPClient.h>
#include <rtps/participant/RTPSParticipantImpl.h>
#include <utils/SystemInfo.hpp>

using namespace eprosima::fastrtps;

Expand Down Expand Up @@ -629,9 +623,8 @@ const std::string& ros_discovery_server_env()
{
static std::string servers;
{
#pragma warning(suppress:4996)
const char* data = std::getenv(DEFAULT_ROS2_MASTER_URI);
if (nullptr != data)
const char* data;
if (eprosima::ReturnCode_t::RETCODE_OK == SystemInfo::instance().get_env(DEFAULT_ROS2_MASTER_URI, &data))
{
servers = data;
}
Expand All @@ -654,8 +647,10 @@ bool load_environment_server_info(
return false;
}

// parsing ancillary regex
const std::regex ROS2_IPV4_PATTERN(R"(^((?:[0-9]{1,3}\.){3}[0-9]{1,3})?:?(?:(\d+))?$)");
/* Parsing ancillary regex */
// Address should be <letter,numbers,dots>:<number>. We do not need to verify that the first part
// is an IPv4 address, as it is done latter.
const std::regex ROS2_ADDRESS_PATTERN(R"(^([A-Za-z0-9-.]+)?:?(?:(\d+))?$)");
const std::regex ROS2_SERVER_LIST_PATTERN(R"(([^;]*);?)");

try
Expand All @@ -681,16 +676,30 @@ bool load_environment_server_info(
// now we must parse the inner expression
std::smatch mr;
std::string locator(sm);
if (std::regex_match(locator, mr, ROS2_IPV4_PATTERN, std::regex_constants::match_not_null))
if (std::regex_match(locator, mr, ROS2_ADDRESS_PATTERN, std::regex_constants::match_not_null))
{
std::smatch::iterator it = mr.cbegin();

while (++it != mr.cend())
{
if (!IPLocator::setIPv4(server_locator, it->str()))
std::string address = it->str();

// Check whether the address is IPv4
if (!IPLocator::isIPv4(address))
{
auto response = rtps::IPLocator::resolveNameDNS(address);

// Add the first valid IPv4 address that we can find
if (response.first.size() > 0)
{
address = response.first.begin()->data();
}
}

if (!IPLocator::setIPv4(server_locator, address))
{
std::stringstream ss;
ss << "Wrong ipv4 address passed into the server's list " << it->str();
ss << "Wrong ipv4 address passed into the server's list " << address;
throw std::invalid_argument(ss.str());
}

Expand All @@ -705,17 +714,17 @@ bool load_environment_server_info(
// reset the locator to default
IPLocator::setPhysicalPort(server_locator, DEFAULT_ROS2_SERVER_PORT);

if ( it->matched)
if (it->matched)
{
// note stoi throws also an invalid_argument
int port = stoi(it->str());

if ( port > std::numeric_limits<uint16_t>::max())
if (port > std::numeric_limits<uint16_t>::max())
{
throw std::out_of_range("Too larget udp port passed into the server's list");
throw std::out_of_range("Too large udp port passed into the server's list");
}

if ( !IPLocator::setPhysicalPort(server_locator, static_cast<uint16_t>(port)))
if (!IPLocator::setPhysicalPort(server_locator, static_cast<uint16_t>(port)))
{
std::stringstream ss;
ss << "Wrong udp port passed into the server's list " << it->str();
Expand All @@ -728,7 +737,7 @@ bool load_environment_server_info(
// add the server to the list
if (!get_server_client_default_guidPrefix(server_id, server_att.guidPrefix))
{
throw std::invalid_argument("The maximum number of default discovery servers have been reached");
throw std::invalid_argument("The maximum number of default discovery servers has been reached");
}

server_att.metatrafficUnicastLocatorList.clear();
Expand Down Expand Up @@ -757,7 +766,7 @@ bool load_environment_server_info(
throw std::invalid_argument("No default server locators were provided.");
}
}
catch ( std::exception& e )
catch (std::exception& e)
{
logError(SERVER_CLIENT_DISCOVERY, e.what());
attributes.clear();
Expand Down
34 changes: 34 additions & 0 deletions src/cpp/rtps/xmlparser/XMLElementParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2729,6 +2729,23 @@ XMLP_ret XMLParser::getXMLLocatorUDPv4(
{
return XMLP_ret::XML_ERROR;
}
// Check whether the address is IPv4
if (!IPLocator::isIPv4(s))
{
auto response = rtps::IPLocator::resolveNameDNS(s);

// Add the first valid IPv4 address that we can find
if (response.first.size() > 0)
{
s = response.first.begin()->data();
}
else
{
logError(XMLPARSER,
"DNS server did not return any IPv4 address for: '" << s << "'. Name: " << name);
return XMLP_ret::XML_ERROR;
}
}
IPLocator::setIPv4(locator, s);
}
else
Expand Down Expand Up @@ -2776,6 +2793,23 @@ XMLP_ret XMLParser::getXMLLocatorUDPv6(
{
return XMLP_ret::XML_ERROR;
}
// Check whether the address is IPv6
if (!IPLocator::isIPv6(s))
{
auto response = rtps::IPLocator::resolveNameDNS(s);

// Add the first valid IPv6 address that we can find
if (response.second.size() > 0)
{
s = response.second.begin()->data();
}
else
{
logError(XMLPARSER,
"DNS server did not return any IPv6 address for: '" << s << "'. Name: " << name);
return XMLP_ret::XML_ERROR;
}
}
IPLocator::setIPv6(locator, s);
}
else
Expand Down
47 changes: 43 additions & 4 deletions test/blackbox/common/BlackboxTestsDiscovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1266,18 +1266,57 @@ TEST(Discovery, ServerClientEnvironmentSetUp)
ASSERT_TRUE(load_environment_server_info(text, output));
ASSERT_EQ(output, standard);

// 7. check ignore some servers scenario
// 8. Check that env var cannot specify more than 256 servers
text = ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;192.168.36.34:14520";
output.clear();

ASSERT_FALSE(load_environment_server_info(text, output));

// 8. check non-consistent addresses scenario
// 9. Check addresses as dns name
text = "localhost:12345";

output.clear();
standard.clear();

att.clear();
IPLocator::setIPv4(loc, string("127.0.0.1"));
IPLocator::setPhysicalPort(loc, 12345);
att.metatrafficUnicastLocatorList.push_back(loc);
get_server_client_default_guidPrefix(0, att.guidPrefix);
standard.push_back(att);

ASSERT_TRUE(load_environment_server_info(text, output));
ASSERT_EQ(output, standard);

// 10. Check mixed scenario with addresses and dns
text = "192.168.36.34:14520;localhost:12345;172.30.80.1:31090;";

output.clear();
ASSERT_FALSE(load_environment_server_info(text, output));
standard.clear();

}
att.clear();
IPLocator::setIPv4(loc, string("192.168.36.34"));
IPLocator::setPhysicalPort(loc, 14520);
att.metatrafficUnicastLocatorList.push_back(loc);
get_server_client_default_guidPrefix(0, att.guidPrefix);
standard.push_back(att);

att.clear();
IPLocator::setIPv4(loc, string("127.0.0.1"));
IPLocator::setPhysicalPort(loc, 12345);
att.metatrafficUnicastLocatorList.push_back(loc);
get_server_client_default_guidPrefix(1, att.guidPrefix);
standard.push_back(att);

att.clear();
IPLocator::setIPv4(loc, string("172.30.80.1"));
IPLocator::setPhysicalPort(loc, 31090);
att.metatrafficUnicastLocatorList.push_back(loc);
get_server_client_default_guidPrefix(2, att.guidPrefix);
standard.push_back(att);

ASSERT_TRUE(load_environment_server_info(text, output));
ASSERT_EQ(output, standard);
}
18 changes: 12 additions & 6 deletions tools/fds/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ General options:
-i --server-id Mandatory unique server identifier. Specifies zero based
server position in ROS_DISCOVERY_SERVER environment variable.

-l --ip-address Server interface chosen to listen the clients. Defaults
to any (0.0.0.0)
-l --ip-address IPv4 address chosen to listen the clients. Defaults
to any (0.0.0.0). Instead of an address, a name can
be specified.

-p --port UDP port chosen to listen the clients. Defaults to 11811

Expand All @@ -27,17 +28,22 @@ Examples:

$ fast-discovery-server -i 1 -l 127.0.0.1 -p 14520

3. Launch a default server with id 3 (third on ROS_DISCOVERY_SERVER)
3. Launch a default server with id 2 (third on ROS_DISCOVERY_SERVER)
listening on Wi-Fi (192.168.36.34) and Ethernet (172.20.96.1) local
interfaces with UDP ports 8783 and 51083 respectively
(addresses and ports are made up for the example).

$ fast-discovery-server -i 1 -l 192.168.36.34 -p 14520 -l 172.20.96.1 -p 51083
$ fast-discovery-server -i 2 -l 192.168.36.34 -p 8783 -l 172.20.96.1 -p 51083

4. Launch a default server with id 4 (fourth on ROS_DISCOVERY_SERVER)
4. Launch a default server with id 3 (fourth on ROS_DISCOVERY_SERVER)
listening on 172.30.144.1 with UDP port 12345 and provided with a
backup file. If the server crashes it will automatically restore its
previous state when reenacted.

$ fast-discovery-server -i 1 -l 172.30.144.1 -p 12345 -b
$ fast-discovery-server -i 3 -l 172.30.144.1 -p 12345 -b

5. Launch a default server with id 0 (first on ROS_DISCOVERY_SERVER)
listening on localhost with UDP port 14520. Only localhost clients
can reach the server defining as `ROS_DISCOVERY_SERVER=localhost:14520`.

$ fastdds discovery -i 0 -l localhost -p 14520
38 changes: 22 additions & 16 deletions tools/fds/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,25 @@ int main (
{
while ( pOp )
{
// Get next address
std::string address = string(pOp->arg);

// Check whether the address is IPv4
if (!rtps::IPLocator::isIPv4(address))
{
auto response = rtps::IPLocator::resolveNameDNS(address);

// Add the first valid IPv4 address that we can find
if (response.first.size() > 0)
{
address = response.first.begin()->data();
}
}

// Update locator address
if (!rtps::IPLocator::setIPv4(locator, string(pOp->arg)))
if (!rtps::IPLocator::setIPv4(locator, address))
{
cout << "Invalid listening locator address specified:" << pOp->arg << endl;
cout << "Invalid listening locator address specified:" << address << endl;
return 1;
}

Expand Down Expand Up @@ -288,35 +303,26 @@ option::ArgStatus Arg::check_server_id(
if (msg)
{
cout << "Option '" << option.name
<< "' is mandatory. Should be a key indentifier between 0 and 255." << endl;
<< "' is mandatory. Should be a key identifier between 0 and 255." << endl;
}

return option::ARG_ILLEGAL;
}

/*static*/
option::ArgStatus Arg::check_server_ipv4(
option::ArgStatus Arg::required(
const option::Option& option,
bool msg)
{
static const std::regex ipv4(R"(^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$)");

// the argument is required
if ( nullptr != option.arg )
if (nullptr != option.arg)
{
// we must check if its a proper ip address
if ( std::regex_match(option.arg, ipv4))
{
return option::ARG_OK;
}
return option::ARG_OK;
}

if (msg)
{
cout << "Option '" << option.name
<< "' should be a proper IPv4 address." << endl;
cout << "Option '" << option << "' requires an argument" << endl;
}

return option::ARG_ILLEGAL;
}

Expand Down
Loading

0 comments on commit df8fbe0

Please sign in to comment.