23#include <test/beast/IPEndpointCommon.h>
25#include <xrpl/basics/random.h>
26#include <xrpl/beast/net/IPEndpoint.h>
27#include <xrpl/beast/unit_test.h>
29#include <boost/algorithm/string.hpp>
30#include <boost/asio/ip/address.hpp>
31#include <boost/predef.h>
47 boost::system::error_code ec;
48 Address const result{Address::from_string(s, ec)};
49 if (!BEAST_EXPECTS(!ec, ec.message()))
51 if (!BEAST_EXPECTS(result.is_v4(), s +
" not v4"))
54 result.to_v4().to_ulong() == value, s +
" value mismatch"))
57 result.to_string() == (normal.empty() ? s : normal),
64 boost::system::error_code ec;
65 auto a = Address::from_string(s, ec);
66 BEAST_EXPECTS(ec, s +
" parses as " + a.to_string());
74 BEAST_EXPECT(
AddressV4{}.to_ulong() == 0);
76 BEAST_EXPECT(
AddressV4{0x01020304}.to_ulong() == 0x01020304);
79 AddressV4::bytes_type d = {{1, 2, 3, 4}};
80 BEAST_EXPECT(
AddressV4{d}.to_ulong() == 0x01020304);
86 BEAST_EXPECT(
AddressV4{v1}.to_ulong() == 1);
91 BEAST_EXPECT(v.to_ulong() == v1.to_ulong());
96 auto d = v.to_bytes();
102 BEAST_EXPECT(v.to_ulong() == 0x01020304);
138 AddressV4::bytes_type d1 = {{10, 0, 0, 1}};
140 BEAST_EXPECT(v4.to_bytes()[0] == 10);
141 BEAST_EXPECT(v4.to_bytes()[1] == 0);
142 BEAST_EXPECT(v4.to_bytes()[2] == 0);
143 BEAST_EXPECT(v4.to_bytes()[3] == 1);
145 BEAST_EXPECT((~((0xff) << 16)) == 0xff00ffff);
147 auto d2 = v4.to_bytes();
150 BEAST_EXPECT(v4.to_bytes()[0] == 10);
151 BEAST_EXPECT(v4.to_bytes()[1] == 10);
152 BEAST_EXPECT(v4.to_bytes()[2] == 0);
153 BEAST_EXPECT(v4.to_bytes()[3] == 1);
163 boost::system::error_code ec;
164 Address result{Address::from_string(
"1.2.3.4", ec)};
165 AddressV4::bytes_type d = {{1, 2, 3, 4}};
167 BEAST_EXPECT(result.is_v4() && result.to_v4() ==
AddressV4{d});
175 AddressV4::bytes_type
const& value,
180 if (!BEAST_EXPECT(result))
182 if (!BEAST_EXPECT(result->address().is_v4()))
184 if (!BEAST_EXPECT(result->address().to_v4() ==
AddressV4{value}))
187 BEAST_EXPECT(result->port() == p);
188 BEAST_EXPECT(
to_string(*result) == (normal.empty() ? s : normal));
194 AddressV6::bytes_type
const& value,
199 if (!BEAST_EXPECT(result))
201 if (!BEAST_EXPECT(result->address().is_v6()))
203 if (!BEAST_EXPECT(result->address().to_v6() ==
AddressV6{value}))
206 BEAST_EXPECT(result->port() == p);
207 BEAST_EXPECT(
to_string(*result) == (normal.empty() ? s : normal));
214 BEAST_EXPECTS(
is_unspecified(a1), s +
" parses as " + a1.to_string());
217 BEAST_EXPECTS(
is_unspecified(a2), s +
" parses as " + a2.to_string());
219 boost::replace_last(s,
":",
" ");
221 BEAST_EXPECTS(
is_unspecified(a3), s +
" parses as " + a3.to_string());
238 "2001:db8:a0b:12f0::1",
239 {{32, 01, 13, 184, 10, 11, 18, 240, 0, 0, 0, 0, 0, 0, 0, 1}},
242 "[2001:db8:a0b:12f0::1]:8",
243 {{32, 01, 13, 184, 10, 11, 18, 240, 0, 0, 0, 0, 0, 0, 0, 1}},
246 "[2001:2002:2003:2004:2005:2006:2007:2008]:65535",
247 {{32, 1, 32, 2, 32, 3, 32, 4, 32, 5, 32, 6, 32, 7, 32, 8}},
250 "2001:2002:2003:2004:2005:2006:2007:2008 65535",
251 {{32, 1, 32, 2, 32, 3, 32, 4, 32, 5, 32, 6, 32, 7, 32, 8}},
253 "[2001:2002:2003:2004:2005:2006:2007:2008]:65535");
257 AddressV4::bytes_type d = {{127, 0, 0, 1}};
264 BEAST_EXPECT(
to_string(ep) ==
"127.0.0.1:80");
276 BEAST_EXPECT(
get_class(ep.to_v4()) ==
'A');
282 BEAST_EXPECT(
to_string(ep) ==
"10.0.0.1");
285 BEAST_EXPECT(
get_class(ep.to_v6().to_v4()) ==
'A');
293 d = {{166, 78, 151, 147}};
300 BEAST_EXPECT(
to_string(ep) ==
"166.78.151.147");
311 AddressV6::bytes_type d2 = {
312 {253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}};
328 BEAST_EXPECT(ep.address() == ep1.address());
329 BEAST_EXPECT(ep1.port() == 2016);
333 BEAST_EXPECT(ep.address() == ep2.address());
334 BEAST_EXPECT(ep2.port() == 2016);
335 BEAST_EXPECT(ep1 == ep2);
339 BEAST_EXPECT(ep.address() == ep3.address());
340 BEAST_EXPECT(ep3.port() == 2016);
341 BEAST_EXPECT(ep2 == ep3);
345 BEAST_EXPECT(ep.address() == ep4.address());
346 BEAST_EXPECT(ep4.port() == 2016);
347 BEAST_EXPECT(ep3 == ep4);
357 BEAST_EXPECT(ep.port() == 2017);
358 BEAST_EXPECT(ep.address() ==
AddressV6{});
383 failParseEP(
"[1234:5678:90ab:cdef:1234:5678:90ab:cdef:1111]:1");
384 failParseEP(
"[1234:5678:90ab:cdef:1234:5678:90ab:cdef:1111]:12345");
391 constexpr auto items{100};
393 for (
auto i = 0; i < items; ++i)
399 BEAST_EXPECT(max_lf > 0.90);
404 template <
typename T>
410 return !stream.fail();
413 template <
typename T>
419 BEAST_EXPECT(
parse(text, t));
421 to_string(t) == (normal.empty() ? text : normal),
422 "string mismatch for "s + text);
425 template <
typename T>
433 template <
typename T>
439 shouldPass<T>(
"0.0.0.0");
440 shouldPass<T>(
"192.168.0.1");
441 shouldPass<T>(
"168.127.149.132");
442 shouldPass<T>(
"168.127.149.132:80");
443 shouldPass<T>(
"168.127.149.132:54321");
444 shouldPass<T>(
"2001:db8:a0b:12f0::1");
445 shouldPass<T>(
"[2001:db8:a0b:12f0::1]:8");
446 shouldPass<T>(
"2001:db8:a0b:12f0::1 8",
"[2001:db8:a0b:12f0::1]:8");
447 shouldPass<T>(
"[::1]:8");
448 shouldPass<T>(
"[2001:2002:2003:2004:2005:2006:2007:2008]:65535");
450 shouldFail<T>(
"1.2.3.256");
454 shouldPass<T>(
"512",
"0.0.2.0");
455 shouldPass<T>(
"255",
"0.0.0.255");
456 shouldPass<T>(
"1.2.3:80",
"1.2.0.3:80");
458 shouldFail<T>(
"512");
459 shouldFail<T>(
"255");
460 shouldFail<T>(
"1.2.3:80");
462 shouldFail<T>(
"1.2.3:65536");
463 shouldFail<T>(
"1.2.3:72131");
464 shouldFail<T>(
"[::1]:89119");
465 shouldFail<T>(
"[::az]:1");
466 shouldFail<T>(
"[1234:5678:90ab:cdef:1234:5678:90ab:cdef:1111]:1");
467 shouldFail<T>(
"[1234:5678:90ab:cdef:1234:5678:90ab:cdef:1111]:12345");
477 testParse<Endpoint>(
"Parse Endpoint");
481BEAST_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()