rippled
IPEndpoint.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of Beast: https://github.com/vinniefalco/Beast
4  Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/beast/net/IPEndpoint.h>
21 #include <boost/algorithm/string.hpp>
22 
23 namespace beast {
24 namespace IP {
25 
26 Endpoint::Endpoint() : m_port(0)
27 {
28 }
29 
30 Endpoint::Endpoint(Address const& addr, Port port) : m_addr(addr), m_port(port)
31 {
32 }
33 
36 {
37  std::stringstream is(boost::trim_copy(s));
38  Endpoint endpoint;
39  is >> endpoint;
40  if (!is.fail() && is.rdbuf()->in_avail() == 0)
41  return endpoint;
42  return {};
43 }
44 
47 {
48  if (std::optional<Endpoint> const result = from_string_checked(s))
49  return *result;
50  return Endpoint{};
51 }
52 
55 {
56  std::string s;
57  s.reserve(
58  (address().is_v6() ? INET6_ADDRSTRLEN - 1 : 15) +
59  (port() == 0 ? 0 : 6 + (address().is_v6() ? 2 : 0)));
60 
61  if (port() != 0 && address().is_v6())
62  s += '[';
63  s += address().to_string();
64  if (port())
65  {
66  if (address().is_v6())
67  s += ']';
68  s += ":" + std::to_string(port());
69  }
70 
71  return s;
72 }
73 
74 bool
75 operator==(Endpoint const& lhs, Endpoint const& rhs)
76 {
77  return lhs.address() == rhs.address() && lhs.port() == rhs.port();
78 }
79 
80 bool
81 operator<(Endpoint const& lhs, Endpoint const& rhs)
82 {
83  if (lhs.address() < rhs.address())
84  return true;
85  if (lhs.address() > rhs.address())
86  return false;
87  return lhs.port() < rhs.port();
88 }
89 
90 //------------------------------------------------------------------------------
91 
94 {
95  std::string addrStr;
96  // valid addresses only need INET6_ADDRSTRLEN-1 chars, but allow the extra
97  // char to check for invalid lengths
98  addrStr.reserve(INET6_ADDRSTRLEN);
99  char i{0};
100  char readTo{0};
101  is.get(i);
102  if (i == '[') // we are an IPv6 endpoint
103  readTo = ']';
104  else
105  addrStr += i;
106 
107  while (is && is.rdbuf()->in_avail() > 0 && is.get(i))
108  {
109  // NOTE: There is a legacy data format
110  // that allowed space to be used as address / port separator
111  // so we continue to honor that here by assuming we are at the end
112  // of the address portion if we hit a space (or the separator
113  // we were expecting to see)
114  if (isspace(static_cast<unsigned char>(i)) || (readTo && i == readTo))
115  break;
116 
117  if ((i == '.') || (i >= '0' && i <= ':') || (i >= 'a' && i <= 'f') ||
118  (i >= 'A' && i <= 'F'))
119  {
120  addrStr += i;
121 
122  // don't exceed a reasonable length...
123  if (addrStr.size() == INET6_ADDRSTRLEN ||
124  (readTo && readTo == ':' && addrStr.size() > 15))
125  {
126  is.setstate(std::ios_base::failbit);
127  return is;
128  }
129 
130  if (!readTo && (i == '.' || i == ':'))
131  {
132  // if we see a dot first, must be IPv4
133  // otherwise must be non-bracketed IPv6
134  readTo = (i == '.') ? ':' : ' ';
135  }
136  }
137  else // invalid char
138  {
139  is.unget();
140  is.setstate(std::ios_base::failbit);
141  return is;
142  }
143  }
144 
145  if (readTo == ']' && is.rdbuf()->in_avail() > 0)
146  {
147  is.get(i);
148  if (!(isspace(static_cast<unsigned char>(i)) || i == ':'))
149  {
150  is.unget();
151  is.setstate(std::ios_base::failbit);
152  return is;
153  }
154  }
155 
156  boost::system::error_code ec;
157  auto addr = Address::from_string(addrStr, ec);
158  if (ec)
159  {
160  is.setstate(std::ios_base::failbit);
161  return is;
162  }
163 
164  if (is.rdbuf()->in_avail() > 0)
165  {
166  Port port;
167  is >> port;
168  if (is.fail())
169  return is;
170  endpoint = Endpoint(addr, port);
171  }
172  else
173  endpoint = Endpoint(addr);
174 
175  return is;
176 }
177 
178 } // namespace IP
179 } // namespace beast
std::istream::setstate
T setstate(T... args)
std::stringstream::rdbuf
T rdbuf(T... args)
std::string
STL class.
beast::IP::Endpoint::to_string
std::string to_string() const
Returns a string representing the endpoint.
Definition: IPEndpoint.cpp:54
std::string::reserve
T reserve(T... args)
std::string::size
T size(T... args)
beast::IP::operator>>
std::istream & operator>>(std::istream &is, Endpoint &endpoint)
Input stream conversion.
Definition: IPEndpoint.cpp:93
beast::IP::Endpoint::is_v6
bool is_v6() const
Definition: IPEndpoint.h:89
beast::IP::Endpoint::address
Address const & address() const
Returns the address portion of this endpoint.
Definition: IPEndpoint.h:76
std::stringstream
STL class.
std::istream::get
T get(T... args)
beast::IP::operator==
bool operator==(Endpoint const &lhs, Endpoint const &rhs)
Definition: IPEndpoint.cpp:75
beast::IP::Address
boost::asio::ip::address Address
Definition: IPAddress.h:41
beast::IP::Endpoint::Endpoint
Endpoint()
Create an unspecified endpoint.
Definition: IPEndpoint.cpp:26
std::to_string
T to_string(T... args)
beast::IP::Endpoint::port
Port port() const
Returns the port number on the endpoint.
Definition: IPEndpoint.h:62
std::uint16_t
beast::IP::operator<
bool operator<(Endpoint const &lhs, Endpoint const &rhs)
Definition: IPEndpoint.cpp:81
std::stringstream::fail
T fail(T... args)
beast::IP::Endpoint::from_string
static Endpoint from_string(std::string const &s)
Definition: IPEndpoint.cpp:46
std::optional
beast::IP::Endpoint
A version-independent IP address and port combination.
Definition: IPEndpoint.h:38
std::istream::unget
T unget(T... args)
std::istream
STL class.
beast::IP::Endpoint::from_string_checked
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
Definition: IPEndpoint.cpp:35
beast
Definition: base_uint.h:654