address-converter.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 "address-converter.hpp"
29 
30 #if BOOST_VERSION < 105800
31 #include <boost/algorithm/string.hpp>
32 #include <boost/lexical_cast.hpp>
33 #include <vector>
34 #endif // BOOST_VERSION < 105800
35 
36 #include <net/if.h> // for if_nametoindex and if_indextoname
37 
38 namespace ndn {
39 namespace ip {
40 
42 scopeNameFromId(unsigned int scopeId)
43 {
44  char buffer[IFNAMSIZ];
45  auto scopeName = if_indextoname(scopeId, buffer);
46  if (scopeName != nullptr) {
47  return std::string(scopeName);
48  }
49  return nullopt;
50 }
51 
52 #if BOOST_VERSION < 105800
53 static unsigned int
54 scopeIdFromString(const std::string& scope)
55 {
56  auto id = if_nametoindex(scope.c_str());
57  if (id != 0) {
58  return id;
59  }
60 
61  // cannot find a corresponding index, assume it's not a name but an interface index
62  try {
63  return boost::lexical_cast<unsigned int>(scope);
64  }
65  catch (const boost::bad_lexical_cast&) {
66  return 0;
67  }
68 }
69 
70 struct ParsedAddress
71 {
72  boost::asio::ip::address addr;
73  std::string scope;
74 };
75 
76 static ParsedAddress
77 parseAddressFromString(const std::string& address, boost::system::error_code& ec)
78 {
79  std::vector<std::string> parseResult;
80  boost::algorithm::split(parseResult, address, boost::is_any_of("%"));
81  auto addr = boost::asio::ip::address::from_string(parseResult[0], ec);
82 
83  switch (parseResult.size()) {
84  case 1:
85  // regular address
86  return {addr, ""};
87  case 2:
88  // the presence of % in either an IPv4 address or a regular IPv6 address is invalid
89  if (!ec && addr.is_v6() && addr.to_v6().is_link_local()) {
90  return {addr, parseResult[1]};
91  }
93  default:
94  ec = boost::asio::error::invalid_argument;
95  return {};
96  }
97 }
98 #endif // BOOST_VERSION < 105800
99 
100 boost::asio::ip::address
101 addressFromString(const std::string& address, boost::system::error_code& ec)
102 {
103  // boost < 1.58 cannot recognize scope-id in link-local IPv6 address
104 #if BOOST_VERSION < 105800
105  auto parsedAddress = parseAddressFromString(address, ec);
106  if (ec || parsedAddress.addr.is_v4()) {
107  return parsedAddress.addr;
108  }
109  auto addr = parsedAddress.addr.to_v6();
110  addr.scope_id(scopeIdFromString(parsedAddress.scope));
111  return addr;
112 #else
113  return boost::asio::ip::address::from_string(address, ec);
114 #endif // BOOST_VERSION < 105800
115 }
116 
117 boost::asio::ip::address
118 addressFromString(const std::string& address)
119 {
120  boost::system::error_code ec;
121  auto addr = addressFromString(address, ec);
122  if (ec) {
123  BOOST_THROW_EXCEPTION(boost::system::system_error(ec));
124  }
125  return addr;
126 }
127 
128 boost::asio::ip::address_v6
129 addressV6FromString(const std::string& address, boost::system::error_code& ec)
130 {
131  auto addr = addressFromString(address, ec);
132  if (ec || addr.is_v4()) {
133  ec = boost::asio::error::invalid_argument;
134  return {};
135  }
136  return addr.to_v6();
137 }
138 
139 boost::asio::ip::address_v6
140 addressV6FromString(const std::string& address)
141 {
142  boost::system::error_code ec;
143  auto addr = addressV6FromString(address, ec);
144  if (ec) {
145  BOOST_THROW_EXCEPTION(boost::system::system_error(ec));
146  }
147  return addr;
148 }
149 
150 } // namespace ip
151 } // namespace ndn
constexpr nullopt_t nullopt
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:66
static unsigned int scopeIdFromString(const std::string &scope)
static ParsedAddress parseAddressFromString(const std::string &address, boost::system::error_code &ec)
boost::asio::ip::address addressFromString(const std::string &address, boost::system::error_code &ec)
parse and convert the input string into an IP address
#define NDN_CXX_FALLTHROUGH
Definition: backports.hpp:63
boost::asio::ip::address_v6 addressV6FromString(const std::string &address, boost::system::error_code &ec)
parse and convert the input string into an IPv6 address
optional< std::string > scopeNameFromId(unsigned int scopeId)
Convert scope ID of IPv6 address into interface name.