rippled
Loading...
Searching...
No Matches
IPEndpoint.cpp
1#include <xrpl/beast/net/IPAddress.h>
2#include <xrpl/beast/net/IPEndpoint.h>
3
4#include <boost/algorithm/string/trim.hpp>
5#include <boost/asio/ip/address.hpp>
6#include <boost/asio/ip/address_v4.hpp>
7#include <boost/system/detail/error_code.hpp>
8
9#include <cctype>
10#include <ios>
11#include <istream>
12#include <optional>
13#include <sstream>
14#include <string>
15
16namespace beast {
17namespace IP {
18
19Endpoint::Endpoint() : m_port(0)
20{
21}
22
23Endpoint::Endpoint(Address const& addr, Port port) : m_addr(addr), m_port(port)
24{
25}
26
29{
30 if (s.size() <= 64)
31 {
32 std::stringstream is(boost::trim_copy(s));
33 Endpoint endpoint;
34 is >> endpoint;
35 if (!is.fail() && is.rdbuf()->in_avail() == 0)
36 return endpoint;
37 }
38 return {};
39}
40
43{
44 if (std::optional<Endpoint> const result = from_string_checked(s))
45 return *result;
46 return Endpoint{};
47}
48
51{
53 s.reserve(
54 (address().is_v6() ? INET6_ADDRSTRLEN - 1 : 15) +
55 (port() == 0 ? 0 : 6 + (address().is_v6() ? 2 : 0)));
56
57 if (port() != 0 && address().is_v6())
58 s += '[';
59 s += address().to_string();
60 if (port() != 0u)
61 {
62 if (address().is_v6())
63 s += ']';
64 s += ":" + std::to_string(port());
65 }
66
67 return s;
68}
69
70bool
71operator==(Endpoint const& lhs, Endpoint const& rhs)
72{
73 return lhs.address() == rhs.address() && lhs.port() == rhs.port();
74}
75
76bool
77operator<(Endpoint const& lhs, Endpoint const& rhs)
78{
79 if (lhs.address() < rhs.address())
80 return true;
81 if (lhs.address() > rhs.address())
82 return false;
83 return lhs.port() < rhs.port();
84}
85
86//------------------------------------------------------------------------------
87
90{
91 std::string addrStr;
92 // valid addresses only need INET6_ADDRSTRLEN-1 chars, but allow the extra
93 // char to check for invalid lengths
94 addrStr.reserve(INET6_ADDRSTRLEN);
95 char i{0};
96 char readTo{0};
97 is.get(i);
98 if (i == '[')
99 { // we are an IPv6 endpoint
100 readTo = ']';
101 }
102 else
103 {
104 addrStr += i;
105 }
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)) != 0) || ((readTo != 0) && 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 || (readTo == ':' && addrStr.size() > 15))
124 {
125 is.setstate(std::ios_base::failbit);
126 return is;
127 }
128
129 if ((readTo == 0) && (i == '.' || i == ':'))
130 {
131 // if we see a dot first, must be IPv4
132 // otherwise must be non-bracketed IPv6
133 readTo = (i == '.') ? ':' : ' ';
134 }
135 }
136 else // invalid char
137 {
138 is.unget();
139 is.setstate(std::ios_base::failbit);
140 return is;
141 }
142 }
143
144 if (readTo == ']' && is.rdbuf()->in_avail() > 0)
145 {
146 is.get(i);
147 if ((isspace(static_cast<unsigned char>(i)) == 0) && i != ':')
148 {
149 is.unget();
150 is.setstate(std::ios_base::failbit);
151 return is;
152 }
153 }
154
155 boost::system::error_code ec;
156 auto addr = boost::asio::ip::make_address(addrStr, ec);
157 if (ec)
158 {
159 is.setstate(std::ios_base::failbit);
160 return is;
161 }
162
163 if (is.rdbuf()->in_avail() > 0)
164 {
165 Port port = 0;
166 is >> port;
167 if (is.fail())
168 return is;
169 endpoint = Endpoint(addr, port);
170 }
171 else
172 {
173 endpoint = Endpoint(addr);
174 }
175
176 return is;
177}
178
179} // namespace IP
180} // namespace beast
A version-independent IP address and port combination.
Definition IPEndpoint.h:18
Address const & address() const
Returns the address portion of this endpoint.
Definition IPEndpoint.h:55
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
Endpoint()
Create an unspecified endpoint.
static Endpoint from_string(std::string const &s)
bool is_v6() const
Definition IPEndpoint.h:68
Port port() const
Returns the port number on the endpoint.
Definition IPEndpoint.h:41
std::string to_string() const
Returns a string representing the endpoint.
T fail(T... args)
T get(T... args)
std::istream & operator>>(std::istream &is, Endpoint &endpoint)
Input stream conversion.
bool operator<(Endpoint const &lhs, Endpoint const &rhs)
boost::asio::ip::address Address
Definition IPAddress.h:19
bool operator==(Endpoint const &lhs, Endpoint const &rhs)
T rdbuf(T... args)
T reserve(T... args)
T setstate(T... args)
T size(T... args)
T to_string(T... args)
T unget(T... args)