23#include <test/beast/IPEndpointCommon.h>
24#include <xrpl/basics/random.h>
25#include <xrpl/beast/net/IPEndpoint.h>
26#include <xrpl/beast/unit_test.h>
27#include <boost/algorithm/string.hpp>
28#include <boost/asio/ip/address.hpp>
29#include <boost/predef.h>
46 boost::system::error_code ec;
47 Address const result{Address::from_string(s, ec)};
48 if (!BEAST_EXPECTS(!ec, ec.message()))
50 if (!BEAST_EXPECTS(result.is_v4(), s +
" not v4"))
53 result.to_v4().to_ulong() == value, s +
" value mismatch"))
56 result.to_string() == (normal.empty() ? s : normal),
63 boost::system::error_code ec;
64 auto a = Address::from_string(s, ec);
65 BEAST_EXPECTS(ec, s +
" parses as " + a.to_string());
73 BEAST_EXPECT(
AddressV4{}.to_ulong() == 0);
75 BEAST_EXPECT(
AddressV4{0x01020304}.to_ulong() == 0x01020304);
78 AddressV4::bytes_type d = {{1, 2, 3, 4}};
79 BEAST_EXPECT(
AddressV4{d}.to_ulong() == 0x01020304);
85 BEAST_EXPECT(
AddressV4{v1}.to_ulong() == 1);
90 BEAST_EXPECT(v.to_ulong() == v1.to_ulong());
95 auto d = v.to_bytes();
101 BEAST_EXPECT(v.to_ulong() == 0x01020304);
137 AddressV4::bytes_type d1 = {{10, 0, 0, 1}};
139 BEAST_EXPECT(v4.to_bytes()[0] == 10);
140 BEAST_EXPECT(v4.to_bytes()[1] == 0);
141 BEAST_EXPECT(v4.to_bytes()[2] == 0);
142 BEAST_EXPECT(v4.to_bytes()[3] == 1);
144 BEAST_EXPECT((~((0xff) << 16)) == 0xff00ffff);
146 auto d2 = v4.to_bytes();
149 BEAST_EXPECT(v4.to_bytes()[0] == 10);
150 BEAST_EXPECT(v4.to_bytes()[1] == 10);
151 BEAST_EXPECT(v4.to_bytes()[2] == 0);
152 BEAST_EXPECT(v4.to_bytes()[3] == 1);
162 boost::system::error_code ec;
163 Address result{Address::from_string(
"1.2.3.4", ec)};
164 AddressV4::bytes_type d = {{1, 2, 3, 4}};
166 BEAST_EXPECT(result.is_v4() && result.to_v4() ==
AddressV4{d});
174 AddressV4::bytes_type
const& value,
179 if (!BEAST_EXPECT(result))
181 if (!BEAST_EXPECT(result->address().is_v4()))
183 if (!BEAST_EXPECT(result->address().to_v4() ==
AddressV4{value}))
186 BEAST_EXPECT(result->port() == p);
187 BEAST_EXPECT(
to_string(*result) == (normal.empty() ? s : normal));
193 AddressV6::bytes_type
const& value,
198 if (!BEAST_EXPECT(result))
200 if (!BEAST_EXPECT(result->address().is_v6()))
202 if (!BEAST_EXPECT(result->address().to_v6() ==
AddressV6{value}))
205 BEAST_EXPECT(result->port() == p);
206 BEAST_EXPECT(
to_string(*result) == (normal.empty() ? s : normal));
213 BEAST_EXPECTS(
is_unspecified(a1), s +
" parses as " + a1.to_string());
216 BEAST_EXPECTS(
is_unspecified(a2), s +
" parses as " + a2.to_string());
218 boost::replace_last(s,
":",
" ");
220 BEAST_EXPECTS(
is_unspecified(a3), s +
" parses as " + a3.to_string());
237 "2001:db8:a0b:12f0::1",
238 {{32, 01, 13, 184, 10, 11, 18, 240, 0, 0, 0, 0, 0, 0, 0, 1}},
241 "[2001:db8:a0b:12f0::1]:8",
242 {{32, 01, 13, 184, 10, 11, 18, 240, 0, 0, 0, 0, 0, 0, 0, 1}},
245 "[2001:2002:2003:2004:2005:2006:2007:2008]:65535",
246 {{32, 1, 32, 2, 32, 3, 32, 4, 32, 5, 32, 6, 32, 7, 32, 8}},
249 "2001:2002:2003:2004:2005:2006:2007:2008 65535",
250 {{32, 1, 32, 2, 32, 3, 32, 4, 32, 5, 32, 6, 32, 7, 32, 8}},
252 "[2001:2002:2003:2004:2005:2006:2007:2008]:65535");
256 AddressV4::bytes_type d = {{127, 0, 0, 1}};
263 BEAST_EXPECT(
to_string(ep) ==
"127.0.0.1:80");
275 BEAST_EXPECT(
get_class(ep.to_v4()) ==
'A');
281 BEAST_EXPECT(
to_string(ep) ==
"10.0.0.1");
284 BEAST_EXPECT(
get_class(ep.to_v6().to_v4()) ==
'A');
292 d = {{166, 78, 151, 147}};
299 BEAST_EXPECT(
to_string(ep) ==
"166.78.151.147");
310 AddressV6::bytes_type d2 = {
311 {253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}};
327 BEAST_EXPECT(ep.address() == ep1.address());
328 BEAST_EXPECT(ep1.port() == 2016);
332 BEAST_EXPECT(ep.address() == ep2.address());
333 BEAST_EXPECT(ep2.port() == 2016);
334 BEAST_EXPECT(ep1 == ep2);
338 BEAST_EXPECT(ep.address() == ep3.address());
339 BEAST_EXPECT(ep3.port() == 2016);
340 BEAST_EXPECT(ep2 == ep3);
344 BEAST_EXPECT(ep.address() == ep4.address());
345 BEAST_EXPECT(ep4.port() == 2016);
346 BEAST_EXPECT(ep3 == ep4);
356 BEAST_EXPECT(ep.port() == 2017);
357 BEAST_EXPECT(ep.address() ==
AddressV6{});
382 failParseEP(
"[1234:5678:90ab:cdef:1234:5678:90ab:cdef:1111]:1");
383 failParseEP(
"[1234:5678:90ab:cdef:1234:5678:90ab:cdef:1111]:12345");
390 constexpr auto items{100};
392 for (
auto i = 0; i < items; ++i)
398 BEAST_EXPECT(max_lf > 0.90);
403 template <
typename T>
409 return !stream.fail();
412 template <
typename T>
416 using namespace std::literals;
418 BEAST_EXPECT(
parse(text, t));
420 to_string(t) == (normal.empty() ? text : normal),
421 "string mismatch for "s + text);
424 template <
typename T>
432 template <
typename T>
438 shouldPass<T>(
"0.0.0.0");
439 shouldPass<T>(
"192.168.0.1");
440 shouldPass<T>(
"168.127.149.132");
441 shouldPass<T>(
"168.127.149.132:80");
442 shouldPass<T>(
"168.127.149.132:54321");
443 shouldPass<T>(
"2001:db8:a0b:12f0::1");
444 shouldPass<T>(
"[2001:db8:a0b:12f0::1]:8");
445 shouldPass<T>(
"2001:db8:a0b:12f0::1 8",
"[2001:db8:a0b:12f0::1]:8");
446 shouldPass<T>(
"[::1]:8");
447 shouldPass<T>(
"[2001:2002:2003:2004:2005:2006:2007:2008]:65535");
449 shouldFail<T>(
"1.2.3.256");
453 shouldPass<T>(
"512",
"0.0.2.0");
454 shouldPass<T>(
"255",
"0.0.0.255");
455 shouldPass<T>(
"1.2.3:80",
"1.2.0.3:80");
457 shouldFail<T>(
"512");
458 shouldFail<T>(
"255");
459 shouldFail<T>(
"1.2.3:80");
461 shouldFail<T>(
"1.2.3:65536");
462 shouldFail<T>(
"1.2.3:72131");
463 shouldFail<T>(
"[::1]:89119");
464 shouldFail<T>(
"[::az]:1");
465 shouldFail<T>(
"[1234:5678:90ab:cdef:1234:5678:90ab:cdef:1111]:1");
466 shouldFail<T>(
"[1234:5678:90ab:cdef:1234:5678:90ab:cdef:1111]:12345");
476 testParse<Endpoint>(
"Parse Endpoint");
480BEAST_DEFINE_TESTSUITE(IPEndpoint, net,
beast);
T bucket_count(T... args)
A version-independent IP address and port combination.
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
static Endpoint from_string(std::string const &s)
void run() override
Runs the suite.
void shouldPass(std::string const &text, std::string const &normal="")
void shouldParseEPV4(std::string const &s, AddressV4::bytes_type const &value, std::uint16_t p, std::string const &normal="")
bool parse(std::string const &text, T &t)
void testAddressV4Proxy()
void shouldParseAddrV4(std::string const &s, std::uint32_t value, std::string const &normal="")
void failParseAddr(std::string const &s)
void shouldFail(std::string const &text)
void testParse(char const *name)
void failParseEP(std::string s)
void shouldParseEPV6(std::string const &s, AddressV6::bytes_type const &value, std::uint16_t p, std::string const &normal="")
bool unexpected(Condition shouldBeFalse, String const &reason)
testcase_t testcase
Memberspace for declaring test cases.
bool is_multicast(Address const &addr)
Returns true if the address is a multicast address.
bool is_loopback(Address const &addr)
Returns true if this is a loopback address.
char get_class(AddressV4 const &address)
Returns the address class for the given address.
boost::asio::ip::address_v6 AddressV6
bool is_public(Address const &addr)
Returns true if the address is a public routable address.
Endpoint randomEP(bool v4=true)
bool is_unspecified(Address const &addr)
Returns true if the address is unspecified.
boost::asio::ip::address_v4 AddressV4
boost::asio::ip::address Address
bool is_private(Address const &addr)
Returns true if the address is a private unroutable address.
std::string to_string(Address const &addr)
Returns the address represented as a string.
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()