core: extend FaceUri with fd, ether, dev schemes
refs #1396
Change-Id: I6680eb2013c335a14c9fa76b965c2d1e63202334
diff --git a/daemon/core/face-uri.cpp b/daemon/core/face-uri.cpp
index cc6c8c8..14751d6 100644
--- a/daemon/core/face-uri.cpp
+++ b/daemon/core/face-uri.cpp
@@ -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 @@
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 @@
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
diff --git a/daemon/core/face-uri.hpp b/daemon/core/face-uri.hpp
index 29647bb..fa0a62a 100644
--- a/daemon/core/face-uri.hpp
+++ b/daemon/core/face-uri.hpp
@@ -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 @@
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 @@
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)
{
}