blob: 47c265efb12f986070e6c594f0e27f6f9f86f2a8 [file] [log] [blame]
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -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,
Junxiao Shi5cc1e342014-05-29 06:32:16 -07008 * 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/>.
24 **/
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 Afanasyev885a85b2014-04-12 21:01:13 -070029#ifdef HAVE_LIBPCAP
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070030#include "ethernet.hpp"
Alexander Afanasyev885a85b2014-04-12 21:01:13 -070031#endif // HAVE_LIBPCAP
Junxiao Shie38b1c42014-04-01 23:45:36 -070032
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080033#include <boost/regex.hpp>
34
35NFD_LOG_INIT("FaceUri");
36
37namespace nfd {
38
39FaceUri::FaceUri(const std::string& uri)
40{
Junxiao Shi61e3cc52014-03-03 20:40:28 -070041 if (!parse(uri)) {
42 throw Error("Malformed URI: " + uri);
43 }
44}
45
46FaceUri::FaceUri(const char* uri)
47{
48 if (!parse(uri)) {
49 throw Error("Malformed URI: " + std::string(uri));
50 }
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080051}
52
53bool
54FaceUri::parse(const std::string& uri)
55{
56 m_scheme.clear();
Junxiao Shi61e3cc52014-03-03 20:40:28 -070057 m_host.clear();
58 m_isV6 = false;
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080059 m_port.clear();
Junxiao Shi61e3cc52014-03-03 20:40:28 -070060 m_path.clear();
61
Junxiao Shie38b1c42014-04-01 23:45:36 -070062 static const boost::regex protocolExp("(\\w+\\d?)://([^/]*)(\\/[^?]*)?");
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080063 boost::smatch protocolMatch;
Junxiao Shi61e3cc52014-03-03 20:40:28 -070064 if (!boost::regex_match(uri, protocolMatch, protocolExp)) {
65 return false;
66 }
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080067 m_scheme = protocolMatch[1];
Junxiao Shie38b1c42014-04-01 23:45:36 -070068 const std::string& authority = protocolMatch[2];
Junxiao Shi61e3cc52014-03-03 20:40:28 -070069 m_path = protocolMatch[3];
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080070
Junxiao Shie38b1c42014-04-01 23:45:36 -070071 // pattern for IPv6 address enclosed in [ ], with optional port number
72 static const boost::regex v6Exp("^\\[([a-fA-F0-9:]+)\\](?:\\:(\\d+))?$");
73 // pattern for Ethernet address in standard hex-digits-and-colons notation
Chengyu Fan514ed5e2014-04-17 13:07:30 -060074 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 -070075 // pattern for IPv4-mapped IPv6 address, with optional port number
76 static const boost::regex v4MappedV6Exp("^\\[::ffff:(\\d+(?:\\.\\d+){3})\\](?:\\:(\\d+))?$");
Junxiao Shie38b1c42014-04-01 23:45:36 -070077 // pattern for IPv4/hostname/fd/ifname, with optional port number
78 static const boost::regex v4HostExp("^([^:]+)(?:\\:(\\d+))?$");
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080079
Junxiao Shie38b1c42014-04-01 23:45:36 -070080 if (authority.empty()) {
81 // UNIX, internal
Junxiao Shi61e3cc52014-03-03 20:40:28 -070082 }
83 else {
Junxiao Shie38b1c42014-04-01 23:45:36 -070084 boost::smatch match;
85 m_isV6 = boost::regex_match(authority, match, v6Exp);
86 if (m_isV6 ||
87 boost::regex_match(authority, match, etherExp) ||
Junxiao Shi5cc1e342014-05-29 06:32:16 -070088 boost::regex_match(authority, match, v4MappedV6Exp) ||
Junxiao Shie38b1c42014-04-01 23:45:36 -070089 boost::regex_match(authority, match, v4HostExp)) {
90 m_host = match[1];
91 m_port = match[2];
92 }
93 else {
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080094 return false;
95 }
Junxiao Shi61e3cc52014-03-03 20:40:28 -070096 }
97
98 NFD_LOG_DEBUG("URI [" << uri << "] parsed into: " <<
99 m_scheme << ", " << m_host << ", " << m_port << ", " << m_path);
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -0800100 return true;
101}
102
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700103FaceUri::FaceUri(const boost::asio::ip::tcp::endpoint& endpoint)
104{
105 m_isV6 = endpoint.address().is_v6();
106 m_scheme = m_isV6 ? "tcp6" : "tcp4";
107 m_host = endpoint.address().to_string();
108 m_port = boost::lexical_cast<std::string>(endpoint.port());
109}
110
111FaceUri::FaceUri(const boost::asio::ip::udp::endpoint& endpoint)
112{
113 m_isV6 = endpoint.address().is_v6();
114 m_scheme = m_isV6 ? "udp6" : "udp4";
115 m_host = endpoint.address().to_string();
116 m_port = boost::lexical_cast<std::string>(endpoint.port());
117}
118
Wentao Shang53df1632014-04-21 12:01:32 -0700119FaceUri::FaceUri(const boost::asio::ip::tcp::endpoint& endpoint, const std::string& scheme)
120 : m_scheme(scheme)
121{
122 m_isV6 = endpoint.address().is_v6();
123 m_host = endpoint.address().to_string();
124 m_port = boost::lexical_cast<std::string>(endpoint.port());
125}
126
Junxiao Shie38b1c42014-04-01 23:45:36 -0700127#ifdef HAVE_UNIX_SOCKETS
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700128FaceUri::FaceUri(const boost::asio::local::stream_protocol::endpoint& endpoint)
129 : m_isV6(false)
130{
131 m_scheme = "unix";
132 m_path = endpoint.path();
133}
Junxiao Shie38b1c42014-04-01 23:45:36 -0700134#endif // HAVE_UNIX_SOCKETS
135
136FaceUri
137FaceUri::fromFd(int fd)
138{
139 FaceUri uri;
140 uri.m_scheme = "fd";
141 uri.m_host = boost::lexical_cast<std::string>(fd);
142 return uri;
143}
144
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700145#ifdef HAVE_LIBPCAP
Junxiao Shie38b1c42014-04-01 23:45:36 -0700146FaceUri::FaceUri(const ethernet::Address& address)
Chengyu Fan514ed5e2014-04-17 13:07:30 -0600147 : m_isV6(true)
Junxiao Shie38b1c42014-04-01 23:45:36 -0700148{
149 m_scheme = "ether";
Davide Pesaventoedae3532014-04-09 03:07:11 +0200150 m_host = address.toString();
Junxiao Shie38b1c42014-04-01 23:45:36 -0700151}
Alexander Afanasyev885a85b2014-04-12 21:01:13 -0700152#endif // HAVE_LIBPCAP
Junxiao Shie38b1c42014-04-01 23:45:36 -0700153
154FaceUri
155FaceUri::fromDev(const std::string& ifname)
156{
157 FaceUri uri;
158 uri.m_scheme = "dev";
159 uri.m_host = ifname;
160 return uri;
161}
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700162
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -0800163} // namespace nfd