rippled
Loading...
Searching...
No Matches
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 <xrpl/beast/net/IPEndpoint.h>
21#include <boost/algorithm/string.hpp>
22
23namespace beast {
24namespace IP {
25
26Endpoint::Endpoint() : m_port(0)
27{
28}
29
30Endpoint::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{
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
77bool
78operator==(Endpoint const& lhs, Endpoint const& rhs)
79{
80 return lhs.address() == rhs.address() && lhs.port() == rhs.port();
81}
82
83bool
84operator<(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
A version-independent IP address and port combination.
Definition: IPEndpoint.h:39
Address const & address() const
Returns the address portion of this endpoint.
Definition: IPEndpoint.h:76
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
Definition: IPEndpoint.cpp:35
Endpoint()
Create an unspecified endpoint.
Definition: IPEndpoint.cpp:26
static Endpoint from_string(std::string const &s)
Definition: IPEndpoint.cpp:49
bool is_v6() const
Definition: IPEndpoint.h:89
Port port() const
Returns the port number on the endpoint.
Definition: IPEndpoint.h:62
std::string to_string() const
Returns a string representing the endpoint.
Definition: IPEndpoint.cpp:57
T fail(T... args)
T get(T... args)
std::istream & operator>>(std::istream &is, Endpoint &endpoint)
Input stream conversion.
Definition: IPEndpoint.cpp:96
bool operator<(Endpoint const &lhs, Endpoint const &rhs)
Definition: IPEndpoint.cpp:84
boost::asio::ip::address Address
Definition: IPAddress.h:41
bool operator==(Endpoint const &lhs, Endpoint const &rhs)
Definition: IPEndpoint.cpp:78
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)