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 
27  : m_port (0)
28 {
29 }
30 
31 Endpoint::Endpoint (Address const& addr, Port port)
32  : m_addr (addr)
33  , m_port (port)
34 {
35 }
36 
37 boost::optional<Endpoint> Endpoint::from_string_checked (std::string const& s)
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  return {};
45 }
46 
48 {
49  if (boost::optional<Endpoint> const result = from_string_checked(s))
50  return *result;
51  return Endpoint{};
52 }
53 
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 operator== (Endpoint const& lhs, Endpoint const& rhs)
75 {
76  return lhs.address() == rhs.address() &&
77  lhs.port() == rhs.port();
78 }
79 
80 bool operator< (Endpoint const& lhs, Endpoint const& rhs)
81 {
82  if (lhs.address() < rhs.address())
83  return true;
84  if (lhs.address() > rhs.address())
85  return false;
86  return lhs.port() < rhs.port();
87 }
88 
89 //------------------------------------------------------------------------------
90 
92 {
93  std::string addrStr;
94  // valid addresses only need INET6_ADDRSTRLEN-1 chars, but allow the extra
95  // char to check for invalid lengths
96  addrStr.reserve(INET6_ADDRSTRLEN);
97  char i {0};
98  char readTo {0};
99  is.get(i);
100  if (i == '[') // we are an IPv6 endpoint
101  readTo = ']';
102  else
103  addrStr+=i;
104 
105  while (is && is.rdbuf()->in_avail() > 0 && is.get(i))
106  {
107  // NOTE: There is a legacy data format
108  // that allowed space to be used as address / port separator
109  // so we continue to honor that here by assuming we are at the end
110  // of the address portion if we hit a space (or the separator
111  // we were expecting to see)
112  if (isspace(static_cast<unsigned char>(i)) || (readTo && i == readTo))
113  break;
114 
115  if ((i == '.') ||
116  (i >= '0' && i <= ':') ||
117  (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 }
179 }
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:91
beast::IP::Endpoint::is_v6
bool is_v6() const
Definition: IPEndpoint.h:74
beast::IP::Endpoint::address
Address const & address() const
Returns the address portion of this endpoint.
Definition: IPEndpoint.h:67
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:74
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:59
std::uint16_t
beast::IP::operator<
bool operator<(Endpoint const &lhs, Endpoint const &rhs)
Definition: IPEndpoint.cpp:80
std::stringstream::fail
T fail(T... args)
beast::IP::Endpoint::from_string
static Endpoint from_string(std::string const &s)
Definition: IPEndpoint.cpp:47
beast::IP::Endpoint
A version-independent IP address and port combination.
Definition: IPEndpoint.h:39
beast::IP::Endpoint::from_string_checked
static boost::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
Definition: IPEndpoint.cpp:37
std::istream::unget
T unget(T... args)
std::istream
STL class.
beast
Definition: base_uint.h:582