32 #include <boost/concept_check.hpp> 33 #include <boost/regex.hpp> 34 #include <boost/lexical_cast.hpp> 35 #include <boost/mpl/vector.hpp> 36 #include <boost/mpl/for_each.hpp> 41 BOOST_CONCEPT_ASSERT((boost::EqualityComparable<FaceUri>));
51 BOOST_THROW_EXCEPTION(
Error(
"Malformed URI: " + uri));
58 BOOST_THROW_EXCEPTION(
Error(
"Malformed URI: " + std::string(uri)));
71 static const boost::regex protocolExp(
"(\\w+\\d?)://([^/]*)(\\/[^?]*)?");
72 boost::smatch protocolMatch;
73 if (!boost::regex_match(uri, protocolMatch, protocolExp)) {
76 m_scheme = protocolMatch[1];
77 const std::string& authority = protocolMatch[2];
78 m_path = protocolMatch[3];
81 static const boost::regex v6Exp(
"^\\[([a-fA-F0-9:]+)\\](?:\\:(\\d+))?$");
83 static const boost::regex etherExp(
"^\\[((?:[a-fA-F0-9]{1,2}\\:){5}(?:[a-fA-F0-9]{1,2}))\\]$");
85 static const boost::regex v4MappedV6Exp(
"^\\[::ffff:(\\d+(?:\\.\\d+){3})\\](?:\\:(\\d+))?$");
87 static const boost::regex v4HostExp(
"^([^:]+)(?:\\:(\\d+))?$");
89 if (authority.empty()) {
94 m_isV6 = boost::regex_match(authority, match, v6Exp);
96 boost::regex_match(authority, match, etherExp) ||
97 boost::regex_match(authority, match, v4MappedV6Exp) ||
98 boost::regex_match(authority, match, v4HostExp)) {
112 m_isV6 = endpoint.address().is_v6();
113 m_scheme = m_isV6 ?
"udp6" :
"udp4";
114 m_host = endpoint.address().to_string();
115 m_port = boost::lexical_cast<std::string>(endpoint.port());
120 m_isV6 = endpoint.address().is_v6();
121 m_scheme = m_isV6 ?
"tcp6" :
"tcp4";
122 m_host = endpoint.address().to_string();
123 m_port = boost::lexical_cast<std::string>(endpoint.port());
126 FaceUri::FaceUri(
const boost::asio::ip::tcp::endpoint& endpoint,
const std::string& scheme)
129 m_isV6 = endpoint.address().is_v6();
130 m_host = endpoint.address().to_string();
131 m_port = boost::lexical_cast<std::string>(endpoint.port());
134 #ifdef BOOST_ASIO_HAS_LOCAL_SOCKETS 135 FaceUri::FaceUri(
const boost::asio::local::stream_protocol::endpoint& endpoint)
139 m_path = endpoint.path();
141 #endif // BOOST_ASIO_HAS_LOCAL_SOCKETS 148 uri.m_host = boost::lexical_cast<std::string>(fd);
163 uri.m_scheme =
"dev";
171 return (m_scheme == rhs.m_scheme &&
172 m_host == rhs.m_host &&
173 m_isV6 == rhs.m_isV6 &&
174 m_port == rhs.m_port &&
175 m_path == rhs.m_path);
181 return !(*
this == rhs);
187 std::ostringstream os;
195 os << uri.m_scheme <<
"://";
197 os <<
"[" << uri.m_host <<
"]";
202 if (!uri.m_port.empty()) {
203 os <<
":" << uri.m_port;
219 virtual std::set<std::string>
220 getSchemes()
const = 0;
229 boost::asio::io_service& io,
const time::nanoseconds& timeout)
const = 0;
232 template<
typename Protocol>
236 virtual std::set<std::string>
239 std::set<std::string> schemes;
240 schemes.insert(m_baseScheme);
241 schemes.insert(m_v4Scheme);
242 schemes.insert(m_v6Scheme);
249 if (faceUri.
getPort().empty()) {
252 if (!faceUri.
getPath().empty()) {
256 boost::system::error_code ec;
257 boost::asio::ip::address addr;
259 addr = boost::asio::ip::address_v4::from_string(faceUri.
getHost(), ec);
261 else if (faceUri.
getScheme() == m_v6Scheme) {
262 addr = boost::asio::ip::address_v6::from_string(faceUri.
getHost(), ec);
267 return !
static_cast<bool>(ec) && addr.to_string() == faceUri.
getHost() &&
268 this->checkAddress(addr).first;
275 boost::asio::io_service& io,
const time::nanoseconds& timeout)
const 286 else if (faceUri.
getScheme() == m_v6Scheme) {
290 BOOST_ASSERT(faceUri.
getScheme() == m_baseScheme);
295 shared_ptr<FaceUri> uri = make_shared<FaceUri>(faceUri);
299 io, addressSelector, timeout);
304 uint32_t defaultUnicastPort = 6363,
305 uint32_t defaultMulticastPort = 56363)
306 : m_baseScheme(baseScheme)
307 , m_v4Scheme(baseScheme +
"4")
308 , m_v6Scheme(baseScheme +
"6")
309 , m_defaultUnicastPort(defaultUnicastPort)
310 , m_defaultMulticastPort(defaultMulticastPort)
317 onDnsSuccess(shared_ptr<FaceUri> faceUri,
322 std::pair<bool, std::string> checkAddressRes = this->checkAddress(ipAddress);
323 if (!checkAddressRes.first) {
324 onFailure(checkAddressRes.second);
329 if (faceUri->getPort().empty()) {
330 port = ipAddress.is_multicast() ? m_defaultMulticastPort : m_defaultUnicastPort;
334 port = boost::lexical_cast<uint32_t>(faceUri->getPort());
336 catch (boost::bad_lexical_cast&) {
337 onFailure(
"invalid port number");
342 FaceUri canonicalUri(
typename Protocol::endpoint(ipAddress, port));
344 onSuccess(canonicalUri);
350 const std::string& reason)
const 359 virtual std::pair<bool, std::string>
362 return std::make_pair(
true,
"");
366 std::string m_baseScheme;
367 std::string m_v4Scheme;
368 std::string m_v6Scheme;
369 uint32_t m_defaultUnicastPort;
370 uint32_t m_defaultMulticastPort;
397 virtual std::pair<bool, std::string>
400 if (ipAddress.is_multicast()) {
401 return std::make_pair(
false,
"cannot use multicast address");
403 return std::make_pair(
true,
"");
410 virtual std::set<std::string>
413 std::set<std::string> schemes;
414 schemes.insert(
"ether");
421 if (!faceUri.
getPort().empty()) {
424 if (!faceUri.
getPath().empty()) {
436 boost::asio::io_service& io,
const time::nanoseconds& timeout)
const 440 onFailure(
"cannot parse address");
446 onSuccess(canonicalUri);
450 typedef boost::mpl::vector<
462 : m_providerTable(providerTable)
466 template<
typename CP>
void 469 shared_ptr<CanonizeProvider> cp = make_shared<CP>();
471 std::set<std::string> schemes = cp->getSchemes();
472 BOOST_ASSERT(!schemes.empty());
474 it != schemes.end(); ++it) {
475 BOOST_ASSERT(m_providerTable.count(*it) == 0);
476 m_providerTable[*it] = cp;
481 CanonizeProviderTable& m_providerTable;
487 static CanonizeProviderTable providerTable;
488 if (providerTable.empty()) {
490 BOOST_ASSERT(!providerTable.empty());
493 CanonizeProviderTable::const_iterator it = providerTable.find(scheme);
494 if (it == providerTable.end()) {
497 return it->second.get();
525 boost::asio::io_service& io,
const time::nanoseconds& timeout)
const 529 if (static_cast<bool>(onFailure)) {
530 onFailure(
"scheme not supported");
539 static_cast<bool>(onSuccess) ? onSuccess : successNop,
540 static_cast<bool>(onFailure) ? onFailure : failureNop,
virtual void canonize(const FaceUri &faceUri, const FaceUri::CanonizeSuccessCallback &onSuccess, const FaceUri::CanonizeFailureCallback &onFailure, boost::asio::io_service &io, const time::nanoseconds &timeout) const
virtual ~CanonizeProvider()
virtual std::set< std::string > getSchemes() const
virtual std::pair< bool, std::string > checkAddress(const dns::IpAddress &ipAddress) const
when overriden in a subclass, check the IP address is allowable
Copyright (c) 2011-2015 Regents of the University of California.
boost::mpl::vector< UdpCanonizeProvider *, TcpCanonizeProvider *, EtherCanonizeProvider *> CanonizeProviders
virtual bool isCanonical(const FaceUri &faceUri) const =0
virtual std::set< std::string > getSchemes() const
bool parse(const std::string &uri)
exception-safe parsing
static bool canCanonize(const std::string &scheme)
represents an Ethernet hardware address
static Address fromString(const std::string &str)
Creates an Address from a string containing an Ethernet address in hexadecimal notation, with colons or hyphens as separators.
represents the underlying protocol and address used by a Face
bool isCanonical() const
determine whether this FaceUri is in canonical form
std::string toString() const
write as a string
IpHostCanonizeProvider(const std::string &baseScheme, uint32_t defaultUnicastPort=6363, uint32_t defaultMulticastPort=56363)
virtual void canonize(const FaceUri &faceUri, const FaceUri::CanonizeSuccessCallback &onSuccess, const FaceUri::CanonizeFailureCallback &onFailure, boost::asio::io_service &io, const time::nanoseconds &timeout) const =0
static const CanonizeProvider * getCanonizeProvider(const std::string &scheme)
function< void(const FaceUri &)> CanonizeSuccessCallback
function< bool(const IpAddress &address)> AddressSelector
bool operator!=(const FaceUri &rhs) const
const std::string & getScheme() const
get scheme (protocol)
Table::const_iterator iterator
CanonizeProviderTableInitializer(CanonizeProviderTable &providerTable)
virtual bool isCanonical(const FaceUri &faceUri) const
friend std::ostream & operator<<(std::ostream &os, const FaceUri &uri)
const std::string & getPort() const
get port
virtual void canonize(const FaceUri &faceUri, const FaceUri::CanonizeSuccessCallback &onSuccess, const FaceUri::CanonizeFailureCallback &onFailure, boost::asio::io_service &io, const time::nanoseconds &timeout) const
std::map< std::string, shared_ptr< CanonizeProvider > > CanonizeProviderTable
virtual bool isCanonical(const FaceUri &faceUri) const
void asyncResolve(const std::string &host, const SuccessCallback &onSuccess, const ErrorCallback &onError, boost::asio::io_service &ioService, const AddressSelector &addressSelector, time::nanoseconds timeout)
Asynchronously resolve host.
a CanonizeProvider provides FaceUri canonization functionality for a group of schemes ...
void canonize(const CanonizeSuccessCallback &onSuccess, const CanonizeFailureCallback &onFailure, boost::asio::io_service &io, const time::nanoseconds &timeout) const
asynchronously convert this FaceUri to canonical form
boost::asio::ip::address IpAddress
static FaceUri fromDev(const std::string &ifname)
create dev FaceUri from network device name
bool operator==(const FaceUri &rhs) const
bool isNull() const
True if this is a null address (00:00:00:00:00:00)
const std::string & getHost() const
get host (domain)
const std::string & getPath() const
get path
function< void(const std::string &reason)> CanonizeFailureCallback
std::string toString(char sep=':') const
Converts the address to a human-readable string.
static FaceUri fromFd(int fd)
create fd FaceUri from file descriptor