blob: 635d8d3e398c2ce48eecaf39984fb6dd4a07d74a [file] [log] [blame]
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi3ffe66d2014-11-06 15:37:59 -07003 * Copyright (c) 2014, 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
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Junxiao Shi3ffe66d2014-11-06 15:37:59 -070024 */
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080025
26#include "face-uri.hpp"
27#include "core/logger.hpp"
Davide Pesavento1bdef282014-04-08 20:59:50 +020028
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080029#include <boost/regex.hpp>
30
31NFD_LOG_INIT("FaceUri");
32
33namespace nfd {
34
35FaceUri::FaceUri(const std::string& uri)
36{
Junxiao Shi61e3cc52014-03-03 20:40:28 -070037 if (!parse(uri)) {
38 throw Error("Malformed URI: " + uri);
39 }
40}
41
42FaceUri::FaceUri(const char* uri)
43{
44 if (!parse(uri)) {
45 throw Error("Malformed URI: " + std::string(uri));
46 }
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080047}
48
49bool
50FaceUri::parse(const std::string& uri)
51{
52 m_scheme.clear();
Junxiao Shi61e3cc52014-03-03 20:40:28 -070053 m_host.clear();
54 m_isV6 = false;
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080055 m_port.clear();
Junxiao Shi61e3cc52014-03-03 20:40:28 -070056 m_path.clear();
57
Junxiao Shie38b1c42014-04-01 23:45:36 -070058 static const boost::regex protocolExp("(\\w+\\d?)://([^/]*)(\\/[^?]*)?");
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080059 boost::smatch protocolMatch;
Junxiao Shi61e3cc52014-03-03 20:40:28 -070060 if (!boost::regex_match(uri, protocolMatch, protocolExp)) {
61 return false;
62 }
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080063 m_scheme = protocolMatch[1];
Junxiao Shie38b1c42014-04-01 23:45:36 -070064 const std::string& authority = protocolMatch[2];
Junxiao Shi61e3cc52014-03-03 20:40:28 -070065 m_path = protocolMatch[3];
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080066
Junxiao Shie38b1c42014-04-01 23:45:36 -070067 // pattern for IPv6 address enclosed in [ ], with optional port number
68 static const boost::regex v6Exp("^\\[([a-fA-F0-9:]+)\\](?:\\:(\\d+))?$");
69 // pattern for Ethernet address in standard hex-digits-and-colons notation
Chengyu Fan514ed5e2014-04-17 13:07:30 -060070 static const boost::regex etherExp("^\\[((?:[a-fA-F0-9]{1,2}\\:){5}(?:[a-fA-F0-9]{1,2}))\\]$");
Junxiao Shi5cc1e342014-05-29 06:32:16 -070071 // pattern for IPv4-mapped IPv6 address, with optional port number
72 static const boost::regex v4MappedV6Exp("^\\[::ffff:(\\d+(?:\\.\\d+){3})\\](?:\\:(\\d+))?$");
Junxiao Shie38b1c42014-04-01 23:45:36 -070073 // pattern for IPv4/hostname/fd/ifname, with optional port number
74 static const boost::regex v4HostExp("^([^:]+)(?:\\:(\\d+))?$");
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080075
Junxiao Shie38b1c42014-04-01 23:45:36 -070076 if (authority.empty()) {
77 // UNIX, internal
Junxiao Shi61e3cc52014-03-03 20:40:28 -070078 }
79 else {
Junxiao Shie38b1c42014-04-01 23:45:36 -070080 boost::smatch match;
81 m_isV6 = boost::regex_match(authority, match, v6Exp);
82 if (m_isV6 ||
83 boost::regex_match(authority, match, etherExp) ||
Junxiao Shi5cc1e342014-05-29 06:32:16 -070084 boost::regex_match(authority, match, v4MappedV6Exp) ||
Junxiao Shie38b1c42014-04-01 23:45:36 -070085 boost::regex_match(authority, match, v4HostExp)) {
86 m_host = match[1];
87 m_port = match[2];
88 }
89 else {
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080090 return false;
91 }
Junxiao Shi61e3cc52014-03-03 20:40:28 -070092 }
93
94 NFD_LOG_DEBUG("URI [" << uri << "] parsed into: " <<
95 m_scheme << ", " << m_host << ", " << m_port << ", " << m_path);
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080096 return true;
97}
98
Junxiao Shi61e3cc52014-03-03 20:40:28 -070099FaceUri::FaceUri(const boost::asio::ip::tcp::endpoint& endpoint)
100{
101 m_isV6 = endpoint.address().is_v6();
102 m_scheme = m_isV6 ? "tcp6" : "tcp4";
103 m_host = endpoint.address().to_string();
104 m_port = boost::lexical_cast<std::string>(endpoint.port());
105}
106
107FaceUri::FaceUri(const boost::asio::ip::udp::endpoint& endpoint)
108{
109 m_isV6 = endpoint.address().is_v6();
110 m_scheme = m_isV6 ? "udp6" : "udp4";
111 m_host = endpoint.address().to_string();
112 m_port = boost::lexical_cast<std::string>(endpoint.port());
113}
114
Wentao Shang53df1632014-04-21 12:01:32 -0700115FaceUri::FaceUri(const boost::asio::ip::tcp::endpoint& endpoint, const std::string& scheme)
116 : m_scheme(scheme)
117{
118 m_isV6 = endpoint.address().is_v6();
119 m_host = endpoint.address().to_string();
120 m_port = boost::lexical_cast<std::string>(endpoint.port());
121}
122
Junxiao Shie38b1c42014-04-01 23:45:36 -0700123#ifdef HAVE_UNIX_SOCKETS
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700124FaceUri::FaceUri(const boost::asio::local::stream_protocol::endpoint& endpoint)
125 : m_isV6(false)
126{
127 m_scheme = "unix";
128 m_path = endpoint.path();
129}
Junxiao Shie38b1c42014-04-01 23:45:36 -0700130#endif // HAVE_UNIX_SOCKETS
131
132FaceUri
133FaceUri::fromFd(int fd)
134{
135 FaceUri uri;
136 uri.m_scheme = "fd";
137 uri.m_host = boost::lexical_cast<std::string>(fd);
138 return uri;
139}
140
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700141#ifdef HAVE_LIBPCAP
Junxiao Shie38b1c42014-04-01 23:45:36 -0700142FaceUri::FaceUri(const ethernet::Address& address)
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600143 : m_isV6(true)
Junxiao Shie38b1c42014-04-01 23:45:36 -0700144{
145 m_scheme = "ether";
Davide Pesaventoedae3532014-04-09 03:07:11 +0200146 m_host = address.toString();
Junxiao Shie38b1c42014-04-01 23:45:36 -0700147}
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700148#endif // HAVE_LIBPCAP
Junxiao Shie38b1c42014-04-01 23:45:36 -0700149
150FaceUri
151FaceUri::fromDev(const std::string& ifname)
152{
153 FaceUri uri;
154 uri.m_scheme = "dev";
155 uri.m_host = ifname;
156 return uri;
157}
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700158
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -0800159} // namespace nfd