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  if (s.size() <= 64)
38  {
39  std::stringstream is(boost::trim_copy(s));
40  Endpoint endpoint;
41  is >> endpoint;
42  if (!is.fail() && is.rdbuf()->in_avail() == 0)
43  return endpoint;
44  }
45  return {};
46 }
47 
50 {
51  if (std::optional<Endpoint> const result = from_string_checked(s))
52  return *result;
53  return Endpoint{};
54 }
55 
58 {
59  std::string s;
60  s.reserve(
61  (address().is_v6() ? INET6_ADDRSTRLEN - 1 : 15) +
62  (port() == 0 ? 0 : 6 + (address().is_v6() ? 2 : 0)));
63 
64  if (port() != 0 && address().is_v6())
65  s += '[';
66  s += address().to_string();
67  if (port())
68  {
69  if (address().is_v6())
70  s += ']';
71  s += ":" + std::to_string(port());
72  }
73 
74  return s;
75 }
76 
77 bool
78 operator==(Endpoint const& lhs, Endpoint const& rhs)
79 {
80  return lhs.address() == rhs.address() && lhs.port() == rhs.port();
81 }
82 
83 bool
84 operator<(Endpoint const& lhs, Endpoint const& rhs)
85 {
86  if (lhs.address() < rhs.address())
87  return true;
88  if (lhs.address() > rhs.address())
89  return false;
90  return lhs.port() < rhs.port();
91 }
92 
93 //------------------------------------------------------------------------------
94 
97 {
98  std::string addrStr;
99  // valid addresses only need INET6_ADDRSTRLEN-1 chars, but allow the extra
100  // char to check for invalid lengths
101  addrStr.reserve(INET6_ADDRSTRLEN);
102  char i{0};
103  char readTo{0};
104  is.get(i);
105  if (i == '[') // we are an IPv6 endpoint
106  readTo = ']';
107  else
108  addrStr += i;
109 
110  while (is && is.rdbuf()->in_avail() > 0 && is.get(i))
111  {
112  // NOTE: There is a legacy data format
113  // that allowed space to be used as address / port separator
114  // so we continue to honor that here by assuming we are at the end
115  // of the address portion if we hit a space (or the separator
116  // we were expecting to see)
117  if (isspace(static_cast<unsigned char>(i)) || (readTo && i == readTo))
118  break;
119 
120  if ((i == '.') || (i >= '0' && i <= ':') || (i >= 'a' && i <= 'f') ||
121  (i >= 'A' && i <= 'F'))
122  {
123  addrStr += i;
124 
125  // don't exceed a reasonable length...
126  if (addrStr.size() == INET6_ADDRSTRLEN ||
127  (readTo && readTo == ':' && addrStr.size() > 15))
128  {
129  is.setstate(std::ios_base::failbit);
130  return is;
131  }
132 
133  if (!readTo && (i == '.' || i == ':'))
134  {
135  // if we see a dot first, must be IPv4
136  // otherwise must be non-bracketed IPv6
137  readTo = (i == '.') ? ':' : ' ';
138  }
139  }
140  else // invalid char
141  {
142  is.unget();
143  is.setstate(std::ios_base::failbit);
144  return is;
145  }
146  }
147 
148  if (readTo == ']' && is.rdbuf()->in_avail() > 0)
149  {
150  is.get(i);
151  if (!(isspace(static_cast<unsigned char>(i)) || i == ':'))
152  {
153  is.unget();
154  is.setstate(std::ios_base::failbit);
155  return is;
156  }
157  }
158 
159  boost::system::error_code ec;
160  auto addr = Address::from_string(addrStr, ec);
161  if (ec)
162  {
163  is.setstate(std::ios_base::failbit);
164  return is;
165  }
166 
167  if (is.rdbuf()->in_avail() > 0)
168  {
169  Port port;
170  is >> port;
171  if (is.fail())
172  return is;
173  endpoint = Endpoint(addr, port);
174  }
175  else
176  endpoint = Endpoint(addr);
177 
178  return is;
179 }
180 
181 } // namespace IP
182 } // 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:57
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:96
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:78
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:84
std::stringstream::fail
T fail(T... args)
beast::IP::Endpoint::from_string
static Endpoint from_string(std::string const &s)
Definition: IPEndpoint.cpp:49
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:641