core: extend FaceUri with fd, ether, dev schemes
refs #1396 Change-Id: I6680eb2013c335a14c9fa76b965c2d1e63202334
This commit is contained in:
1 parent
bf9edeeaee
commit
e38b1c4e8f
3 files changed
+211
-35
No files matched your search
+52
-14
@@ -6,6 +6,10 @@
|
||||
|
||||
#include "face-uri.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#ifdef HAVE_PCAP
|
||||
#include "face/ethernet.hpp"
|
||||
#endif // HAVE_PCAP
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
NFD_LOG_INIT("FaceUri");
|
||||
@@ -35,30 +39,35 @@ FaceUri::parse(const std::string& uri)
|
||||
m_port.clear();
|
||||
m_path.clear();
|
||||
|
||||
boost::regex protocolExp("(\\w+\\d?)://([^/]*)(\\/[^?]*)?");
|
||||
static const boost::regex protocolExp("(\\w+\\d?)://([^/]*)(\\/[^?]*)?");
|
||||
boost::smatch protocolMatch;
|
||||
if (!boost::regex_match(uri, protocolMatch, protocolExp)) {
|
||||
return false;
|
||||
}
|
||||
m_scheme = protocolMatch[1];
|
||||
const std::string& authority = protocolMatch[2];
|
||||
m_path = protocolMatch[3];
|
||||
|
||||
const std::string& authority = protocolMatch[2];
|
||||
// pattern for IPv6 address enclosed in [ ], with optional port number
|
||||
static const boost::regex v6Exp("^\\[([a-fA-F0-9:]+)\\](?:\\:(\\d+))?$");
|
||||
// pattern for Ethernet address in standard hex-digits-and-colons notation
|
||||
static const boost::regex etherExp("^((?:[a-fA-F0-9]{1,2}\\:){5}(?:[a-fA-F0-9]{1,2}))$");
|
||||
// pattern for IPv4/hostname/fd/ifname, with optional port number
|
||||
static const boost::regex v4HostExp("^([^:]+)(?:\\:(\\d+))?$");
|
||||
|
||||
boost::regex v6Exp("^\\[(([a-fA-F0-9:]+))\\](:(\\d+))?$"); // [host]:port
|
||||
boost::regex v4Exp("^((\\d+\\.){3}\\d+)(:(\\d+))?$");
|
||||
boost::regex hostExp("^(([^:]*))(:(\\d+))?$"); // host:port
|
||||
|
||||
boost::smatch match;
|
||||
m_isV6 = boost::regex_match(authority, match, v6Exp);
|
||||
if (m_isV6 ||
|
||||
boost::regex_match(authority, match, v4Exp) ||
|
||||
boost::regex_match(authority, match, hostExp)) {
|
||||
m_host = match[1];
|
||||
m_port = match[4];
|
||||
if (authority.empty()) {
|
||||
// UNIX, internal
|
||||
}
|
||||
else {
|
||||
if (m_path.empty()) {
|
||||
boost::smatch match;
|
||||
m_isV6 = boost::regex_match(authority, match, v6Exp);
|
||||
if (m_isV6 ||
|
||||
boost::regex_match(authority, match, etherExp) ||
|
||||
boost::regex_match(authority, match, v4HostExp)) {
|
||||
m_host = match[1];
|
||||
m_port = match[2];
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -84,11 +93,40 @@ FaceUri::FaceUri(const boost::asio::ip::udp::endpoint& endpoint)
|
||||
m_port = boost::lexical_cast<std::string>(endpoint.port());
|
||||
}
|
||||
|
||||
#ifdef HAVE_UNIX_SOCKETS
|
||||
FaceUri::FaceUri(const boost::asio::local::stream_protocol::endpoint& endpoint)
|
||||
: m_isV6(false)
|
||||
{
|
||||
m_scheme = "unix";
|
||||
m_path = endpoint.path();
|
||||
}
|
||||
#endif // HAVE_UNIX_SOCKETS
|
||||
|
||||
FaceUri
|
||||
FaceUri::fromFd(int fd)
|
||||
{
|
||||
FaceUri uri;
|
||||
uri.m_scheme = "fd";
|
||||
uri.m_host = boost::lexical_cast<std::string>(fd);
|
||||
return uri;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PCAP
|
||||
FaceUri::FaceUri(const ethernet::Address& address)
|
||||
: m_isV6(false)
|
||||
{
|
||||
m_scheme = "ether";
|
||||
m_host = address.toString(':');
|
||||
}
|
||||
#endif // HAVE_PCAP
|
||||
|
||||
FaceUri
|
||||
FaceUri::fromDev(const std::string& ifname)
|
||||
{
|
||||
FaceUri uri;
|
||||
uri.m_scheme = "dev";
|
||||
uri.m_host = ifname;
|
||||
return uri;
|
||||
}
|
||||
|
||||
} // namespace nfd
|
||||
+49
-15
@@ -11,22 +11,34 @@
|
||||
|
||||
namespace nfd {
|
||||
|
||||
/// represents a URI in Face Management protocol
|
||||
#ifdef HAVE_PCAP
|
||||
namespace ethernet {
|
||||
class Address;
|
||||
} // namespace ethernet
|
||||
#endif // HAVE_PCAP
|
||||
|
||||
/** \brief represents the underlying protocol and address used by a Face
|
||||
* \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#FaceUri
|
||||
*/
|
||||
class FaceUri
|
||||
{
|
||||
public:
|
||||
class Error : public std::runtime_error
|
||||
class Error : public std::invalid_argument
|
||||
{
|
||||
public:
|
||||
Error(const std::string& what) : std::runtime_error(what) {}
|
||||
explicit
|
||||
Error(const std::string& what)
|
||||
: std::invalid_argument(what)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
FaceUri();
|
||||
|
||||
/** \brief construct by parsing
|
||||
*
|
||||
* \param uri scheme://domain[:port]/path
|
||||
* \throw FaceUri::Error if URI cannot be parsed
|
||||
* \param uri scheme://host[:port]/path
|
||||
* \throw FaceUri::Error if URI cannot be parsed
|
||||
*/
|
||||
explicit
|
||||
FaceUri(const std::string& uri);
|
||||
@@ -36,19 +48,40 @@ public:
|
||||
explicit
|
||||
FaceUri(const char* uri);
|
||||
|
||||
explicit
|
||||
FaceUri(const boost::asio::ip::tcp::endpoint& endpoint);
|
||||
|
||||
explicit
|
||||
FaceUri(const boost::asio::ip::udp::endpoint& endpoint);
|
||||
|
||||
explicit
|
||||
FaceUri(const boost::asio::local::stream_protocol::endpoint& endpoint);
|
||||
|
||||
/// exception-safe parsing
|
||||
bool
|
||||
parse(const std::string& uri);
|
||||
|
||||
public: // scheme-specific construction
|
||||
/// construct tcp4 or tcp6 canonical FaceUri
|
||||
explicit
|
||||
FaceUri(const boost::asio::ip::tcp::endpoint& endpoint);
|
||||
|
||||
/// construct udp4 or udp6 canonical FaceUri
|
||||
explicit
|
||||
FaceUri(const boost::asio::ip::udp::endpoint& endpoint);
|
||||
|
||||
#ifdef HAVE_UNIX_SOCKETS
|
||||
/// construct unix canonical FaceUri
|
||||
explicit
|
||||
FaceUri(const boost::asio::local::stream_protocol::endpoint& endpoint);
|
||||
#endif // HAVE_UNIX_SOCKETS
|
||||
|
||||
/// create fd FaceUri from file descriptor
|
||||
static FaceUri
|
||||
fromFd(int fd);
|
||||
|
||||
#ifdef HAVE_PCAP
|
||||
/// construct ether canonical FaceUri
|
||||
explicit
|
||||
FaceUri(const ethernet::Address& address);
|
||||
#endif // HAVE_PCAP
|
||||
|
||||
/// create dev FaceUri from network device name
|
||||
static FaceUri
|
||||
fromDev(const std::string& ifname);
|
||||
|
||||
public: // getters
|
||||
/// get scheme (protocol)
|
||||
const std::string&
|
||||
getScheme() const;
|
||||
@@ -76,12 +109,13 @@ private:
|
||||
bool m_isV6;
|
||||
std::string m_port;
|
||||
std::string m_path;
|
||||
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const FaceUri& uri);
|
||||
};
|
||||
|
||||
inline
|
||||
FaceUri::FaceUri()
|
||||
: m_isV6(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+110
-6
@@ -5,6 +5,9 @@
|
||||
*/
|
||||
|
||||
#include "core/face-uri.hpp"
|
||||
#ifdef HAVE_PCAP
|
||||
#include "face/ethernet.hpp"
|
||||
#endif // HAVE_PCAP
|
||||
|
||||
#include "tests/test-common.hpp"
|
||||
|
||||
@@ -13,7 +16,21 @@ namespace tests {
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(CoreFaceUri, BaseFixture)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Basic)
|
||||
BOOST_AUTO_TEST_CASE(Internal)
|
||||
{
|
||||
FaceUri uri;
|
||||
|
||||
BOOST_CHECK(uri.parse("internal://"));
|
||||
BOOST_CHECK_EQUAL(uri.getScheme(), "internal");
|
||||
BOOST_CHECK_EQUAL(uri.getHost(), "");
|
||||
BOOST_CHECK_EQUAL(uri.getPort(), "");
|
||||
BOOST_CHECK_EQUAL(uri.getPath(), "");
|
||||
|
||||
BOOST_CHECK_EQUAL(uri.parse("internal:"), false);
|
||||
BOOST_CHECK_EQUAL(uri.parse("internal:/"), false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Udp)
|
||||
{
|
||||
BOOST_CHECK_NO_THROW(FaceUri("udp://hostname:6363"));
|
||||
BOOST_CHECK_THROW(FaceUri("udp//hostname:6363"), FaceUri::Error);
|
||||
@@ -21,7 +38,7 @@ BOOST_AUTO_TEST_CASE(Basic)
|
||||
|
||||
FaceUri uri;
|
||||
BOOST_CHECK_EQUAL(uri.parse("udp//hostname:6363"), false);
|
||||
|
||||
|
||||
BOOST_CHECK(uri.parse("udp://hostname:80"));
|
||||
BOOST_CHECK_EQUAL(uri.getScheme(), "udp");
|
||||
BOOST_CHECK_EQUAL(uri.getHost(), "hostname");
|
||||
@@ -39,29 +56,116 @@ BOOST_AUTO_TEST_CASE(Basic)
|
||||
BOOST_CHECK_EQUAL(uri.getHost(), "2001:db8:3f9:0::1");
|
||||
BOOST_CHECK_EQUAL(uri.getPort(), "6363");
|
||||
BOOST_CHECK_EQUAL(uri.getPath(), "");
|
||||
|
||||
|
||||
BOOST_CHECK(uri.parse("udp6://[2001:db8:3f9:0:3025:ccc5:eeeb:86d3]:6363"));
|
||||
BOOST_CHECK_EQUAL(uri.getScheme(), "udp6");
|
||||
BOOST_CHECK_EQUAL(uri.getHost(), "2001:db8:3f9:0:3025:ccc5:eeeb:86d3");
|
||||
BOOST_CHECK_EQUAL(uri.getPort(), "6363");
|
||||
BOOST_CHECK_EQUAL(uri.getPath(), "");
|
||||
|
||||
BOOST_CHECK_EQUAL(uri.parse("udp6://[2001:db8:3f9:0:3025:ccc5:eeeb:86dg]:6363"), false);
|
||||
|
||||
using namespace boost::asio;
|
||||
ip::udp::endpoint endpoint4(ip::address_v4::from_string("192.0.2.1"), 7777);
|
||||
BOOST_REQUIRE_NO_THROW(FaceUri(endpoint4));
|
||||
BOOST_CHECK_EQUAL(FaceUri(endpoint4).toString(), "udp4://192.0.2.1:7777");
|
||||
|
||||
ip::udp::endpoint endpoint6(ip::address_v6::from_string("2001:DB8::1"), 7777);
|
||||
BOOST_REQUIRE_NO_THROW(FaceUri(endpoint6));
|
||||
BOOST_CHECK_EQUAL(FaceUri(endpoint6).toString(), "udp6://[2001:db8::1]:7777");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Tcp)
|
||||
{
|
||||
FaceUri uri;
|
||||
|
||||
BOOST_CHECK(uri.parse("tcp://random.host.name"));
|
||||
BOOST_CHECK_EQUAL(uri.getScheme(), "tcp");
|
||||
BOOST_CHECK_EQUAL(uri.getHost(), "random.host.name");
|
||||
BOOST_CHECK_EQUAL(uri.getPort(), "");
|
||||
BOOST_CHECK_EQUAL(uri.getPath(), "");
|
||||
|
||||
BOOST_CHECK_EQUAL(uri.parse("tcp://192.0.2.1:"), false);
|
||||
BOOST_CHECK_EQUAL(uri.parse("tcp://[::zzzz]"), false);
|
||||
|
||||
using namespace boost::asio;
|
||||
ip::tcp::endpoint endpoint4(ip::address_v4::from_string("192.0.2.1"), 7777);
|
||||
BOOST_REQUIRE_NO_THROW(FaceUri(endpoint4));
|
||||
BOOST_CHECK_EQUAL(FaceUri(endpoint4).toString(), "tcp4://192.0.2.1:7777");
|
||||
|
||||
ip::tcp::endpoint endpoint6(ip::address_v6::from_string("2001:DB8::1"), 7777);
|
||||
BOOST_REQUIRE_NO_THROW(FaceUri(endpoint6));
|
||||
BOOST_CHECK_EQUAL(FaceUri(endpoint6).toString(), "tcp6://[2001:db8::1]:7777");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Unix)
|
||||
{
|
||||
FaceUri uri;
|
||||
|
||||
BOOST_CHECK(uri.parse("unix:///var/run/example.sock"));
|
||||
BOOST_CHECK_EQUAL(uri.getScheme(), "unix");
|
||||
BOOST_CHECK_EQUAL(uri.getHost(), "");
|
||||
BOOST_CHECK_EQUAL(uri.getPort(), "");
|
||||
BOOST_CHECK_EQUAL(uri.getPath(), "/var/run/example.sock");
|
||||
|
||||
BOOST_CHECK_EQUAL(uri.parse("tcp://192.0.2.1:"), false);
|
||||
BOOST_CHECK_EQUAL(uri.parse("tcp://[::zzzz]"), false);
|
||||
BOOST_CHECK_EQUAL(uri.parse("udp6://[2001:db8:3f9:0:3025:ccc5:eeeb:86dg]:6363"), false);
|
||||
//BOOST_CHECK_EQUAL(uri.parse("unix://var/run/example.sock"), false);
|
||||
// This is not a valid unix:/ URI, but the parse would treat "var" as host
|
||||
|
||||
#ifdef HAVE_UNIX_SOCKETS
|
||||
using namespace boost::asio;
|
||||
local::stream_protocol::endpoint endpoint("/var/run/example.sock");
|
||||
BOOST_REQUIRE_NO_THROW(FaceUri(endpoint));
|
||||
BOOST_CHECK_EQUAL(FaceUri(endpoint).toString(), "unix:///var/run/example.sock");
|
||||
#endif // HAVE_UNIX_SOCKETS
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Fd)
|
||||
{
|
||||
FaceUri uri;
|
||||
|
||||
BOOST_CHECK(uri.parse("fd://6"));
|
||||
BOOST_CHECK_EQUAL(uri.getScheme(), "fd");
|
||||
BOOST_CHECK_EQUAL(uri.getHost(), "6");
|
||||
BOOST_CHECK_EQUAL(uri.getPort(), "");
|
||||
BOOST_CHECK_EQUAL(uri.getPath(), "");
|
||||
|
||||
int fd = 21;
|
||||
BOOST_REQUIRE_NO_THROW(FaceUri::fromFd(fd));
|
||||
BOOST_CHECK_EQUAL(FaceUri::fromFd(fd).toString(), "fd://21");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Ether)
|
||||
{
|
||||
FaceUri uri;
|
||||
|
||||
BOOST_CHECK(uri.parse("ether://08:00:27:01:dd:01"));
|
||||
BOOST_CHECK_EQUAL(uri.getScheme(), "ether");
|
||||
BOOST_CHECK_EQUAL(uri.getHost(), "08:00:27:01:dd:01");
|
||||
BOOST_CHECK_EQUAL(uri.getPort(), "");
|
||||
BOOST_CHECK_EQUAL(uri.getPath(), "");
|
||||
|
||||
BOOST_CHECK_EQUAL(uri.parse("ether://08:00:27:zz:dd:01"), false);
|
||||
|
||||
#ifdef HAVE_PCAP
|
||||
ethernet::Address address = ethernet::Address::fromString("33:33:01:01:01:01");
|
||||
BOOST_REQUIRE_NO_THROW(FaceUri(address));
|
||||
BOOST_CHECK_EQUAL(FaceUri(address).toString(), "ether://33:33:01:01:01:01");
|
||||
#endif // HAVE_PCAP
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Dev)
|
||||
{
|
||||
FaceUri uri;
|
||||
|
||||
BOOST_CHECK(uri.parse("dev://eth0"));
|
||||
BOOST_CHECK_EQUAL(uri.getScheme(), "dev");
|
||||
BOOST_CHECK_EQUAL(uri.getHost(), "eth0");
|
||||
BOOST_CHECK_EQUAL(uri.getPort(), "");
|
||||
BOOST_CHECK_EQUAL(uri.getPath(), "");
|
||||
|
||||
std::string ifname = "en1";
|
||||
BOOST_REQUIRE_NO_THROW(FaceUri::fromDev(ifname));
|
||||
BOOST_CHECK_EQUAL(FaceUri::fromDev(ifname).toString(), "dev://en1");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
Reference in new issue
Block a user