blob: 442837bf8e0a0df31dabb58c44c2a8811ae424fc [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"
Junxiao Shie38b1c42014-04-01 23:45:36 -070027#ifdef HAVE_PCAP
28#include "face/ethernet.hpp"
29#endif // HAVE_PCAP
30
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080031#include <boost/regex.hpp>
32
33NFD_LOG_INIT("FaceUri");
34
35namespace nfd {
36
37FaceUri::FaceUri(const std::string& uri)
38{
Junxiao Shi61e3cc52014-03-03 20:40:28 -070039 if (!parse(uri)) {
40 throw Error("Malformed URI: " + uri);
41 }
42}
43
44FaceUri::FaceUri(const char* uri)
45{
46 if (!parse(uri)) {
47 throw Error("Malformed URI: " + std::string(uri));
48 }
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080049}
50
51bool
52FaceUri::parse(const std::string& uri)
53{
54 m_scheme.clear();
Junxiao Shi61e3cc52014-03-03 20:40:28 -070055 m_host.clear();
56 m_isV6 = false;
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080057 m_port.clear();
Junxiao Shi61e3cc52014-03-03 20:40:28 -070058 m_path.clear();
59
Junxiao Shie38b1c42014-04-01 23:45:36 -070060 static const boost::regex protocolExp("(\\w+\\d?)://([^/]*)(\\/[^?]*)?");
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080061 boost::smatch protocolMatch;
Junxiao Shi61e3cc52014-03-03 20:40:28 -070062 if (!boost::regex_match(uri, protocolMatch, protocolExp)) {
63 return false;
64 }
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080065 m_scheme = protocolMatch[1];
Junxiao Shie38b1c42014-04-01 23:45:36 -070066 const std::string& authority = protocolMatch[2];
Junxiao Shi61e3cc52014-03-03 20:40:28 -070067 m_path = protocolMatch[3];
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080068
Junxiao Shie38b1c42014-04-01 23:45:36 -070069 // pattern for IPv6 address enclosed in [ ], with optional port number
70 static const boost::regex v6Exp("^\\[([a-fA-F0-9:]+)\\](?:\\:(\\d+))?$");
71 // pattern for Ethernet address in standard hex-digits-and-colons notation
72 static const boost::regex etherExp("^((?:[a-fA-F0-9]{1,2}\\:){5}(?:[a-fA-F0-9]{1,2}))$");
73 // 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) ||
84 boost::regex_match(authority, match, v4HostExp)) {
85 m_host = match[1];
86 m_port = match[2];
87 }
88 else {
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080089 return false;
90 }
Junxiao Shi61e3cc52014-03-03 20:40:28 -070091 }
92
93 NFD_LOG_DEBUG("URI [" << uri << "] parsed into: " <<
94 m_scheme << ", " << m_host << ", " << m_port << ", " << m_path);
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -080095 return true;
96}
97
Junxiao Shi61e3cc52014-03-03 20:40:28 -070098FaceUri::FaceUri(const boost::asio::ip::tcp::endpoint& endpoint)
99{
100 m_isV6 = endpoint.address().is_v6();
101 m_scheme = m_isV6 ? "tcp6" : "tcp4";
102 m_host = endpoint.address().to_string();
103 m_port = boost::lexical_cast<std::string>(endpoint.port());
104}
105
106FaceUri::FaceUri(const boost::asio::ip::udp::endpoint& endpoint)
107{
108 m_isV6 = endpoint.address().is_v6();
109 m_scheme = m_isV6 ? "udp6" : "udp4";
110 m_host = endpoint.address().to_string();
111 m_port = boost::lexical_cast<std::string>(endpoint.port());
112}
113
Junxiao Shie38b1c42014-04-01 23:45:36 -0700114#ifdef HAVE_UNIX_SOCKETS
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700115FaceUri::FaceUri(const boost::asio::local::stream_protocol::endpoint& endpoint)
116 : m_isV6(false)
117{
118 m_scheme = "unix";
119 m_path = endpoint.path();
120}
Junxiao Shie38b1c42014-04-01 23:45:36 -0700121#endif // HAVE_UNIX_SOCKETS
122
123FaceUri
124FaceUri::fromFd(int fd)
125{
126 FaceUri uri;
127 uri.m_scheme = "fd";
128 uri.m_host = boost::lexical_cast<std::string>(fd);
129 return uri;
130}
131
132#ifdef HAVE_PCAP
133FaceUri::FaceUri(const ethernet::Address& address)
134 : m_isV6(false)
135{
136 m_scheme = "ether";
137 m_host = address.toString(':');
138}
139#endif // HAVE_PCAP
140
141FaceUri
142FaceUri::fromDev(const std::string& ifname)
143{
144 FaceUri uri;
145 uri.m_scheme = "dev";
146 uri.m_host = ifname;
147 return uri;
148}
Junxiao Shi61e3cc52014-03-03 20:40:28 -0700149
Alexander Afanasyev7b9347b2014-02-28 08:37:56 -0800150} // namespace nfd