blob: 5cfaf72097e1cae76e9911c6ceebf9c158b03f04 [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,
8 * Beijing Institute of Technology
9 *
10 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 **/
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080024
25#include "face-uri.hpp"
26#include "core/logger.hpp"
Davide Pesavento1bdef282014-04-08 20:59:50 +020027
Junxiao Shie38b1c42014-04-01 23:45:36 -070028#ifdef HAVE_PCAP
29#include "face/ethernet.hpp"
30#endif // HAVE_PCAP
31
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080032#include <boost/regex.hpp>
33
34NFD_LOG_INIT("FaceUri");
35
36namespace nfd {
37
38FaceUri::FaceUri(const std::string& uri)
39{
Junxiao Shi61e3cc52014-03-03 20:40:28 -070040 if (!parse(uri)) {
41 throw Error("Malformed URI: " + uri);
42 }
43}
44
45FaceUri::FaceUri(const char* uri)
46{
47 if (!parse(uri)) {
48 throw Error("Malformed URI: " + std::string(uri));
49 }
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080050}
51
52bool
53FaceUri::parse(const std::string& uri)
54{
55 m_scheme.clear();
Junxiao Shi61e3cc52014-03-03 20:40:28 -070056 m_host.clear();
57 m_isV6 = false;
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080058 m_port.clear();
Junxiao Shi61e3cc52014-03-03 20:40:28 -070059 m_path.clear();
60
Junxiao Shie38b1c42014-04-01 23:45:36 -070061 static const boost::regex protocolExp("(\\w+\\d?)://([^/]*)(\\/[^?]*)?");
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080062 boost::smatch protocolMatch;
Junxiao Shi61e3cc52014-03-03 20:40:28 -070063 if (!boost::regex_match(uri, protocolMatch, protocolExp)) {
64 return false;
65 }
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080066 m_scheme = protocolMatch[1];
Junxiao Shie38b1c42014-04-01 23:45:36 -070067 const std::string& authority = protocolMatch[2];
Junxiao Shi61e3cc52014-03-03 20:40:28 -070068 m_path = protocolMatch[3];
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080069
Junxiao Shie38b1c42014-04-01 23:45:36 -070070 // pattern for IPv6 address enclosed in [ ], with optional port number
71 static const boost::regex v6Exp("^\\[([a-fA-F0-9:]+)\\](?:\\:(\\d+))?$");
72 // pattern for Ethernet address in standard hex-digits-and-colons notation
73 static const boost::regex etherExp("^((?:[a-fA-F0-9]{1,2}\\:){5}(?:[a-fA-F0-9]{1,2}))$");
74 // pattern for IPv4/hostname/fd/ifname, with optional port number
75 static const boost::regex v4HostExp("^([^:]+)(?:\\:(\\d+))?$");
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080076
Junxiao Shie38b1c42014-04-01 23:45:36 -070077 if (authority.empty()) {
78 // UNIX, internal
Junxiao Shi61e3cc52014-03-03 20:40:28 -070079 }
80 else {
Junxiao Shie38b1c42014-04-01 23:45:36 -070081 boost::smatch match;
82 m_isV6 = boost::regex_match(authority, match, v6Exp);
83 if (m_isV6 ||
84 boost::regex_match(authority, match, etherExp) ||
85 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
Junxiao Shie38b1c42014-04-01 23:45:36 -0700115#ifdef HAVE_UNIX_SOCKETS
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700116FaceUri::FaceUri(const boost::asio::local::stream_protocol::endpoint& endpoint)
117 : m_isV6(false)
118{
119 m_scheme = "unix";
120 m_path = endpoint.path();
121}
Junxiao Shie38b1c42014-04-01 23:45:36 -0700122#endif // HAVE_UNIX_SOCKETS
123
124FaceUri
125FaceUri::fromFd(int fd)
126{
127 FaceUri uri;
128 uri.m_scheme = "fd";
129 uri.m_host = boost::lexical_cast<std::string>(fd);
130 return uri;
131}
132
133#ifdef HAVE_PCAP
134FaceUri::FaceUri(const ethernet::Address& address)
135 : m_isV6(false)
136{
137 m_scheme = "ether";
Davide Pesaventoedae3532014-04-09 03:07:11 +0200138 m_host = address.toString();
Junxiao Shie38b1c42014-04-01 23:45:36 -0700139}
140#endif // HAVE_PCAP
141
142FaceUri
143FaceUri::fromDev(const std::string& ifname)
144{
145 FaceUri uri;
146 uri.m_scheme = "dev";
147 uri.m_host = ifname;
148 return uri;
149}
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700150
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -0800151} // namespace nfd