face-uri.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2017 Regents of the University of California,
4  * Arizona Board of Regents,
5  * Colorado State University,
6  * University Pierre & Marie Curie, Sorbonne University,
7  * Washington University in St. Louis,
8  * Beijing Institute of Technology,
9  * The University of Memphis.
10  *
11  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
12  *
13  * ndn-cxx library is free software: you can redistribute it and/or modify it under the
14  * terms of the GNU Lesser General Public License as published by the Free Software
15  * Foundation, either version 3 of the License, or (at your option) any later version.
16  *
17  * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
18  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
20  *
21  * You should have received copies of the GNU General Public License and GNU Lesser
22  * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
23  * <http://www.gnu.org/licenses/>.
24  *
25  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
26  */
27 
28 #include "face-uri.hpp"
29 
30 #include "address-converter.hpp"
31 #include "dns.hpp"
32 #include "util/string-helper.hpp"
33 
34 #include <boost/algorithm/string.hpp>
35 #include <boost/lexical_cast.hpp>
36 #include <boost/mpl/vector.hpp>
37 #include <boost/mpl/for_each.hpp>
38 #include <boost/regex.hpp>
39 #include <set>
40 #include <sstream>
41 
42 namespace ndn {
43 
44 BOOST_CONCEPT_ASSERT((boost::EqualityComparable<FaceUri>));
45 
47  : m_isV6(false)
48 {
49 }
50 
51 FaceUri::FaceUri(const std::string& uri)
52 {
53  if (!parse(uri)) {
54  BOOST_THROW_EXCEPTION(Error("Malformed URI: " + uri));
55  }
56 }
57 
58 FaceUri::FaceUri(const char* uri)
59  : FaceUri(std::string(uri))
60 {
61 }
62 
63 bool
64 FaceUri::parse(const std::string& uri)
65 {
66  m_scheme.clear();
67  m_host.clear();
68  m_port.clear();
69  m_path.clear();
70  m_isV6 = false;
71 
72  static const boost::regex protocolExp("(\\w+\\d?(\\+\\w+)?)://([^/]*)(\\/[^?]*)?");
73  boost::smatch protocolMatch;
74  if (!boost::regex_match(uri, protocolMatch, protocolExp)) {
75  return false;
76  }
77  m_scheme = protocolMatch[1];
78  const std::string& authority = protocolMatch[3];
79  m_path = protocolMatch[4];
80 
81  // pattern for IPv6 link local address enclosed in [ ], with optional port number
82  static const boost::regex v6LinkLocalExp("^\\[([a-fA-F0-9:]+)%([a-zA-Z0-9]+)\\]"
83  "(?:\\:(\\d+))?$");
84  // pattern for IPv6 address enclosed in [ ], with optional port number
85  static const boost::regex v6Exp("^\\[([a-fA-F0-9:]+)\\](?:\\:(\\d+))?$");
86  // pattern for Ethernet address in standard hex-digits-and-colons notation
87  static const boost::regex etherExp("^\\[((?:[a-fA-F0-9]{1,2}\\:){5}(?:[a-fA-F0-9]{1,2}))\\]$");
88  // pattern for IPv4-mapped IPv6 address, with optional port number
89  static const boost::regex v4MappedV6Exp("^\\[::ffff:(\\d+(?:\\.\\d+){3})\\](?:\\:(\\d+))?$");
90  // pattern for IPv4/hostname/fd/ifname, with optional port number
91  static const boost::regex v4HostExp("^([^:]+)(?:\\:(\\d+))?$");
92 
93  if (authority.empty()) {
94  // UNIX, internal
95  }
96  else {
97  boost::smatch match;
98  if (boost::regex_match(authority, match, v6LinkLocalExp)) {
99  m_isV6 = true;
100  m_host = match[1] + "%" + match[2];
101  m_port = match[3];
102  return true;
103  }
104 
105  m_isV6 = boost::regex_match(authority, match, v6Exp);
106  if (m_isV6 ||
107  boost::regex_match(authority, match, etherExp) ||
108  boost::regex_match(authority, match, v4MappedV6Exp) ||
109  boost::regex_match(authority, match, v4HostExp)) {
110  m_host = match[1];
111  m_port = match[2];
112  }
113  else {
114  return false;
115  }
116  }
117 
118  return true;
119 }
120 
121 FaceUri::FaceUri(const boost::asio::ip::udp::endpoint& endpoint)
122 {
123  m_isV6 = endpoint.address().is_v6();
124  m_scheme = m_isV6 ? "udp6" : "udp4";
125  m_host = endpoint.address().to_string();
126  m_port = to_string(endpoint.port());
127 }
128 
129 FaceUri::FaceUri(const boost::asio::ip::tcp::endpoint& endpoint)
130 {
131  m_isV6 = endpoint.address().is_v6();
132  m_scheme = m_isV6 ? "tcp6" : "tcp4";
133  m_host = endpoint.address().to_string();
134  m_port = to_string(endpoint.port());
135 }
136 
137 FaceUri::FaceUri(const boost::asio::ip::tcp::endpoint& endpoint, const std::string& scheme)
138 {
139  m_isV6 = endpoint.address().is_v6();
140  m_scheme = scheme;
141  m_host = endpoint.address().to_string();
142  m_port = to_string(endpoint.port());
143 }
144 
145 #ifdef BOOST_ASIO_HAS_LOCAL_SOCKETS
146 FaceUri::FaceUri(const boost::asio::local::stream_protocol::endpoint& endpoint)
147  : m_scheme("unix")
148  , m_path(endpoint.path())
149  , m_isV6(false)
150 {
151 }
152 #endif // BOOST_ASIO_HAS_LOCAL_SOCKETS
153 
154 FaceUri
156 {
157  FaceUri uri;
158  uri.m_scheme = "fd";
159  uri.m_host = to_string(fd);
160  return uri;
161 }
162 
164  : m_scheme("ether")
165  , m_host(address.toString())
166  , m_isV6(true)
167 {
168 }
169 
170 FaceUri
171 FaceUri::fromDev(const std::string& ifname)
172 {
173  FaceUri uri;
174  uri.m_scheme = "dev";
175  uri.m_host = ifname;
176  return uri;
177 }
178 
179 FaceUri
180 FaceUri::fromUdpDev(const boost::asio::ip::udp::endpoint& endpoint, const std::string& ifname)
181 {
182  FaceUri uri;
183  uri.m_scheme = endpoint.address().is_v6() ? "udp6+dev" : "udp4+dev";
184  uri.m_host = ifname;
185  uri.m_port = to_string(endpoint.port());
186  return uri;
187 }
188 
189 bool
190 FaceUri::operator==(const FaceUri& rhs) const
191 {
192  return m_isV6 == rhs.m_isV6 &&
193  m_scheme == rhs.m_scheme &&
194  m_host == rhs.m_host &&
195  m_port == rhs.m_port &&
196  m_path == rhs.m_path;
197 }
198 
199 bool
200 FaceUri::operator!=(const FaceUri& rhs) const
201 {
202  return !(*this == rhs);
203 }
204 
205 std::string
207 {
208  std::ostringstream os;
209  os << *this;
210  return os.str();
211 }
212 
213 std::ostream&
214 operator<<(std::ostream& os, const FaceUri& uri)
215 {
216  os << uri.m_scheme << "://";
217  if (uri.m_isV6) {
218  os << "[" << uri.m_host << "]";
219  }
220  else {
221  os << uri.m_host;
222  }
223  if (!uri.m_port.empty()) {
224  os << ":" << uri.m_port;
225  }
226  os << uri.m_path;
227  return os;
228 }
229 
230 
233 class CanonizeProvider : noncopyable
234 {
235 public:
236  virtual
237  ~CanonizeProvider() = default;
238 
239  virtual std::set<std::string>
240  getSchemes() const = 0;
241 
242  virtual bool
243  isCanonical(const FaceUri& faceUri) const = 0;
244 
245  virtual void
246  canonize(const FaceUri& faceUri,
247  const FaceUri::CanonizeSuccessCallback& onSuccess,
248  const FaceUri::CanonizeFailureCallback& onFailure,
249  boost::asio::io_service& io, time::nanoseconds timeout) const = 0;
250 };
251 
252 template<typename Protocol>
253 class IpHostCanonizeProvider : public CanonizeProvider
254 {
255 public:
256  std::set<std::string>
257  getSchemes() const override
258  {
259  return {m_baseScheme, m_v4Scheme, m_v6Scheme};
260  }
261 
262  bool
263  isCanonical(const FaceUri& faceUri) const override
264  {
265  if (faceUri.getPort().empty()) {
266  return false;
267  }
268  if (!faceUri.getPath().empty()) {
269  return false;
270  }
271 
272  boost::system::error_code ec;
273  auto addr = ip::addressFromString(unescapeHost(faceUri.getHost()), ec);
274  if (ec) {
275  return false;
276  }
277 
278  bool hasCorrectScheme = (faceUri.getScheme() == m_v4Scheme && addr.is_v4()) ||
279  (faceUri.getScheme() == m_v6Scheme && addr.is_v6());
280  if (!hasCorrectScheme) {
281  return false;
282  }
283 
284  auto checkAddressWithUri = [] (const boost::asio::ip::address& addr,
285  const FaceUri& faceUri) -> bool {
286  if (addr.is_v4() || !addr.to_v6().is_link_local()) {
287  return addr.to_string() == faceUri.getHost();
288  }
289 
290  std::vector<std::string> addrFields, faceUriFields;
291  std::string addrString = addr.to_string();
292  std::string faceUriString = faceUri.getHost();
293 
294  boost::algorithm::split(addrFields, addrString, boost::is_any_of("%"));
295  boost::algorithm::split(faceUriFields, faceUriString, boost::is_any_of("%"));
296  if (addrFields.size() != 2 || faceUriFields.size() != 2) {
297  return false;
298  }
299 
300  if (faceUriFields[1].size() > 2 && faceUriFields[1].compare(0, 2, "25") == 0) {
301  // %25... is accepted, but not a canonical form
302  return false;
303  }
304 
305  return addrFields[0] == faceUriFields[0] &&
306  addrFields[1] == faceUriFields[1];
307  };
308 
309  return checkAddressWithUri(addr, faceUri) && checkAddress(addr).first;
310  }
311 
312  void
313  canonize(const FaceUri& faceUri,
314  const FaceUri::CanonizeSuccessCallback& onSuccess,
315  const FaceUri::CanonizeFailureCallback& onFailure,
316  boost::asio::io_service& io, time::nanoseconds timeout) const override
317  {
318  if (this->isCanonical(faceUri)) {
319  onSuccess(faceUri);
320  return;
321  }
322 
323  // make a copy because caller may modify faceUri
324  auto uri = make_shared<FaceUri>(faceUri);
325  boost::system::error_code ec;
326  auto ipAddress = ip::addressFromString(unescapeHost(faceUri.getHost()), ec);
327  if (!ec) {
328  // No need to resolve IP address if host is already an IP
329  if ((faceUri.getScheme() == m_v4Scheme && !ipAddress.is_v4()) ||
330  (faceUri.getScheme() == m_v6Scheme && !ipAddress.is_v6())) {
331  return onFailure("IPv4/v6 mismatch");
332  }
333 
334  onDnsSuccess(uri, onSuccess, onFailure, ipAddress);
335  }
336  else {
337  dns::AddressSelector addressSelector;
338  if (faceUri.getScheme() == m_v4Scheme) {
339  addressSelector = dns::Ipv4Only();
340  }
341  else if (faceUri.getScheme() == m_v6Scheme) {
342  addressSelector = dns::Ipv6Only();
343  }
344  else {
345  BOOST_ASSERT(faceUri.getScheme() == m_baseScheme);
346  addressSelector = dns::AnyAddress();
347  }
348 
349  dns::asyncResolve(unescapeHost(faceUri.getHost()),
350  bind(&IpHostCanonizeProvider<Protocol>::onDnsSuccess, this, uri, onSuccess, onFailure, _1),
351  bind(&IpHostCanonizeProvider<Protocol>::onDnsFailure, this, uri, onFailure, _1),
352  io, addressSelector, timeout);
353  }
354  }
355 
356 protected:
357  explicit
358  IpHostCanonizeProvider(const std::string& baseScheme,
359  uint16_t defaultUnicastPort = 6363,
360  uint16_t defaultMulticastPort = 56363)
361  : m_baseScheme(baseScheme)
362  , m_v4Scheme(baseScheme + '4')
363  , m_v6Scheme(baseScheme + '6')
364  , m_defaultUnicastPort(defaultUnicastPort)
365  , m_defaultMulticastPort(defaultMulticastPort)
366  {
367  }
368 
369 private:
370  void
371  onDnsSuccess(const shared_ptr<FaceUri>& faceUri,
372  const FaceUri::CanonizeSuccessCallback& onSuccess,
373  const FaceUri::CanonizeFailureCallback& onFailure,
374  const dns::IpAddress& ipAddress) const
375  {
376  bool isOk = false;
377  std::string reason;
378  std::tie(isOk, reason) = this->checkAddress(ipAddress);
379  if (!isOk) {
380  return onFailure(reason);
381  }
382 
383  uint16_t port = 0;
384  if (faceUri->getPort().empty()) {
385  port = ipAddress.is_multicast() ? m_defaultMulticastPort : m_defaultUnicastPort;
386  }
387  else {
388  try {
389  port = boost::lexical_cast<uint16_t>(faceUri->getPort());
390  }
391  catch (const boost::bad_lexical_cast&) {
392  return onFailure("invalid port number '" + faceUri->getPort() + "'");
393  }
394  }
395 
396  FaceUri canonicalUri(typename Protocol::endpoint(ipAddress, port));
397  BOOST_ASSERT(canonicalUri.isCanonical());
398  onSuccess(canonicalUri);
399  }
400 
401  void
402  onDnsFailure(const shared_ptr<FaceUri>& faceUri,
403  const FaceUri::CanonizeFailureCallback& onFailure,
404  const std::string& reason) const
405  {
406  onFailure(reason);
407  }
408 
413  virtual std::pair<bool, std::string>
414  checkAddress(const dns::IpAddress& ipAddress) const
415  {
416  return {true, ""};
417  }
418 
419  static std::string
420  unescapeHost(std::string host)
421  {
422  auto escapePos = host.find("%25");
423  if (escapePos != std::string::npos && escapePos < host.size() - 3) {
424  host = unescape(host);
425  }
426  return host;
427  }
428 
429 private:
430  std::string m_baseScheme;
431  std::string m_v4Scheme;
432  std::string m_v6Scheme;
433  uint16_t m_defaultUnicastPort;
434  uint16_t m_defaultMulticastPort;
435 };
436 
437 class UdpCanonizeProvider : public IpHostCanonizeProvider<boost::asio::ip::udp>
438 {
439 public:
440  UdpCanonizeProvider()
441  : IpHostCanonizeProvider("udp")
442  {
443  }
444 
445 protected:
446  // checkAddress is not overriden:
447  // Although NFD doesn't support IPv6 multicast, it's an implementation limitation.
448  // FaceMgmt protocol allows IPv6 multicast address in UDP.
449 };
450 
451 class TcpCanonizeProvider : public IpHostCanonizeProvider<boost::asio::ip::tcp>
452 {
453 public:
454  TcpCanonizeProvider()
455  : IpHostCanonizeProvider("tcp")
456  {
457  }
458 
459 protected:
460  std::pair<bool, std::string>
461  checkAddress(const dns::IpAddress& ipAddress) const override
462  {
463  if (ipAddress.is_multicast()) {
464  return {false, "cannot use multicast address"};
465  }
466  return {true, ""};
467  }
468 };
469 
470 class EtherCanonizeProvider : public CanonizeProvider
471 {
472 public:
473  std::set<std::string>
474  getSchemes() const override
475  {
476  return {"ether"};
477  }
478 
479  bool
480  isCanonical(const FaceUri& faceUri) const override
481  {
482  if (!faceUri.getPort().empty()) {
483  return false;
484  }
485  if (!faceUri.getPath().empty()) {
486  return false;
487  }
488 
489  auto addr = ethernet::Address::fromString(faceUri.getHost());
490  return addr.toString() == faceUri.getHost();
491  }
492 
493  void
494  canonize(const FaceUri& faceUri,
495  const FaceUri::CanonizeSuccessCallback& onSuccess,
496  const FaceUri::CanonizeFailureCallback& onFailure,
497  boost::asio::io_service& io, time::nanoseconds timeout) const override
498  {
499  auto addr = ethernet::Address::fromString(faceUri.getHost());
500  if (addr.isNull()) {
501  return onFailure("invalid ethernet address '" + faceUri.getHost() + "'");
502  }
503 
504  FaceUri canonicalUri(addr);
505  BOOST_ASSERT(canonicalUri.isCanonical());
506  onSuccess(canonicalUri);
507  }
508 };
509 
510 class DevCanonizeProvider : public CanonizeProvider
511 {
512 public:
513  std::set<std::string>
514  getSchemes() const override
515  {
516  return {"dev"};
517  }
518 
519  bool
520  isCanonical(const FaceUri& faceUri) const override
521  {
522  return !faceUri.getHost().empty() && faceUri.getPort().empty() && faceUri.getPath().empty();
523  }
524 
525  void
526  canonize(const FaceUri& faceUri,
527  const FaceUri::CanonizeSuccessCallback& onSuccess,
528  const FaceUri::CanonizeFailureCallback& onFailure,
529  boost::asio::io_service& io, time::nanoseconds timeout) const override
530  {
531  if (faceUri.getHost().empty()) {
532  onFailure("network interface name is missing");
533  return;
534  }
535  if (!faceUri.getPort().empty()) {
536  onFailure("port number is not allowed");
537  return;
538  }
539  if (!faceUri.getPath().empty() && faceUri.getPath() != "/") { // permit trailing slash only
540  onFailure("path is not allowed");
541  return;
542  }
543 
544  FaceUri canonicalUri = FaceUri::fromDev(faceUri.getHost());
545  BOOST_ASSERT(canonicalUri.isCanonical());
546  onSuccess(canonicalUri);
547  }
548 };
549 
550 class UdpDevCanonizeProvider : public CanonizeProvider
551 {
552 public:
553  std::set<std::string>
554  getSchemes() const override
555  {
556  return {"udp4+dev", "udp6+dev"};
557  }
558 
559  bool
560  isCanonical(const FaceUri& faceUri) const override
561  {
562  if (faceUri.getPort().empty()) {
563  return false;
564  }
565  if (!faceUri.getPath().empty()) {
566  return false;
567  }
568  return true;
569  }
570 
571  void
572  canonize(const FaceUri& faceUri,
573  const FaceUri::CanonizeSuccessCallback& onSuccess,
574  const FaceUri::CanonizeFailureCallback& onFailure,
575  boost::asio::io_service& io, time::nanoseconds timeout) const override
576  {
577  if (this->isCanonical(faceUri)) {
578  onSuccess(faceUri);
579  }
580  else {
581  onFailure("cannot canonize " + faceUri.toString());
582  }
583  }
584 };
585 
586 using CanonizeProviders = boost::mpl::vector<UdpCanonizeProvider*,
587  TcpCanonizeProvider*,
588  EtherCanonizeProvider*,
589  DevCanonizeProvider*,
590  UdpDevCanonizeProvider*>;
591 using CanonizeProviderTable = std::map<std::string, shared_ptr<CanonizeProvider>>;
592 
593 class CanonizeProviderTableInitializer
594 {
595 public:
596  explicit
597  CanonizeProviderTableInitializer(CanonizeProviderTable& providerTable)
598  : m_providerTable(providerTable)
599  {
600  }
601 
602  template<typename CP>
603  void
604  operator()(CP*)
605  {
606  shared_ptr<CanonizeProvider> cp = make_shared<CP>();
607  auto schemes = cp->getSchemes();
608  BOOST_ASSERT(!schemes.empty());
609 
610  for (const auto& scheme : schemes) {
611  BOOST_ASSERT(m_providerTable.count(scheme) == 0);
612  m_providerTable[scheme] = cp;
613  }
614  }
615 
616 private:
617  CanonizeProviderTable& m_providerTable;
618 };
619 
620 static const CanonizeProvider*
621 getCanonizeProvider(const std::string& scheme)
622 {
623  static CanonizeProviderTable providerTable;
624  if (providerTable.empty()) {
625  boost::mpl::for_each<CanonizeProviders>(CanonizeProviderTableInitializer(providerTable));
626  BOOST_ASSERT(!providerTable.empty());
627  }
628 
629  auto it = providerTable.find(scheme);
630  return it == providerTable.end() ? nullptr : it->second.get();
631 }
632 
633 
634 bool
635 FaceUri::canCanonize(const std::string& scheme)
636 {
637  return getCanonizeProvider(scheme) != nullptr;
638 }
639 
640 bool
642 {
643  const CanonizeProvider* cp = getCanonizeProvider(this->getScheme());
644  if (cp == nullptr) {
645  return false;
646  }
647 
648  return cp->isCanonical(*this);
649 }
650 
651 void
653  const CanonizeFailureCallback& onFailure,
654  boost::asio::io_service& io, time::nanoseconds timeout) const
655 {
656  const CanonizeProvider* cp = getCanonizeProvider(this->getScheme());
657  if (cp == nullptr) {
658  if (onFailure) {
659  onFailure("scheme not supported");
660  }
661  return;
662  }
663 
664  static CanonizeSuccessCallback successNop = bind([]{});
665  static CanonizeFailureCallback failureNop = bind([]{});
666  cp->canonize(*this,
667  onSuccess ? onSuccess : successNop,
668  onFailure ? onFailure : failureNop,
669  io, timeout);
670 }
671 
672 } // namespace ndn
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.
Definition: ethernet.cpp:91
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:66
function< void(const std::string &reason)> CanonizeFailureCallback
Definition: face-uri.hpp:164
static FaceUri fromFd(int fd)
create fd FaceUri from file descriptor
Definition: face-uri.cpp:155
BOOST_CONCEPT_ASSERT((boost::EqualityComparable< Data >))
function< void(const FaceUri &)> CanonizeSuccessCallback
Definition: face-uri.hpp:163
static bool canCanonize(const std::string &scheme)
Definition: face-uri.cpp:635
static const CanonizeProvider * getCanonizeProvider(const std::string &scheme)
Definition: face-uri.cpp:621
STL namespace.
function< bool(const IpAddress &address)> AddressSelector
Definition: dns.hpp:40
static FaceUri fromUdpDev(const boost::asio::ip::udp::endpoint &endpoint, const std::string &ifname)
create udp4 or udp6 NIC-associated FaceUri from endpoint and network device name
Definition: face-uri.cpp:180
bool operator!=(const FaceUri &rhs) const
Definition: face-uri.cpp:200
void canonize(const CanonizeSuccessCallback &onSuccess, const CanonizeFailureCallback &onFailure, boost::asio::io_service &io, time::nanoseconds timeout) const
asynchronously convert this FaceUri to canonical form
Definition: face-uri.cpp:652
bool parse(const std::string &uri)
exception-safe parsing
Definition: face-uri.cpp:64
std::string toString() const
write as a string
Definition: face-uri.cpp:206
std::string unescape(const std::string &str)
Decode a percent-encoded string.
std::string toString(char sep= ':') const
Converts the address to a human-readable string.
Definition: ethernet.cpp:77
represents the underlying protocol and address used by a Face
Definition: face-uri.hpp:43
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.
Definition: dns.cpp:132
std::map< std::string, shared_ptr< CanonizeProvider >> CanonizeProviderTable
Definition: face-uri.cpp:591
boost::asio::ip::address addressFromString(const std::string &address, boost::system::error_code &ec)
parse and convert the input string into an IP address
represents an Ethernet hardware address
Definition: ethernet.hpp:52
bool isCanonical() const
determine whether this FaceUri is in canonical form
Definition: face-uri.cpp:641
bool operator==(const FaceUri &rhs) const
Definition: face-uri.cpp:190
const std::string & getScheme() const
get scheme (protocol)
Definition: face-uri.hpp:112
boost::asio::ip::address IpAddress
Definition: dns.hpp:39
std::string to_string(const V &v)
Definition: backports.hpp:84
const std::string & getHost() const
get host (domain)
Definition: face-uri.hpp:119
const std::string & getPort() const
get port
Definition: face-uri.hpp:126
boost::mpl::vector< UdpCanonizeProvider *, TcpCanonizeProvider *, EtherCanonizeProvider *, DevCanonizeProvider *, UdpDevCanonizeProvider * > CanonizeProviders
Definition: face-uri.cpp:590
static FaceUri fromDev(const std::string &ifname)
create dev FaceUri from network device name
Definition: face-uri.cpp:171
const std::string & getPath() const
get path
Definition: face-uri.hpp:133
friend std::ostream & operator<<(std::ostream &os, const FaceUri &uri)
Definition: face-uri.cpp:214