mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Support ipv6 for peer and RPC comms:
Fixes: RIPD-1574 Alias beast address classes to the asio equivalents. Adjust users of address classes accordingly. Fix resolver class so that it can support ipv6 addresses. Make unit tests use ipv6 localhost network. Extend endpoint peer message to support string endpoint representations while also supporting the existing fields (both are optional/repeated types). Expand test for Livecache and Endpoint. Workaround some false positive ipaddr tests on windows (asio bug?) Replaced usage of address::from_string(deprecated) with free function make_address. Identified a remaining use of v4 address type and replaced with the more appropriate IPEndpoint type (rpc_ip cmdline option). Add CLI flag for using ipv4 with unit tests. Release Notes ------------- The optional rpc_port command line flag is deprecated. The rpc_ip parameter now works as documented and accepts ip and port combined.
This commit is contained in:
@@ -216,12 +216,15 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace test{ extern std::atomic<bool> envUseIPv4; }
|
||||||
|
|
||||||
static int runUnitTests(
|
static int runUnitTests(
|
||||||
std::string const& pattern,
|
std::string const& pattern,
|
||||||
std::string const& argument,
|
std::string const& argument,
|
||||||
bool quiet,
|
bool quiet,
|
||||||
bool log,
|
bool log,
|
||||||
bool child,
|
bool child,
|
||||||
|
bool ipv4,
|
||||||
std::size_t num_jobs,
|
std::size_t num_jobs,
|
||||||
int argc,
|
int argc,
|
||||||
char** argv)
|
char** argv)
|
||||||
@@ -229,6 +232,9 @@ static int runUnitTests(
|
|||||||
using namespace beast::unit_test;
|
using namespace beast::unit_test;
|
||||||
using namespace ripple::test;
|
using namespace ripple::test;
|
||||||
|
|
||||||
|
if (ipv4)
|
||||||
|
ripple::test::envUseIPv4 = true;
|
||||||
|
|
||||||
#if HAS_BOOST_PROCESS
|
#if HAS_BOOST_PROCESS
|
||||||
if (!child && num_jobs == 1)
|
if (!child && num_jobs == 1)
|
||||||
#endif
|
#endif
|
||||||
@@ -365,6 +371,7 @@ int run (int argc, char** argv)
|
|||||||
"Specify the IP address for RPC command. "
|
"Specify the IP address for RPC command. "
|
||||||
"Format: <ip-address>[':'<port-number>]")
|
"Format: <ip-address>[':'<port-number>]")
|
||||||
("rpc_port", po::value <std::uint16_t> (),
|
("rpc_port", po::value <std::uint16_t> (),
|
||||||
|
"DEPRECATED: include with rpc_ip instead. "
|
||||||
"Specify the port number for RPC command.")
|
"Specify the port number for RPC command.")
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -384,6 +391,7 @@ int run (int argc, char** argv)
|
|||||||
"argument is handled individually by any suite that accesses it -- "
|
"argument is handled individually by any suite that accesses it -- "
|
||||||
"as such, it typically only make sense to provide this when running "
|
"as such, it typically only make sense to provide this when running "
|
||||||
"a single suite.")
|
"a single suite.")
|
||||||
|
("unittest-ipv4", "Use IPv4 localhost when running unittests (default is IPv6).")
|
||||||
("unittest-log",
|
("unittest-log",
|
||||||
"Force unit test log message output. Only useful in combination with "
|
"Force unit test log message output. Only useful in combination with "
|
||||||
"--quiet, in which case log messages will print but suite/case names "
|
"--quiet, in which case log messages will print but suite/case names "
|
||||||
@@ -468,6 +476,7 @@ int run (int argc, char** argv)
|
|||||||
bool (vm.count ("quiet")),
|
bool (vm.count ("quiet")),
|
||||||
bool (vm.count ("unittest-log")),
|
bool (vm.count ("unittest-log")),
|
||||||
unittestChild,
|
unittestChild,
|
||||||
|
bool (vm.count ("unittest-ipv4")),
|
||||||
numJobs,
|
numJobs,
|
||||||
argc,
|
argc,
|
||||||
argv);
|
argv);
|
||||||
@@ -553,37 +562,38 @@ int run (int argc, char** argv)
|
|||||||
// happen after the config file is loaded.
|
// happen after the config file is loaded.
|
||||||
if (vm.count ("rpc_ip"))
|
if (vm.count ("rpc_ip"))
|
||||||
{
|
{
|
||||||
try
|
auto res = beast::IP::Endpoint::from_string_checked(
|
||||||
{
|
vm["rpc_ip"].as<std::string>());
|
||||||
config->rpc_ip.emplace (
|
if (! res.second)
|
||||||
boost::asio::ip::address_v4::from_string(
|
|
||||||
vm["rpc_ip"].as<std::string>()));
|
|
||||||
}
|
|
||||||
catch(std::exception const&)
|
|
||||||
{
|
{
|
||||||
std::cerr << "Invalid rpc_ip = " <<
|
std::cerr << "Invalid rpc_ip = " <<
|
||||||
vm["rpc_ip"].as<std::string>() << std::endl;
|
vm["rpc_ip"].as<std::string>() << "\n";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Override the RPC destination port number
|
if (res.first.port() == 0)
|
||||||
//
|
|
||||||
if (vm.count ("rpc_port"))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
config->rpc_port.emplace (
|
std::cerr << "No port specified in rpc_ip.\n";
|
||||||
vm["rpc_port"].as<std::uint16_t>());
|
if (vm.count ("rpc_port"))
|
||||||
|
{
|
||||||
|
std::cerr << "WARNING: using deprecated rpc_port param.\n";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
res.first.at_port(vm["rpc_port"].as<std::uint16_t>());
|
||||||
|
if (res.first.port() == 0)
|
||||||
|
throw std::domain_error("0");
|
||||||
|
}
|
||||||
|
catch(std::exception const& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Invalid rpc_port = " << e.what() << "\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (*config->rpc_port == 0)
|
config->rpc_ip = std::move(res.first);
|
||||||
throw std::domain_error("0");
|
|
||||||
}
|
|
||||||
catch(std::exception const& e)
|
|
||||||
{
|
|
||||||
std::cerr << "Invalid rpc_port = " << e.what() << "\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.count ("quorum"))
|
if (vm.count ("quorum"))
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <ripple/basics/ResolverAsio.h>
|
#include <ripple/basics/ResolverAsio.h>
|
||||||
#include <ripple/basics/Log.h>
|
#include <ripple/basics/Log.h>
|
||||||
#include <ripple/beast/net/IPAddressConversion.h>
|
#include <ripple/beast/net/IPAddressConversion.h>
|
||||||
|
#include <ripple/beast/net/IPEndpoint.h>
|
||||||
#include <ripple/beast/core/WaitableEvent.h>
|
#include <ripple/beast/core/WaitableEvent.h>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
@@ -259,6 +260,21 @@ public:
|
|||||||
|
|
||||||
HostAndPort parseName(std::string const& str)
|
HostAndPort parseName(std::string const& str)
|
||||||
{
|
{
|
||||||
|
// first attempt to parse as an endpoint (IP addr + port).
|
||||||
|
// If that doesn't succeed, fall back to generic name + port parsing
|
||||||
|
|
||||||
|
auto result {beast::IP::Endpoint::from_string_checked (str)};
|
||||||
|
if (result.second)
|
||||||
|
{
|
||||||
|
return make_pair (
|
||||||
|
result.first.address().to_string(),
|
||||||
|
std::to_string(result.first.port()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// generic name/port parsing, which doesn't work for
|
||||||
|
// IPv6 addresses in particular because it considers a colon
|
||||||
|
// a port separator
|
||||||
|
|
||||||
// Attempt to find the first and last non-whitespace
|
// Attempt to find the first and last non-whitespace
|
||||||
auto const find_whitespace = std::bind (
|
auto const find_whitespace = std::bind (
|
||||||
&std::isspace <std::string::value_type>,
|
&std::isspace <std::string::value_type>,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#include <ripple/basics/ToString.h>
|
#include <ripple/basics/ToString.h>
|
||||||
#include <ripple/beast/core/LexicalCast.h>
|
#include <ripple/beast/core/LexicalCast.h>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/asio/ip/address.hpp>
|
#include <ripple/beast/net/IPEndpoint.h>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
@@ -93,24 +93,38 @@ uint64_t uintFromHex (std::string const& strSrc)
|
|||||||
bool parseUrl (parsedURL& pUrl, std::string const& strUrl)
|
bool parseUrl (parsedURL& pUrl, std::string const& strUrl)
|
||||||
{
|
{
|
||||||
// scheme://username:password@hostname:port/rest
|
// scheme://username:password@hostname:port/rest
|
||||||
static boost::regex reUrl ("(?i)\\`\\s*([[:alpha:]][-+.[:alpha:][:digit:]]*)://([^:/]+)(?::(\\d+))?(/.*)?\\s*?\\'");
|
static boost::regex reUrl ("(?i)\\`\\s*([[:alpha:]][-+.[:alpha:][:digit:]]*)://([^/]+)(/.*)?\\s*?\\'");
|
||||||
boost::smatch smMatch;
|
boost::smatch smMatch;
|
||||||
|
|
||||||
bool bMatch = boost::regex_match (strUrl, smMatch, reUrl); // Match status code.
|
bool bMatch = boost::regex_match (strUrl, smMatch, reUrl); // Match status code.
|
||||||
|
|
||||||
if (bMatch)
|
if (bMatch)
|
||||||
{
|
{
|
||||||
std::string strPort;
|
|
||||||
|
|
||||||
pUrl.scheme = smMatch[1];
|
pUrl.scheme = smMatch[1];
|
||||||
boost::algorithm::to_lower (pUrl.scheme);
|
boost::algorithm::to_lower (pUrl.scheme);
|
||||||
|
pUrl.path = smMatch[3];
|
||||||
pUrl.domain = smMatch[2];
|
pUrl.domain = smMatch[2];
|
||||||
if (smMatch[3].length ())
|
|
||||||
|
// now consider the domain/port fragment
|
||||||
|
auto colonPos = pUrl.domain.find_last_of(':');
|
||||||
|
if (colonPos != std::string::npos)
|
||||||
{
|
{
|
||||||
pUrl.port = beast::lexicalCast <std::uint16_t> (
|
// use Endpoint class to see if this thing looks
|
||||||
std::string (smMatch[3]));
|
// like an IP addr...
|
||||||
|
auto result {beast::IP::Endpoint::from_string_checked (pUrl.domain)};
|
||||||
|
if (result.second)
|
||||||
|
{
|
||||||
|
pUrl.domain = result.first.address().to_string();
|
||||||
|
pUrl.port = result.first.port();
|
||||||
|
}
|
||||||
|
else // otherwise we are DNS name + port
|
||||||
|
{
|
||||||
|
pUrl.port = beast::lexicalCast <std::uint16_t> (
|
||||||
|
pUrl.domain.substr(colonPos+1));
|
||||||
|
pUrl.domain = pUrl.domain.substr(0, colonPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pUrl.path = smMatch[4];
|
//else, the whole thing is domain, not port
|
||||||
}
|
}
|
||||||
|
|
||||||
return bMatch;
|
return bMatch;
|
||||||
|
|||||||
@@ -217,19 +217,9 @@ private:
|
|||||||
std::thread m_thread;
|
std::thread m_thread;
|
||||||
|
|
||||||
static boost::asio::ip::udp::endpoint to_endpoint (
|
static boost::asio::ip::udp::endpoint to_endpoint (
|
||||||
IP::Endpoint const &address)
|
IP::Endpoint const &ep)
|
||||||
{
|
{
|
||||||
if (address.is_v4 ())
|
return boost::asio::ip::udp::endpoint (ep.address(), ep.port());
|
||||||
{
|
|
||||||
return boost::asio::ip::udp::endpoint (
|
|
||||||
boost::asio::ip::address_v4 (
|
|
||||||
address.to_v4().value), address.port ());
|
|
||||||
}
|
|
||||||
|
|
||||||
// VFALCO TODO IPv6 support
|
|
||||||
assert(false);
|
|
||||||
return boost::asio::ip::udp::endpoint (
|
|
||||||
boost::asio::ip::address_v6 (), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <ripple/beast/hash/hash_append.h>
|
#include <ripple/beast/hash/hash_append.h>
|
||||||
#include <ripple/beast/hash/uhash.h>
|
#include <ripple/beast/hash/uhash.h>
|
||||||
#include <boost/functional/hash.hpp>
|
#include <boost/functional/hash.hpp>
|
||||||
|
#include <boost/asio/ip/address.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
@@ -37,213 +38,22 @@
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace IP {
|
namespace IP {
|
||||||
|
|
||||||
/** A version-independent IP address.
|
using Address = boost::asio::ip::address;
|
||||||
This object can represent either an IPv4 or IPv6 address.
|
|
||||||
*/
|
/** Returns the address represented as a string. */
|
||||||
class Address
|
inline
|
||||||
|
std::string
|
||||||
|
to_string (Address const& addr)
|
||||||
{
|
{
|
||||||
public:
|
return addr.to_string ();
|
||||||
/** Create an unspecified IPv4 address. */
|
}
|
||||||
Address ()
|
|
||||||
: m_type (ipv4)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create an IPv4 address. */
|
|
||||||
Address (AddressV4 const& addr)
|
|
||||||
: m_type (ipv4)
|
|
||||||
, m_v4 (addr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create an IPv6 address. */
|
|
||||||
Address (AddressV6 const& addr)
|
|
||||||
: m_type (ipv6)
|
|
||||||
, m_v6 (addr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Assign a copy from another address in any format. */
|
|
||||||
/** @{ */
|
|
||||||
Address&
|
|
||||||
operator= (AddressV4 const& addr)
|
|
||||||
{
|
|
||||||
m_type = ipv4;
|
|
||||||
m_v6 = AddressV6();
|
|
||||||
m_v4 = addr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Address&
|
|
||||||
operator= (AddressV6 const& addr)
|
|
||||||
{
|
|
||||||
m_type = ipv6;
|
|
||||||
m_v4 = AddressV4();
|
|
||||||
m_v6 = addr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/** Create an Address from a string.
|
|
||||||
@return A pair with the address, and bool set to `true` on success.
|
|
||||||
*/
|
|
||||||
static
|
|
||||||
std::pair <Address, bool>
|
|
||||||
from_string (std::string const& s);
|
|
||||||
|
|
||||||
/** Returns a string representing the address. */
|
|
||||||
std::string
|
|
||||||
to_string () const
|
|
||||||
{
|
|
||||||
return (is_v4 ())
|
|
||||||
? IP::to_string (to_v4())
|
|
||||||
: IP::to_string (to_v6());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns `true` if this address represents an IPv4 address. */
|
|
||||||
bool
|
|
||||||
is_v4 () const noexcept
|
|
||||||
{
|
|
||||||
return m_type == ipv4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns `true` if this address represents an IPv6 address. */
|
|
||||||
bool
|
|
||||||
is_v6() const noexcept
|
|
||||||
{
|
|
||||||
return m_type == ipv6;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the IPv4 address.
|
|
||||||
Precondition:
|
|
||||||
is_v4() == `true`
|
|
||||||
*/
|
|
||||||
AddressV4 const&
|
|
||||||
to_v4 () const
|
|
||||||
{
|
|
||||||
if (!is_v4 ())
|
|
||||||
throw std::bad_cast();
|
|
||||||
return m_v4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the IPv6 address.
|
|
||||||
Precondition:
|
|
||||||
is_v6() == `true`
|
|
||||||
*/
|
|
||||||
AddressV6 const&
|
|
||||||
to_v6 () const
|
|
||||||
{
|
|
||||||
if (!is_v6 ())
|
|
||||||
throw std::bad_cast();
|
|
||||||
return m_v6;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns `true` if this address represents 0.0.0.0 */
|
|
||||||
bool
|
|
||||||
is_any () const
|
|
||||||
{
|
|
||||||
return is_v4 () ? m_v4 == IP::AddressV4::any ()
|
|
||||||
: false; // m_v6 == IP::AddressV6::any();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Hasher>
|
|
||||||
friend
|
|
||||||
void
|
|
||||||
hash_append(Hasher& h, Address const& addr) noexcept
|
|
||||||
{
|
|
||||||
using beast::hash_append;
|
|
||||||
if (addr.is_v4 ())
|
|
||||||
hash_append(h, addr.to_v4 ());
|
|
||||||
else if (addr.is_v6 ())
|
|
||||||
hash_append(h, addr.to_v6 ());
|
|
||||||
else
|
|
||||||
assert (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Arithmetic comparison. */
|
|
||||||
/** @{ */
|
|
||||||
friend
|
|
||||||
bool
|
|
||||||
operator== (Address const& lhs, Address const& rhs)
|
|
||||||
{
|
|
||||||
if (lhs.is_v4 ())
|
|
||||||
{
|
|
||||||
if (rhs.is_v4 ())
|
|
||||||
return lhs.to_v4() == rhs.to_v4();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (rhs.is_v6 ())
|
|
||||||
return lhs.to_v6() == rhs.to_v6();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool
|
|
||||||
operator< (Address const& lhs, Address const& rhs)
|
|
||||||
{
|
|
||||||
if (lhs.m_type < rhs.m_type)
|
|
||||||
return true;
|
|
||||||
if (lhs.is_v4 ())
|
|
||||||
return lhs.to_v4() < rhs.to_v4();
|
|
||||||
return lhs.to_v6() < rhs.to_v6();
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool
|
|
||||||
operator!= (Address const& lhs, Address const& rhs)
|
|
||||||
{
|
|
||||||
return ! (lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool
|
|
||||||
operator> (Address const& lhs, Address const& rhs)
|
|
||||||
{
|
|
||||||
return rhs < lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool
|
|
||||||
operator<= (Address const& lhs, Address const& rhs)
|
|
||||||
{
|
|
||||||
return ! (lhs > rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool
|
|
||||||
operator>= (Address const& lhs, Address const& rhs)
|
|
||||||
{
|
|
||||||
return ! (rhs > lhs);
|
|
||||||
}
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
ipv4,
|
|
||||||
ipv6
|
|
||||||
};
|
|
||||||
|
|
||||||
Type m_type;
|
|
||||||
AddressV4 m_v4;
|
|
||||||
AddressV6 m_v6;
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Properties
|
|
||||||
|
|
||||||
/** Returns `true` if this is a loopback address. */
|
/** Returns `true` if this is a loopback address. */
|
||||||
inline
|
inline
|
||||||
bool
|
bool
|
||||||
is_loopback (Address const& addr)
|
is_loopback (Address const& addr)
|
||||||
{
|
{
|
||||||
return (addr.is_v4 ())
|
return addr.is_loopback();
|
||||||
? is_loopback (addr.to_v4 ())
|
|
||||||
: is_loopback (addr.to_v6 ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns `true` if the address is unspecified. */
|
/** Returns `true` if the address is unspecified. */
|
||||||
@@ -251,9 +61,7 @@ inline
|
|||||||
bool
|
bool
|
||||||
is_unspecified (Address const& addr)
|
is_unspecified (Address const& addr)
|
||||||
{
|
{
|
||||||
return (addr.is_v4 ())
|
return addr.is_unspecified();
|
||||||
? is_unspecified (addr.to_v4 ())
|
|
||||||
: is_unspecified (addr.to_v6 ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns `true` if the address is a multicast address. */
|
/** Returns `true` if the address is a multicast address. */
|
||||||
@@ -261,9 +69,7 @@ inline
|
|||||||
bool
|
bool
|
||||||
is_multicast (Address const& addr)
|
is_multicast (Address const& addr)
|
||||||
{
|
{
|
||||||
return (addr.is_v4 ())
|
return addr.is_multicast();
|
||||||
? is_multicast (addr.to_v4 ())
|
|
||||||
: is_multicast (addr.to_v6 ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns `true` if the address is a private unroutable address. */
|
/** Returns `true` if the address is a private unroutable address. */
|
||||||
@@ -286,51 +92,24 @@ is_public (Address const& addr)
|
|||||||
: is_public (addr.to_v6 ());
|
: is_public (addr.to_v6 ());
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Returns the address represented as a string. */
|
|
||||||
inline std::string to_string (Address const& addr)
|
|
||||||
{
|
|
||||||
return addr.to_string ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Output stream conversion. */
|
|
||||||
template <typename OutputStream>
|
|
||||||
OutputStream&
|
|
||||||
operator<< (OutputStream& os, Address const& addr)
|
|
||||||
{
|
|
||||||
return os << to_string (addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Input stream conversion. */
|
|
||||||
inline
|
|
||||||
std::istream&
|
|
||||||
operator>> (std::istream& is, Address& addr)
|
|
||||||
{
|
|
||||||
// VFALCO TODO Support ipv6!
|
|
||||||
AddressV4 addrv4;
|
|
||||||
is >> addrv4;
|
|
||||||
addr = Address (addrv4);
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
std::pair <Address, bool>
|
|
||||||
Address::from_string (std::string const& s)
|
|
||||||
{
|
|
||||||
std::stringstream is (s);
|
|
||||||
Address addr;
|
|
||||||
is >> addr;
|
|
||||||
if (! is.fail() && is.rdbuf()->in_avail() == 0)
|
|
||||||
return std::make_pair (addr, true);
|
|
||||||
return std::make_pair (Address (), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template <class Hasher>
|
||||||
|
void
|
||||||
|
hash_append(Hasher& h, beast::IP::Address const& addr) noexcept
|
||||||
|
{
|
||||||
|
using beast::hash_append;
|
||||||
|
if (addr.is_v4 ())
|
||||||
|
hash_append(h, addr.to_v4().to_bytes());
|
||||||
|
else if (addr.is_v6 ())
|
||||||
|
hash_append(h, addr.to_v6().to_bytes());
|
||||||
|
else
|
||||||
|
assert (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <>
|
template <>
|
||||||
struct hash <beast::IP::Address>
|
struct hash <beast::IP::Address>
|
||||||
|
|||||||
@@ -21,141 +21,17 @@
|
|||||||
#define BEAST_NET_IPADDRESSV4_H_INCLUDED
|
#define BEAST_NET_IPADDRESSV4_H_INCLUDED
|
||||||
|
|
||||||
#include <ripple/beast/hash/hash_append.h>
|
#include <ripple/beast/hash/hash_append.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <boost/asio/ip/address_v4.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace IP {
|
namespace IP {
|
||||||
|
|
||||||
/** Represents a version 4 IP address. */
|
using AddressV4 = boost::asio::ip::address_v4;
|
||||||
struct AddressV4
|
|
||||||
{
|
|
||||||
/** Default constructor represents the 'any' address. */
|
|
||||||
AddressV4 ();
|
|
||||||
|
|
||||||
/** Construct from a 32-bit unsigned.
|
|
||||||
@note Octets are formed in order from the MSB to the LSB.
|
|
||||||
*/
|
|
||||||
explicit AddressV4 (std::uint32_t value_);
|
|
||||||
|
|
||||||
/** Construct from four individual octets..
|
|
||||||
@note The resulting address is a.b.c.d
|
|
||||||
*/
|
|
||||||
AddressV4 (std::uint8_t a, std::uint8_t b, std::uint8_t c, std::uint8_t d);
|
|
||||||
|
|
||||||
/** Create an address from an IPv4 address string in dotted decimal form.
|
|
||||||
@return A pair with the address, and bool set to `true` on success.
|
|
||||||
*/
|
|
||||||
static std::pair <AddressV4, bool> from_string (std::string const& s);
|
|
||||||
|
|
||||||
/** Returns an address that represents 'any' address. */
|
|
||||||
static AddressV4 any ()
|
|
||||||
{ return AddressV4(); }
|
|
||||||
|
|
||||||
/** Returns an address that represents the loopback address. */
|
|
||||||
static AddressV4 loopback ()
|
|
||||||
{ return AddressV4 (0x7f000001); }
|
|
||||||
|
|
||||||
/** Returns an address that represents the broadcast address. */
|
|
||||||
static AddressV4 broadcast ()
|
|
||||||
{ return AddressV4 (0xffffffff); }
|
|
||||||
|
|
||||||
/** Returns the broadcast address for the specified address. */
|
|
||||||
static AddressV4 broadcast (AddressV4 const& address);
|
|
||||||
|
|
||||||
/** Returns the broadcast address corresponding to the address and mask. */
|
|
||||||
static AddressV4 broadcast (
|
|
||||||
AddressV4 const& address, AddressV4 const& mask);
|
|
||||||
|
|
||||||
/** Returns `true` if this is a broadcast address. */
|
|
||||||
bool is_broadcast () const
|
|
||||||
{ return *this == broadcast (*this); }
|
|
||||||
|
|
||||||
/** Returns the address class for the given address.
|
|
||||||
@note Class 'D' represents multicast addresses (224.*.*.*).
|
|
||||||
*/
|
|
||||||
static char get_class (AddressV4 const& address);
|
|
||||||
|
|
||||||
/** Returns the netmask for the address class or address. */
|
|
||||||
/** @{ */
|
|
||||||
static AddressV4 netmask (char address_class);
|
|
||||||
static AddressV4 netmask (AddressV4 const& v);
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/** Arithmetic comparison. */
|
|
||||||
/** @{ */
|
|
||||||
friend bool operator== (AddressV4 const& lhs, AddressV4 const& rhs)
|
|
||||||
{ return lhs.value == rhs.value; }
|
|
||||||
friend bool operator< (AddressV4 const& lhs, AddressV4 const& rhs)
|
|
||||||
{ return lhs.value < rhs.value; }
|
|
||||||
|
|
||||||
friend bool operator!= (AddressV4 const& lhs, AddressV4 const& rhs)
|
|
||||||
{ return ! (lhs == rhs); }
|
|
||||||
friend bool operator> (AddressV4 const& lhs, AddressV4 const& rhs)
|
|
||||||
{ return rhs < lhs; }
|
|
||||||
friend bool operator<= (AddressV4 const& lhs, AddressV4 const& rhs)
|
|
||||||
{ return ! (lhs > rhs); }
|
|
||||||
friend bool operator>= (AddressV4 const& lhs, AddressV4 const& rhs)
|
|
||||||
{ return ! (rhs > lhs); }
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/** Array indexing for reading and writing indiviual octets. */
|
|
||||||
/** @{ */
|
|
||||||
template <bool IsConst>
|
|
||||||
class Proxy
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Pointer = typename std::conditional <
|
|
||||||
IsConst, std::uint32_t const*, std::uint32_t*>::type;
|
|
||||||
|
|
||||||
Proxy (int shift, Pointer value)
|
|
||||||
: m_shift (shift)
|
|
||||||
, m_value (value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
operator std::uint8_t() const
|
|
||||||
{
|
|
||||||
return ((*m_value)>>m_shift) & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename IntegralType>
|
|
||||||
Proxy& operator= (IntegralType v)
|
|
||||||
{
|
|
||||||
(*m_value) =
|
|
||||||
( (*m_value) & (~((0xff)<<m_shift)) )
|
|
||||||
| ((v&0xff) << m_shift);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_shift;
|
|
||||||
Pointer m_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Proxy <true> operator[] (std::size_t index) const;
|
|
||||||
Proxy <false> operator[] (std::size_t index);
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/** The value as a 32 bit unsigned. */
|
|
||||||
std::uint32_t value;
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Returns `true` if this is a loopback address. */
|
|
||||||
bool is_loopback (AddressV4 const& addr);
|
|
||||||
|
|
||||||
/** Returns `true` if the address is unspecified. */
|
|
||||||
bool is_unspecified (AddressV4 const& addr);
|
|
||||||
|
|
||||||
/** Returns `true` if the address is a multicast address. */
|
|
||||||
bool is_multicast (AddressV4 const& addr);
|
|
||||||
|
|
||||||
/** Returns `true` if the address is a private unroutable address. */
|
/** Returns `true` if the address is a private unroutable address. */
|
||||||
bool is_private (AddressV4 const& addr);
|
bool is_private (AddressV4 const& addr);
|
||||||
@@ -163,42 +39,12 @@ bool is_private (AddressV4 const& addr);
|
|||||||
/** Returns `true` if the address is a public routable address. */
|
/** Returns `true` if the address is a public routable address. */
|
||||||
bool is_public (AddressV4 const& addr);
|
bool is_public (AddressV4 const& addr);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
/** Returns the address class for the given address.
|
||||||
|
@note Class 'D' represents multicast addresses (224.*.*.*).
|
||||||
/** Returns the address represented as a string. */
|
*/
|
||||||
std::string to_string (AddressV4 const& addr);
|
char get_class (AddressV4 const& address);
|
||||||
|
|
||||||
/** Output stream conversion. */
|
|
||||||
template <typename OutputStream>
|
|
||||||
OutputStream& operator<< (OutputStream& os, AddressV4 const& addr)
|
|
||||||
{ return os << to_string (addr); }
|
|
||||||
|
|
||||||
/** Input stream conversion. */
|
|
||||||
std::istream& operator>> (std::istream& is, AddressV4& addr);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class HashAlgorithm>
|
|
||||||
struct is_contiguously_hashable<IP::AddressV4, HashAlgorithm>
|
|
||||||
: public std::integral_constant<bool, sizeof(IP::AddressV4) == sizeof(std::uint32_t)>
|
|
||||||
{
|
|
||||||
explicit is_contiguously_hashable() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
/** std::hash support. */
|
|
||||||
template <>
|
|
||||||
struct hash <beast::IP::AddressV4>
|
|
||||||
{
|
|
||||||
explicit hash() = default;
|
|
||||||
|
|
||||||
std::size_t operator() (beast::IP::AddressV4 const& addr) const
|
|
||||||
{ return addr.value; }
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -26,45 +26,12 @@
|
|||||||
#include <ios>
|
#include <ios>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <boost/asio/ip/address_v6.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace IP {
|
namespace IP {
|
||||||
|
|
||||||
/** Represents a version 4 IP address. */
|
using AddressV6 = boost::asio::ip::address_v6;
|
||||||
struct AddressV6
|
|
||||||
{
|
|
||||||
explicit AddressV6() = default;
|
|
||||||
|
|
||||||
// VFALCO TODO
|
|
||||||
|
|
||||||
/** Arithmetic comparison. */
|
|
||||||
/** @{ */
|
|
||||||
friend bool operator== (AddressV6 const&, AddressV6 const&)
|
|
||||||
{ assert(false); return false; }
|
|
||||||
friend bool operator< (AddressV6 const&, AddressV6 const&)
|
|
||||||
{ assert(false); return false; }
|
|
||||||
|
|
||||||
friend bool operator!= (AddressV6 const& lhs, AddressV6 const& rhs)
|
|
||||||
{ return ! (lhs == rhs); }
|
|
||||||
friend bool operator> (AddressV6 const& lhs, AddressV6 const& rhs)
|
|
||||||
{ return rhs < lhs; }
|
|
||||||
friend bool operator<= (AddressV6 const& lhs, AddressV6 const& rhs)
|
|
||||||
{ return ! (lhs > rhs); }
|
|
||||||
friend bool operator>= (AddressV6 const& lhs, AddressV6 const& rhs)
|
|
||||||
{ return ! (rhs > lhs); }
|
|
||||||
/** @} */
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Returns `true` if this is a loopback address. */
|
|
||||||
bool is_loopback (AddressV6 const& addr);
|
|
||||||
|
|
||||||
/** Returns `true` if the address is unspecified. */
|
|
||||||
bool is_unspecified (AddressV6 const& addr);
|
|
||||||
|
|
||||||
/** Returns `true` if the address is a multicast address. */
|
|
||||||
bool is_multicast (AddressV6 const& addr);
|
|
||||||
|
|
||||||
/** Returns `true` if the address is a private unroutable address. */
|
/** Returns `true` if the address is a private unroutable address. */
|
||||||
bool is_private (AddressV6 const& addr);
|
bool is_private (AddressV6 const& addr);
|
||||||
@@ -72,41 +39,7 @@ bool is_private (AddressV6 const& addr);
|
|||||||
/** Returns `true` if the address is a public routable address. */
|
/** Returns `true` if the address is a public routable address. */
|
||||||
bool is_public (AddressV6 const& addr);
|
bool is_public (AddressV6 const& addr);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template <class Hasher>
|
|
||||||
void
|
|
||||||
hash_append(Hasher&, AddressV6 const&)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the address represented as a string. */
|
|
||||||
std::string to_string (AddressV6 const& addr);
|
|
||||||
|
|
||||||
/** Output stream conversion. */
|
|
||||||
template <typename OutputStream>
|
|
||||||
OutputStream& operator<< (OutputStream& os, AddressV6 const& addr)
|
|
||||||
{ return os << to_string (addr); }
|
|
||||||
|
|
||||||
/** Input stream conversion. */
|
|
||||||
std::istream& operator>> (std::istream& is, AddressV6& addr);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
/** std::hash support. */
|
|
||||||
template <>
|
|
||||||
struct hash <beast::IP::AddressV6>
|
|
||||||
{
|
|
||||||
explicit hash() = default;
|
|
||||||
|
|
||||||
std::size_t operator() (beast::IP::AddressV6 const& addr) const
|
|
||||||
{ assert(false); return 0; }
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
static std::pair <Endpoint, bool> from_string_checked (std::string const& s);
|
static std::pair <Endpoint, bool> from_string_checked (std::string const& s);
|
||||||
static Endpoint from_string (std::string const& s);
|
static Endpoint from_string (std::string const& s);
|
||||||
static Endpoint from_string_altform (std::string const& s);
|
|
||||||
|
|
||||||
/** Returns a string representing the endpoint. */
|
/** Returns a string representing the endpoint. */
|
||||||
std::string to_string () const;
|
std::string to_string () const;
|
||||||
@@ -71,9 +70,9 @@ public:
|
|||||||
{ return m_addr.is_v4(); }
|
{ return m_addr.is_v4(); }
|
||||||
bool is_v6 () const
|
bool is_v6 () const
|
||||||
{ return m_addr.is_v6(); }
|
{ return m_addr.is_v6(); }
|
||||||
AddressV4 const& to_v4 () const
|
AddressV4 const to_v4 () const
|
||||||
{ return m_addr.to_v4 (); }
|
{ return m_addr.to_v4 (); }
|
||||||
AddressV6 const& to_v6 () const
|
AddressV6 const to_v6 () const
|
||||||
{ return m_addr.to_v6 (); }
|
{ return m_addr.to_v6 (); }
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|||||||
@@ -1,103 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_NET_DETAIL_PARSE_H_INCLUDED
|
|
||||||
#define BEAST_NET_DETAIL_PARSE_H_INCLUDED
|
|
||||||
|
|
||||||
#include <ios>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace IP {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
/** Require and consume the specified character from the input.
|
|
||||||
@return `true` if the character matched.
|
|
||||||
*/
|
|
||||||
template <typename InputStream>
|
|
||||||
bool expect(InputStream& is, char v)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
if (is.get(c) && v == c)
|
|
||||||
return true;
|
|
||||||
is.unget();
|
|
||||||
is.setstate (std::ios_base::failbit);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Require and consume whitespace from the input.
|
|
||||||
@return `true` if the character matched.
|
|
||||||
*/
|
|
||||||
template <typename InputStream>
|
|
||||||
bool expect_whitespace (InputStream& is)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
if (is.get(c) && isspace(static_cast<unsigned char>(c)))
|
|
||||||
return true;
|
|
||||||
is.unget();
|
|
||||||
is.setstate (std::ios_base::failbit);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Used to disambiguate 8-bit integers from characters. */
|
|
||||||
template <typename IntType>
|
|
||||||
struct integer_holder
|
|
||||||
{
|
|
||||||
IntType* pi;
|
|
||||||
explicit integer_holder (IntType& i)
|
|
||||||
: pi (&i)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
template <typename OtherIntType>
|
|
||||||
IntType& operator= (OtherIntType o) const
|
|
||||||
{
|
|
||||||
*pi = o;
|
|
||||||
return *pi;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Parse 8-bit unsigned integer. */
|
|
||||||
template <typename InputStream>
|
|
||||||
InputStream& operator>> (InputStream& is, integer_holder <std::uint8_t> const& i)
|
|
||||||
{
|
|
||||||
std::uint16_t v;
|
|
||||||
is >> v;
|
|
||||||
if (! (v>=0 && v<=255))
|
|
||||||
{
|
|
||||||
is.setstate (std::ios_base::failbit);
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
i = std::uint8_t(v);
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Free function for template argument deduction. */
|
|
||||||
template <typename IntType>
|
|
||||||
integer_holder <IntType> integer (IntType& i)
|
|
||||||
{
|
|
||||||
return integer_holder <IntType> (i);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -24,43 +24,22 @@ namespace IP {
|
|||||||
|
|
||||||
Endpoint from_asio (boost::asio::ip::address const& address)
|
Endpoint from_asio (boost::asio::ip::address const& address)
|
||||||
{
|
{
|
||||||
if (address.is_v4 ())
|
return Endpoint {address};
|
||||||
{
|
|
||||||
boost::asio::ip::address_v4::bytes_type const bytes (
|
|
||||||
address.to_v4().to_bytes());
|
|
||||||
return Endpoint (AddressV4 (
|
|
||||||
bytes [0], bytes [1], bytes [2], bytes [3]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// VFALCO TODO IPv6 support
|
|
||||||
assert(false);
|
|
||||||
return Endpoint();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Endpoint from_asio (boost::asio::ip::tcp::endpoint const& endpoint)
|
Endpoint from_asio (boost::asio::ip::tcp::endpoint const& endpoint)
|
||||||
{
|
{
|
||||||
return from_asio (endpoint.address()).at_port (endpoint.port());
|
return Endpoint {endpoint.address(), endpoint.port()};
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::ip::address to_asio_address (Endpoint const& endpoint)
|
boost::asio::ip::address to_asio_address (Endpoint const& endpoint)
|
||||||
{
|
{
|
||||||
if (endpoint.address().is_v4())
|
return endpoint.address();
|
||||||
{
|
|
||||||
return boost::asio::ip::address (
|
|
||||||
boost::asio::ip::address_v4 (
|
|
||||||
endpoint.address().to_v4().value));
|
|
||||||
}
|
|
||||||
|
|
||||||
// VFALCO TODO IPv6 support
|
|
||||||
assert(false);
|
|
||||||
return boost::asio::ip::address (
|
|
||||||
boost::asio::ip::address_v6 ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::ip::tcp::endpoint to_asio_endpoint (Endpoint const& endpoint)
|
boost::asio::ip::tcp::endpoint to_asio_endpoint (Endpoint const& endpoint)
|
||||||
{
|
{
|
||||||
return boost::asio::ip::tcp::endpoint (
|
return boost::asio::ip::tcp::endpoint {endpoint.address(), endpoint.port()};
|
||||||
to_asio_address (endpoint), endpoint.port());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ripple/beast/net/IPAddressV4.h>
|
#include <ripple/beast/net/IPAddressV4.h>
|
||||||
#include <ripple/beast/net/detail/Parse.h>
|
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@@ -29,154 +28,26 @@
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace IP {
|
namespace IP {
|
||||||
|
|
||||||
AddressV4::AddressV4 ()
|
|
||||||
: value (0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressV4::AddressV4 (std::uint32_t value_)
|
|
||||||
: value (value_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressV4::AddressV4 (std::uint8_t a, std::uint8_t b, std::uint8_t c, std::uint8_t d)
|
|
||||||
: value ((a<<24)|(b<<16)|(c<<8)|d)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair <AddressV4, bool> AddressV4::from_string (std::string const& s)
|
|
||||||
{
|
|
||||||
std::stringstream is (s);
|
|
||||||
AddressV4 addr;
|
|
||||||
is >> addr;
|
|
||||||
if (! is.fail() && is.rdbuf()->in_avail() == 0)
|
|
||||||
return std::make_pair (addr, true);
|
|
||||||
return std::make_pair (AddressV4 (), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressV4 AddressV4::broadcast (AddressV4 const& address)
|
|
||||||
{
|
|
||||||
return broadcast (address, netmask (address));
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressV4 AddressV4::broadcast (
|
|
||||||
AddressV4 const& address, AddressV4 const& mask)
|
|
||||||
{
|
|
||||||
return AddressV4 (address.value | (mask.value ^ 0xffffffff));
|
|
||||||
}
|
|
||||||
|
|
||||||
char AddressV4::get_class (AddressV4 const& addr)
|
|
||||||
{
|
|
||||||
static char const* table = "AAAABBCD";
|
|
||||||
return table [(addr.value & 0xE0000000) >> 29];
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressV4 AddressV4::netmask (char address_class)
|
|
||||||
{
|
|
||||||
switch (address_class)
|
|
||||||
{
|
|
||||||
case 'A': return AddressV4 (0xff000000);
|
|
||||||
case 'B': return AddressV4 (0xffff0000);
|
|
||||||
case 'C': return AddressV4 (0xffffff00);
|
|
||||||
case 'D':
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return AddressV4 (0xffffffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressV4 AddressV4::netmask (AddressV4 const& addr)
|
|
||||||
{
|
|
||||||
return netmask (get_class (addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressV4::Proxy <true> AddressV4::operator[] (std::size_t index) const
|
|
||||||
{
|
|
||||||
switch (index)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
throw std::out_of_range ("bad array index");
|
|
||||||
case 0: return Proxy <true> (24, &value);
|
|
||||||
case 1: return Proxy <true> (16, &value);
|
|
||||||
case 2: return Proxy <true> ( 8, &value);
|
|
||||||
case 3: return Proxy <true> ( 0, &value);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
AddressV4::Proxy <false> AddressV4::operator[] (std::size_t index)
|
|
||||||
{
|
|
||||||
switch (index)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
throw std::out_of_range ("bad array index");
|
|
||||||
case 0: return Proxy <false> (24, &value);
|
|
||||||
case 1: return Proxy <false> (16, &value);
|
|
||||||
case 2: return Proxy <false> ( 8, &value);
|
|
||||||
case 3: return Proxy <false> ( 0, &value);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool is_loopback (AddressV4 const& addr)
|
|
||||||
{
|
|
||||||
return (addr.value & 0xff000000) == 0x7f000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_unspecified (AddressV4 const& addr)
|
|
||||||
{
|
|
||||||
return addr.value == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_multicast (AddressV4 const& addr)
|
|
||||||
{
|
|
||||||
return (addr.value & 0xf0000000) == 0xe0000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_private (AddressV4 const& addr)
|
bool is_private (AddressV4 const& addr)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
((addr.value & 0xff000000) == 0x0a000000) || // Prefix /8, 10. #.#.#
|
((addr.to_ulong() & 0xff000000) == 0x0a000000) || // Prefix /8, 10. #.#.#
|
||||||
((addr.value & 0xfff00000) == 0xac100000) || // Prefix /12 172. 16.#.# - 172.31.#.#
|
((addr.to_ulong() & 0xfff00000) == 0xac100000) || // Prefix /12 172. 16.#.# - 172.31.#.#
|
||||||
((addr.value & 0xffff0000) == 0xc0a80000) || // Prefix /16 192.168.#.#
|
((addr.to_ulong() & 0xffff0000) == 0xc0a80000) || // Prefix /16 192.168.#.#
|
||||||
is_loopback (addr);
|
addr.is_loopback();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_public (AddressV4 const& addr)
|
bool is_public (AddressV4 const& addr)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
! is_private (addr) &&
|
! is_private (addr) &&
|
||||||
! is_multicast (addr);
|
! addr.is_multicast();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
char get_class (AddressV4 const& addr)
|
||||||
|
|
||||||
std::string to_string (AddressV4 const& addr)
|
|
||||||
{
|
{
|
||||||
std::string s;
|
static char const* table = "AAAABBCD";
|
||||||
s.reserve (15);
|
return table [(addr.to_ulong() & 0xE0000000) >> 29];
|
||||||
s =
|
|
||||||
std::to_string (addr[0]) + "." +
|
|
||||||
std::to_string (addr[1]) + "." +
|
|
||||||
std::to_string (addr[2]) + "." +
|
|
||||||
std::to_string (addr[3]);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::istream& operator>> (std::istream& is, AddressV4& addr)
|
|
||||||
{
|
|
||||||
std::uint8_t octet [4];
|
|
||||||
is >> IP::detail::integer (octet [0]);
|
|
||||||
for (int i = 1; i < 4; ++i)
|
|
||||||
{
|
|
||||||
if (!is || !IP::detail::expect(is, '.'))
|
|
||||||
return is;
|
|
||||||
is >> IP::detail::integer (octet [i]);
|
|
||||||
if (!is)
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
addr = AddressV4 (octet[0], octet[1], octet[2], octet[3]);
|
|
||||||
return is;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,62 +21,25 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ripple/beast/net/IPAddressV6.h>
|
#include <ripple/beast/net/IPAddressV6.h>
|
||||||
|
#include <ripple/beast/net/IPAddressV4.h>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace IP {
|
namespace IP {
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
bool is_private (AddressV6 const& addr)
|
||||||
|
|
||||||
bool is_loopback (AddressV6 const&)
|
|
||||||
{
|
{
|
||||||
// VFALCO TODO
|
return ((addr.to_bytes()[0] & 0xfd) || // TODO fc00::/8 too ?
|
||||||
assert(false);
|
(addr.is_v4_mapped() && is_private(addr.to_v4())) );
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_unspecified (AddressV6 const&)
|
bool is_public (AddressV6 const& addr)
|
||||||
{
|
{
|
||||||
// VFALCO TODO
|
// TODO is this correct?
|
||||||
assert(false);
|
return
|
||||||
return false;
|
! is_private (addr) &&
|
||||||
|
! addr.is_multicast();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_multicast (AddressV6 const&)
|
|
||||||
{
|
|
||||||
// VFALCO TODO
|
|
||||||
assert(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_private (AddressV6 const&)
|
|
||||||
{
|
|
||||||
// VFALCO TODO
|
|
||||||
assert(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_public (AddressV6 const&)
|
|
||||||
{
|
|
||||||
// VFALCO TODO
|
|
||||||
assert(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
std::string to_string (AddressV6 const&)
|
|
||||||
{
|
|
||||||
// VFALCO TODO
|
|
||||||
assert(false);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::istream& operator>> (std::istream& is, AddressV6&)
|
|
||||||
{
|
|
||||||
// VFALCO TODO
|
|
||||||
assert(false);
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ripple/beast/net/IPEndpoint.h>
|
#include <ripple/beast/net/IPEndpoint.h>
|
||||||
#include <ripple/beast/net/detail/Parse.h>
|
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace IP {
|
namespace IP {
|
||||||
@@ -44,7 +43,7 @@ std::pair <Endpoint, bool> Endpoint::from_string_checked (std::string const& s)
|
|||||||
is >> endpoint;
|
is >> endpoint;
|
||||||
if (! is.fail() && is.rdbuf()->in_avail() == 0)
|
if (! is.fail() && is.rdbuf()->in_avail() == 0)
|
||||||
return std::make_pair (endpoint, true);
|
return std::make_pair (endpoint, true);
|
||||||
return std::make_pair (Endpoint (), false);
|
return std::make_pair (Endpoint {}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Endpoint Endpoint::from_string (std::string const& s)
|
Endpoint Endpoint::from_string (std::string const& s)
|
||||||
@@ -53,69 +52,26 @@ Endpoint Endpoint::from_string (std::string const& s)
|
|||||||
from_string_checked (s));
|
from_string_checked (s));
|
||||||
if (result.second)
|
if (result.second)
|
||||||
return result.first;
|
return result.first;
|
||||||
return Endpoint();
|
return Endpoint {};
|
||||||
}
|
|
||||||
|
|
||||||
// VFALCO NOTE This is a hack to support legacy data format
|
|
||||||
//
|
|
||||||
Endpoint Endpoint::from_string_altform (std::string const& s)
|
|
||||||
{
|
|
||||||
// Accept the regular form if it parses
|
|
||||||
{
|
|
||||||
Endpoint ep (Endpoint::from_string (s));
|
|
||||||
if (! is_unspecified (ep))
|
|
||||||
return ep;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now try the alt form
|
|
||||||
std::stringstream is (s);
|
|
||||||
|
|
||||||
AddressV4 v4;
|
|
||||||
is >> v4;
|
|
||||||
if (! is.fail())
|
|
||||||
{
|
|
||||||
Endpoint ep (v4);
|
|
||||||
|
|
||||||
if (is.rdbuf()->in_avail()>0)
|
|
||||||
{
|
|
||||||
if (! IP::detail::expect_whitespace (is))
|
|
||||||
return Endpoint();
|
|
||||||
|
|
||||||
while (is.rdbuf()->in_avail()>0)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
is.get(c);
|
|
||||||
if (!isspace (static_cast<unsigned char>(c)))
|
|
||||||
{
|
|
||||||
is.unget();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Port port;
|
|
||||||
is >> port;
|
|
||||||
if (is.fail())
|
|
||||||
return Endpoint();
|
|
||||||
|
|
||||||
return ep.at_port (port);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Just an address with no port
|
|
||||||
return ep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Could be V6 here...
|
|
||||||
|
|
||||||
return Endpoint();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Endpoint::to_string () const
|
std::string Endpoint::to_string () const
|
||||||
{
|
{
|
||||||
std::string s (address ().to_string ());
|
std::string s;
|
||||||
if (port() != 0)
|
s.reserve(
|
||||||
s = s + ":" + std::to_string (port());
|
(address().is_v6() ? INET6_ADDRSTRLEN-1 : 15) +
|
||||||
|
(port() == 0 ? 0 : 6 + (address().is_v6() ? 2 : 0)));
|
||||||
|
|
||||||
|
if (port() != 0 && address().is_v6())
|
||||||
|
s += '[';
|
||||||
|
s += address ().to_string();
|
||||||
|
if (port())
|
||||||
|
{
|
||||||
|
if (address().is_v6())
|
||||||
|
s += ']';
|
||||||
|
s += ":" + std::to_string (port());
|
||||||
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,34 +94,88 @@ bool operator< (Endpoint const& lhs, Endpoint const& rhs)
|
|||||||
|
|
||||||
std::istream& operator>> (std::istream& is, Endpoint& endpoint)
|
std::istream& operator>> (std::istream& is, Endpoint& endpoint)
|
||||||
{
|
{
|
||||||
// VFALCO TODO Support ipv6!
|
std::string addrStr;
|
||||||
|
// valid addresses only need INET6_ADDRSTRLEN-1 chars, but allow the extra
|
||||||
|
// char to check for invalid lengths
|
||||||
|
addrStr.reserve(INET6_ADDRSTRLEN);
|
||||||
|
char i {0};
|
||||||
|
char readTo {0};
|
||||||
|
is.get(i);
|
||||||
|
if (i == '[') // we are an IPv6 endpoint
|
||||||
|
readTo = ']';
|
||||||
|
else
|
||||||
|
addrStr+=i;
|
||||||
|
|
||||||
Address addr;
|
while (is && is.rdbuf()->in_avail() > 0 && is.get(i))
|
||||||
is >> addr;
|
|
||||||
if (is.fail())
|
|
||||||
return is;
|
|
||||||
|
|
||||||
if (is.rdbuf()->in_avail()>0)
|
|
||||||
{
|
{
|
||||||
char c;
|
// NOTE: There is a legacy data format
|
||||||
is.get(c);
|
// that allowed space to be used as address / port separator
|
||||||
if (c != ':')
|
// so we continue to honor that here by assuming we are at the end
|
||||||
|
// of the address portion if we hit a space (or the separator
|
||||||
|
// we were expecting to see)
|
||||||
|
if (isspace(static_cast<unsigned char>(i)) || (readTo && i == readTo))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((i == '.') ||
|
||||||
|
(i >= '0' && i <= ':') ||
|
||||||
|
(i >= 'a' && i <= 'f') ||
|
||||||
|
(i >= 'A' && i <= 'F'))
|
||||||
|
{
|
||||||
|
addrStr+=i;
|
||||||
|
|
||||||
|
// don't exceed a reasonable length...
|
||||||
|
if ( addrStr.size() == INET6_ADDRSTRLEN ||
|
||||||
|
(readTo && readTo == ':' && addrStr.size() > 15))
|
||||||
|
{
|
||||||
|
is.setstate (std::ios_base::failbit);
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! readTo && (i == '.' || i == ':'))
|
||||||
|
{
|
||||||
|
// if we see a dot first, must be IPv4
|
||||||
|
// otherwise must be non-bracketed IPv6
|
||||||
|
readTo = (i == '.') ? ':' : ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // invalid char
|
||||||
{
|
{
|
||||||
is.unget();
|
is.unget();
|
||||||
endpoint = Endpoint (addr);
|
is.setstate (std::ios_base::failbit);
|
||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readTo == ']' && is.rdbuf()->in_avail() > 0)
|
||||||
|
{
|
||||||
|
is.get(i);
|
||||||
|
if (! (isspace(static_cast<unsigned char>(i)) || i == ':'))
|
||||||
|
{
|
||||||
|
is.unget();
|
||||||
|
is.setstate (std::ios_base::failbit);
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::system::error_code ec;
|
||||||
|
auto addr = Address::from_string(addrStr, ec);
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
is.setstate (std::ios_base::failbit);
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is.rdbuf()->in_avail() > 0)
|
||||||
|
{
|
||||||
Port port;
|
Port port;
|
||||||
is >> port;
|
is >> port;
|
||||||
if (is.fail())
|
if (is.fail())
|
||||||
return is;
|
return is;
|
||||||
|
|
||||||
endpoint = Endpoint (addr, port);
|
endpoint = Endpoint (addr, port);
|
||||||
return is;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
endpoint = Endpoint (addr);
|
||||||
|
|
||||||
endpoint = Endpoint (addr);
|
|
||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
#include <ripple/beast/net/IPEndpoint.h>
|
#include <ripple/beast/net/IPEndpoint.h>
|
||||||
#include <boost/beast/core/string.hpp>
|
#include <boost/beast/core/string.hpp>
|
||||||
#include <ripple/beast/utility/Journal.h>
|
#include <ripple/beast/utility/Journal.h>
|
||||||
#include <boost/asio/ip/tcp.hpp> // VFALCO FIX: This include should not be here
|
|
||||||
#include <boost/filesystem.hpp> // VFALCO FIX: This include should not be here
|
#include <boost/filesystem.hpp> // VFALCO FIX: This include should not be here
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
@@ -174,8 +173,7 @@ public:
|
|||||||
std::size_t WORKERS = 0;
|
std::size_t WORKERS = 0;
|
||||||
|
|
||||||
// These override the command line client settings
|
// These override the command line client settings
|
||||||
boost::optional<boost::asio::ip::address_v4> rpc_ip;
|
boost::optional<beast::IP::Endpoint> rpc_ip;
|
||||||
boost::optional<std::uint16_t> rpc_port;
|
|
||||||
|
|
||||||
std::unordered_set<uint256, beast::uhash<>> features;
|
std::unordered_set<uint256, beast::uhash<>> features;
|
||||||
|
|
||||||
|
|||||||
@@ -1355,9 +1355,10 @@ rpcClient(std::vector<std::string> const& args,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config.rpc_ip)
|
if (config.rpc_ip)
|
||||||
setup.client.ip = config.rpc_ip->to_string();
|
{
|
||||||
if (config.rpc_port)
|
setup.client.ip = config.rpc_ip->address().to_string();
|
||||||
setup.client.port = *config.rpc_port;
|
setup.client.port = config.rpc_ip->port();
|
||||||
|
}
|
||||||
|
|
||||||
Json::Value jvParams (Json::arrayValue);
|
Json::Value jvParams (Json::arrayValue);
|
||||||
|
|
||||||
|
|||||||
@@ -1048,11 +1048,9 @@ setup_Overlay (BasicConfig const& config)
|
|||||||
set (ip, "public_ip", section);
|
set (ip, "public_ip", section);
|
||||||
if (! ip.empty ())
|
if (! ip.empty ())
|
||||||
{
|
{
|
||||||
bool valid;
|
boost::system::error_code ec;
|
||||||
std::tie (setup.public_ip, valid) =
|
setup.public_ip = beast::IP::Address::from_string (ip, ec);
|
||||||
beast::IP::Address::from_string (ip);
|
if (ec || beast::IP::is_private (setup.public_ip))
|
||||||
if (! valid || ! setup.public_ip.is_v4() ||
|
|
||||||
is_private (setup.public_ip))
|
|
||||||
Throw<std::runtime_error> ("Configured public IP is invalid");
|
Throw<std::runtime_error> ("Configured public IP is invalid");
|
||||||
}
|
}
|
||||||
return setup;
|
return setup;
|
||||||
|
|||||||
@@ -1019,37 +1019,75 @@ PeerImp::onMessage (std::shared_ptr <protocol::TMEndpoints> const& m)
|
|||||||
|
|
||||||
std::vector <PeerFinder::Endpoint> endpoints;
|
std::vector <PeerFinder::Endpoint> endpoints;
|
||||||
|
|
||||||
endpoints.reserve (m->endpoints().size());
|
if (m->endpoints_v2().size())
|
||||||
|
|
||||||
for (int i = 0; i < m->endpoints ().size (); ++i)
|
|
||||||
{
|
{
|
||||||
PeerFinder::Endpoint endpoint;
|
endpoints.reserve (m->endpoints_v2().size());
|
||||||
protocol::TMEndpoint const& tm (m->endpoints(i));
|
for (auto const& tm : m->endpoints_v2 ())
|
||||||
|
|
||||||
// hops
|
|
||||||
endpoint.hops = tm.hops();
|
|
||||||
|
|
||||||
// ipv4
|
|
||||||
if (endpoint.hops > 0)
|
|
||||||
{
|
{
|
||||||
in_addr addr;
|
// these endpoint strings support ipv4 and ipv6
|
||||||
addr.s_addr = tm.ipv4().ipv4();
|
auto result = beast::IP::Endpoint::from_string_checked(tm.endpoint());
|
||||||
beast::IP::AddressV4 v4 (ntohl (addr.s_addr));
|
if (! result.second)
|
||||||
endpoint.address = beast::IP::Endpoint (v4, tm.ipv4().ipv4port ());
|
{
|
||||||
}
|
JLOG(p_journal_.error()) <<
|
||||||
else
|
"failed to parse incoming endpoint: {" <<
|
||||||
{
|
tm.endpoint() << "}";
|
||||||
// This Endpoint describes the peer we are connected to.
|
continue;
|
||||||
// We will take the remote address seen on the socket and
|
}
|
||||||
// store that in the IP::Endpoint. If this is the first time,
|
|
||||||
// then we'll verify that their listener can receive incoming
|
|
||||||
// by performing a connectivity test.
|
|
||||||
//
|
|
||||||
endpoint.address = remote_address_.at_port (
|
|
||||||
tm.ipv4().ipv4port ());
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoints.push_back (endpoint);
|
// If hops == 0, this Endpoint describes the peer we are connected
|
||||||
|
// to -- in that case, we take the remote address seen on the
|
||||||
|
// socket and store that in the IP::Endpoint. If this is the first
|
||||||
|
// time, then we'll verify that their listener can receive incoming
|
||||||
|
// by performing a connectivity test. if hops > 0, then we just
|
||||||
|
// take the address/port we were given
|
||||||
|
|
||||||
|
endpoints.emplace_back(
|
||||||
|
tm.hops() > 0 ?
|
||||||
|
result.first :
|
||||||
|
remote_address_.at_port(result.first.port()),
|
||||||
|
tm.hops());
|
||||||
|
JLOG(p_journal_.trace()) <<
|
||||||
|
"got v2 EP: " << endpoints.back().address <<
|
||||||
|
", hops = " << endpoints.back().hops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// this branch can be removed once the entire network is operating with
|
||||||
|
// endpoint_v2() items (strings)
|
||||||
|
endpoints.reserve (m->endpoints().size());
|
||||||
|
for (int i = 0; i < m->endpoints ().size (); ++i)
|
||||||
|
{
|
||||||
|
PeerFinder::Endpoint endpoint;
|
||||||
|
protocol::TMEndpoint const& tm (m->endpoints(i));
|
||||||
|
|
||||||
|
// hops
|
||||||
|
endpoint.hops = tm.hops();
|
||||||
|
|
||||||
|
// ipv4
|
||||||
|
if (endpoint.hops > 0)
|
||||||
|
{
|
||||||
|
in_addr addr;
|
||||||
|
addr.s_addr = tm.ipv4().ipv4();
|
||||||
|
beast::IP::AddressV4 v4 (ntohl (addr.s_addr));
|
||||||
|
endpoint.address = beast::IP::Endpoint (v4, tm.ipv4().ipv4port ());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This Endpoint describes the peer we are connected to.
|
||||||
|
// We will take the remote address seen on the socket and
|
||||||
|
// store that in the IP::Endpoint. If this is the first time,
|
||||||
|
// then we'll verify that their listener can receive incoming
|
||||||
|
// by performing a connectivity test.
|
||||||
|
//
|
||||||
|
endpoint.address = remote_address_.at_port (
|
||||||
|
tm.ipv4().ipv4port ());
|
||||||
|
}
|
||||||
|
endpoints.push_back (endpoint);
|
||||||
|
JLOG(p_journal_.trace()) <<
|
||||||
|
"got v1 EP: " << endpoints.back().address <<
|
||||||
|
", hops = " << endpoints.back().hops;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! endpoints.empty())
|
if (! endpoints.empty())
|
||||||
|
|||||||
@@ -514,16 +514,24 @@ PeerImp::sendEndpoints (FwdIt first, FwdIt last)
|
|||||||
for (;first != last; ++first)
|
for (;first != last; ++first)
|
||||||
{
|
{
|
||||||
auto const& ep = *first;
|
auto const& ep = *first;
|
||||||
|
// eventually remove endpoints and just keep endpoints_v2
|
||||||
|
// (once we are sure the entire network understands endpoints_v2)
|
||||||
protocol::TMEndpoint& tme (*tm.add_endpoints());
|
protocol::TMEndpoint& tme (*tm.add_endpoints());
|
||||||
if (ep.address.is_v4())
|
if (ep.address.is_v4())
|
||||||
tme.mutable_ipv4()->set_ipv4(
|
tme.mutable_ipv4()->set_ipv4(
|
||||||
beast::toNetworkByteOrder (ep.address.to_v4().value));
|
beast::toNetworkByteOrder<std::uint32_t> (
|
||||||
|
ep.address.to_v4().to_ulong()));
|
||||||
else
|
else
|
||||||
tme.mutable_ipv4()->set_ipv4(0);
|
tme.mutable_ipv4()->set_ipv4(0);
|
||||||
tme.mutable_ipv4()->set_ipv4port (ep.address.port());
|
tme.mutable_ipv4()->set_ipv4port (ep.address.port());
|
||||||
tme.set_hops (ep.hops);
|
tme.set_hops (ep.hops);
|
||||||
|
|
||||||
|
// add v2 endpoints (strings)
|
||||||
|
auto& tme2 (*tm.add_endpoints_v2());
|
||||||
|
tme2.set_endpoint(ep.address.to_string());
|
||||||
|
tme2.set_hops (ep.hops);
|
||||||
}
|
}
|
||||||
tm.set_version (1);
|
tm.set_version (2);
|
||||||
|
|
||||||
send (std::make_shared <Message> (tm, protocol::mtENDPOINTS));
|
send (std::make_shared <Message> (tm, protocol::mtENDPOINTS));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,19 +114,14 @@ buildHello (
|
|||||||
TokenType::NodePublic,
|
TokenType::NodePublic,
|
||||||
app.nodeIdentity().first));
|
app.nodeIdentity().first));
|
||||||
h.set_nodeproof (sig.data(), sig.size());
|
h.set_nodeproof (sig.data(), sig.size());
|
||||||
// h.set_ipv4port (portNumber); // ignored now
|
|
||||||
h.set_testnet (false);
|
h.set_testnet (false);
|
||||||
|
|
||||||
if (remote.is_v4())
|
if (beast::IP::is_public (remote))
|
||||||
{
|
{
|
||||||
auto addr = remote.to_v4 ();
|
// Connection is to a public IP
|
||||||
if (is_public (addr))
|
h.set_remote_ip_str (remote.to_string());
|
||||||
{
|
if (! public_ip.is_unspecified())
|
||||||
// Connection is to a public IP
|
h.set_local_ip_str (public_ip.to_string());
|
||||||
h.set_remote_ip (addr.value);
|
|
||||||
if (public_ip != beast::IP::Address())
|
|
||||||
h.set_local_ip (public_ip.to_v4().value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We always advertise ourselves as private in the HELLO message. This
|
// We always advertise ourselves as private in the HELLO message. This
|
||||||
@@ -174,13 +169,11 @@ appendHello (boost::beast::http::fields& h,
|
|||||||
h.insert ("Previous-Ledger", boost::beast::detail::base64_encode (
|
h.insert ("Previous-Ledger", boost::beast::detail::base64_encode (
|
||||||
hello.ledgerprevious()));
|
hello.ledgerprevious()));
|
||||||
|
|
||||||
if (hello.has_local_ip())
|
if (hello.has_local_ip_str())
|
||||||
h.insert ("Local-IP", beast::IP::to_string (
|
h.insert ("Local-IP", hello.local_ip_str());
|
||||||
beast::IP::AddressV4(hello.local_ip())));
|
|
||||||
|
|
||||||
if (hello.has_remote_ip())
|
if (hello.has_remote_ip())
|
||||||
h.insert ("Remote-IP", beast::IP::to_string (
|
h.insert ("Remote-IP", hello.remote_ip_str());
|
||||||
beast::IP::AddressV4(hello.remote_ip())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ProtocolVersion>
|
std::vector<ProtocolVersion>
|
||||||
@@ -306,14 +299,16 @@ parseHello (bool request, boost::beast::http::fields const& h, beast::Journal jo
|
|||||||
auto const iter = h.find ("Local-IP");
|
auto const iter = h.find ("Local-IP");
|
||||||
if (iter != h.end())
|
if (iter != h.end())
|
||||||
{
|
{
|
||||||
bool valid;
|
boost::system::error_code ec;
|
||||||
beast::IP::Address address;
|
auto address =
|
||||||
std::tie (address, valid) =
|
beast::IP::Address::from_string (iter->value().to_string(), ec);
|
||||||
beast::IP::Address::from_string (iter->value().to_string());
|
if (ec)
|
||||||
if (!valid)
|
{
|
||||||
|
JLOG(journal.warn()) << "invalid Local-IP: "
|
||||||
|
<< iter->value().to_string();
|
||||||
return boost::none;
|
return boost::none;
|
||||||
if (address.is_v4())
|
}
|
||||||
hello.set_local_ip(address.to_v4().value);
|
hello.set_local_ip_str(address.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,14 +316,16 @@ parseHello (bool request, boost::beast::http::fields const& h, beast::Journal jo
|
|||||||
auto const iter = h.find ("Remote-IP");
|
auto const iter = h.find ("Remote-IP");
|
||||||
if (iter != h.end())
|
if (iter != h.end())
|
||||||
{
|
{
|
||||||
bool valid;
|
boost::system::error_code ec;
|
||||||
beast::IP::Address address;
|
auto address =
|
||||||
std::tie (address, valid) =
|
beast::IP::Address::from_string (iter->value().to_string(), ec);
|
||||||
beast::IP::Address::from_string (iter->value().to_string());
|
if (ec)
|
||||||
if (!valid)
|
{
|
||||||
|
JLOG(journal.warn()) << "invalid Remote-IP: "
|
||||||
|
<< iter->value().to_string();
|
||||||
return boost::none;
|
return boost::none;
|
||||||
if (address.is_v4())
|
}
|
||||||
hello.set_remote_ip(address.to_v4().value);
|
hello.set_remote_ip_str(address.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,33 +409,50 @@ verifyHello (protocol::TMHello const& h,
|
|||||||
return boost::none;
|
return boost::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h.has_local_ip () &&
|
if (h.has_local_ip_str () &&
|
||||||
is_public (remote) &&
|
is_public (remote))
|
||||||
remote.is_v4 () &&
|
|
||||||
(remote.to_v4().value != h.local_ip ()))
|
|
||||||
{
|
{
|
||||||
// Remote asked us to confirm connection is from
|
boost::system::error_code ec;
|
||||||
// correct IP
|
auto local_ip =
|
||||||
JLOG(journal.info()) <<
|
beast::IP::Address::from_string (h.local_ip_str(), ec);
|
||||||
"Hello: Disconnect: Peer IP is " <<
|
if (ec)
|
||||||
beast::IP::to_string (remote.to_v4())
|
{
|
||||||
<< " not " <<
|
JLOG(journal.warn()) << "invalid local-ip: " << h.local_ip_str();
|
||||||
beast::IP::to_string (beast::IP::AddressV4 (h.local_ip()));
|
return boost::none;
|
||||||
return boost::none;
|
}
|
||||||
|
|
||||||
|
if (remote.address() != local_ip)
|
||||||
|
{
|
||||||
|
// Remote asked us to confirm connection is from correct IP
|
||||||
|
JLOG(journal.info()) <<
|
||||||
|
"Hello: Disconnect: Peer IP is " << remote.address().to_string()
|
||||||
|
<< " not " << local_ip.to_string();
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h.has_remote_ip() && is_public (remote) &&
|
if (h.has_remote_ip_str () &&
|
||||||
(public_ip != beast::IP::Address()) &&
|
is_public (remote) &&
|
||||||
(h.remote_ip() != public_ip.to_v4().value))
|
(! beast::IP::is_unspecified(public_ip)))
|
||||||
{
|
{
|
||||||
// We know our public IP and peer reports connection
|
boost::system::error_code ec;
|
||||||
// from some other IP
|
auto remote_ip =
|
||||||
JLOG(journal.info()) <<
|
beast::IP::Address::from_string (h.remote_ip_str(), ec);
|
||||||
"Hello: Disconnect: Our IP is " <<
|
if (ec)
|
||||||
beast::IP::to_string (public_ip.to_v4())
|
{
|
||||||
<< " not " <<
|
JLOG(journal.warn()) << "invalid remote-ip: " << h.remote_ip_str();
|
||||||
beast::IP::to_string (beast::IP::AddressV4 (h.remote_ip()));
|
return boost::none;
|
||||||
return boost::none;
|
}
|
||||||
|
|
||||||
|
if (remote_ip != public_ip)
|
||||||
|
{
|
||||||
|
// We know our public IP and peer reports connection from some
|
||||||
|
// other IP
|
||||||
|
JLOG(journal.info()) <<
|
||||||
|
"Hello: Disconnect: Our IP is " << public_ip.to_string()
|
||||||
|
<< " not " << remote_ip.to_string();
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return publicKey;
|
return publicKey;
|
||||||
|
|||||||
@@ -618,8 +618,15 @@ public:
|
|||||||
{
|
{
|
||||||
Endpoint ep;
|
Endpoint ep;
|
||||||
ep.hops = 0;
|
ep.hops = 0;
|
||||||
|
// we use the unspecified (0) address here because the value is
|
||||||
|
// irrelevant to recipients. When peers receive an endpoint
|
||||||
|
// with 0 hops, they use the socket remote_addr instead of the
|
||||||
|
// value in the message. Furthermore, since the address value
|
||||||
|
// is ignored, the type/version (ipv4 vs ipv6) doesn't matter
|
||||||
|
// either. ipv6 has a slightly more compact string
|
||||||
|
// representation of 0, so use that for self entries.
|
||||||
ep.address = beast::IP::Endpoint (
|
ep.address = beast::IP::Endpoint (
|
||||||
beast::IP::AddressV4 ()).at_port (
|
beast::IP::AddressV6 ()).at_port (
|
||||||
config_.listeningPort);
|
config_.listeningPort);
|
||||||
for (auto& t : targets)
|
for (auto& t : targets)
|
||||||
t.insert (ep);
|
t.insert (ep);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public:
|
|||||||
{
|
{
|
||||||
beast::IP::Endpoint ep (beast::IP::Endpoint::from_string (m_strings [i]));
|
beast::IP::Endpoint ep (beast::IP::Endpoint::from_string (m_strings [i]));
|
||||||
if (is_unspecified (ep))
|
if (is_unspecified (ep))
|
||||||
ep = beast::IP::Endpoint::from_string_altform (m_strings [i]);
|
ep = beast::IP::Endpoint::from_string (m_strings [i]);
|
||||||
if (! is_unspecified (ep))
|
if (! is_unspecified (ep))
|
||||||
results.addresses.push_back (ep);
|
results.addresses.push_back (ep);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,15 +89,17 @@ message TMHello
|
|||||||
required bytes nodeProof = 4;
|
required bytes nodeProof = 4;
|
||||||
optional string fullVersion = 5;
|
optional string fullVersion = 5;
|
||||||
optional uint64 netTime = 6;
|
optional uint64 netTime = 6;
|
||||||
optional uint32 ipv4Port = 7;
|
optional uint32 ipv4Port = 7; // NOT USED
|
||||||
optional uint32 ledgerIndex = 8;
|
optional uint32 ledgerIndex = 8;
|
||||||
optional bytes ledgerClosed = 9; // our last closed ledger
|
optional bytes ledgerClosed = 9; // our last closed ledger
|
||||||
optional bytes ledgerPrevious = 10; // the ledger before the last closed ledger
|
optional bytes ledgerPrevious = 10; // the ledger before the last closed ledger
|
||||||
optional bool nodePrivate = 11; // Request to not forward IP.
|
optional bool nodePrivate = 11; // Request to not forward IP.
|
||||||
optional TMProofWork proofOfWork = 12; // request/provide proof of work
|
optional TMProofWork proofOfWork = 12; // request/provide proof of work
|
||||||
optional bool testNet = 13; // Running as testnet.
|
optional bool testNet = 13; // Running as testnet.
|
||||||
optional uint32 local_ip = 14; // our public IP
|
optional uint32 local_ip = 14; // NOT USED -- our public IP
|
||||||
optional uint32 remote_ip = 15; // IP we see connection from
|
optional uint32 remote_ip = 15; // NOT USED -- IP we see connection from
|
||||||
|
optional string local_ip_str = 16; // our public IP
|
||||||
|
optional string remote_ip_str = 17; // IP we see connection from
|
||||||
}
|
}
|
||||||
|
|
||||||
// The status of a node in our cluster
|
// The status of a node in our cluster
|
||||||
@@ -234,6 +236,7 @@ message TMIPv4Endpoint
|
|||||||
required uint32 ipv4Port = 2;
|
required uint32 ipv4Port = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this message is obsolete/no longer procesed
|
||||||
message TMPeers
|
message TMPeers
|
||||||
{
|
{
|
||||||
repeated TMIPv4Endpoint nodes = 1;
|
repeated TMIPv4Endpoint nodes = 1;
|
||||||
@@ -254,6 +257,15 @@ message TMEndpoints
|
|||||||
required uint32 version = 1;
|
required uint32 version = 1;
|
||||||
|
|
||||||
repeated TMEndpoint endpoints = 2;
|
repeated TMEndpoint endpoints = 2;
|
||||||
|
|
||||||
|
// An update to the Endpoint type that uses a string
|
||||||
|
// to represent endpoints, thus allowing ipv6 or ipv4 addresses
|
||||||
|
message TMEndpointv2
|
||||||
|
{
|
||||||
|
required string endpoint = 1;
|
||||||
|
required uint32 hops = 2;
|
||||||
|
}
|
||||||
|
repeated TMEndpointv2 endpoints_v2 = 3;
|
||||||
};
|
};
|
||||||
|
|
||||||
message TMIndexedObject
|
message TMIndexedObject
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ ipAllowed (beast::IP::Address const& remoteIp,
|
|||||||
std::vector<beast::IP::Address> const& adminIp)
|
std::vector<beast::IP::Address> const& adminIp)
|
||||||
{
|
{
|
||||||
return std::find_if (adminIp.begin (), adminIp.end (),
|
return std::find_if (adminIp.begin (), adminIp.end (),
|
||||||
[&remoteIp](beast::IP::Address const& ip) { return ip.is_any () ||
|
[&remoteIp](beast::IP::Address const& ip) { return ip.is_unspecified () ||
|
||||||
ip == remoteIp; }) != adminIp.end ();
|
ip == remoteIp; }) != adminIp.end ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1041,10 +1041,11 @@ setup_Client (ServerHandler::Setup& setup)
|
|||||||
return;
|
return;
|
||||||
setup.client.secure =
|
setup.client.secure =
|
||||||
iter->protocol.count("https") > 0;
|
iter->protocol.count("https") > 0;
|
||||||
setup.client.ip = iter->ip.to_string();
|
setup.client.ip =
|
||||||
// VFALCO HACK! to make localhost work
|
beast::IP::is_unspecified(iter->ip) ?
|
||||||
if (setup.client.ip == "0.0.0.0")
|
// VFALCO HACK! to make localhost work
|
||||||
setup.client.ip = "127.0.0.1";
|
(iter->ip.is_v6() ? "::1" : "127.0.0.1") :
|
||||||
|
iter->ip.to_string();
|
||||||
setup.client.port = iter->port;
|
setup.client.port = iter->port;
|
||||||
setup.client.user = iter->user;
|
setup.client.user = iter->user;
|
||||||
setup.client.password = iter->password;
|
setup.client.password = iter->password;
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ populate (Section const& section, std::string const& field, std::ostream& log,
|
|||||||
{
|
{
|
||||||
if (! allowAllIps)
|
if (! allowAllIps)
|
||||||
{
|
{
|
||||||
log << "0.0.0.0 not allowed'" <<
|
log << addr.first.address() << " not allowed'" <<
|
||||||
"' for key '" << field << "' in [" <<
|
"' for key '" << field << "' in [" <<
|
||||||
section.name () << "]";
|
section.name () << "]";
|
||||||
Throw<std::exception> ();
|
Throw<std::exception> ();
|
||||||
@@ -108,8 +108,8 @@ populate (Section const& section, std::string const& field, std::ostream& log,
|
|||||||
|
|
||||||
if (has_any && ! ips->empty ())
|
if (has_any && ! ips->empty ())
|
||||||
{
|
{
|
||||||
log << "IP specified along with 0.0.0.0 '" << ip <<
|
log << "IP specified along with " << addr.first.address() <<
|
||||||
"' for key '" << field << "' in [" <<
|
" '" << ip << "' for key '" << field << "' in [" <<
|
||||||
section.name () << "]";
|
section.name () << "]";
|
||||||
Throw<std::exception> ();
|
Throw<std::exception> ();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,21 +172,12 @@ private:
|
|||||||
while (list2.size () < listSize)
|
while (list2.size () < listSize)
|
||||||
list2.push_back (randomValidator());
|
list2.push_back (randomValidator());
|
||||||
|
|
||||||
|
|
||||||
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
|
||||||
using address_type = boost::asio::ip::address;
|
|
||||||
|
|
||||||
// Use ports of 0 to allow OS selection
|
|
||||||
endpoint_type ep1{address_type::from_string("127.0.0.1"), 0};
|
|
||||||
endpoint_type ep2{address_type::from_string("127.0.0.1"), 0};
|
|
||||||
|
|
||||||
auto const sequence = 1;
|
auto const sequence = 1;
|
||||||
auto const version = 1;
|
auto const version = 1;
|
||||||
NetClock::time_point const expiration =
|
NetClock::time_point const expiration =
|
||||||
env.timeKeeper().now() + 3600s;
|
env.timeKeeper().now() + 3600s;
|
||||||
|
|
||||||
TrustedPublisherServer server1(
|
TrustedPublisherServer server1(
|
||||||
ep1,
|
|
||||||
env.app().getIOService(),
|
env.app().getIOService(),
|
||||||
pubSigningKeys1,
|
pubSigningKeys1,
|
||||||
manifest1,
|
manifest1,
|
||||||
@@ -196,7 +187,6 @@ private:
|
|||||||
list1);
|
list1);
|
||||||
|
|
||||||
TrustedPublisherServer server2(
|
TrustedPublisherServer server2(
|
||||||
ep2,
|
|
||||||
env.app().getIOService(),
|
env.app().getIOService(),
|
||||||
pubSigningKeys2,
|
pubSigningKeys2,
|
||||||
manifest2,
|
manifest2,
|
||||||
@@ -205,14 +195,13 @@ private:
|
|||||||
version,
|
version,
|
||||||
list2);
|
list2);
|
||||||
|
|
||||||
std::uint16_t const port1 = server1.local_endpoint().port();
|
std::stringstream url1, url2;
|
||||||
std::uint16_t const port2 = server2.local_endpoint().port();
|
url1 << "http://" << server1.local_endpoint() << "/validators";
|
||||||
|
url2 << "http://" << server2.local_endpoint() << "/validators";
|
||||||
|
|
||||||
{
|
{
|
||||||
// fetch single site
|
// fetch single site
|
||||||
std::vector<std::string> cfgSites(
|
std::vector<std::string> cfgSites({ url1.str() });
|
||||||
{"http://127.0.0.1:" + std::to_string(port1) + "/validators"});
|
|
||||||
|
|
||||||
auto sites = std::make_unique<ValidatorSite> (
|
auto sites = std::make_unique<ValidatorSite> (
|
||||||
env.app().getIOService(), env.app().validators(), journal);
|
env.app().getIOService(), env.app().validators(), journal);
|
||||||
@@ -229,9 +218,7 @@ private:
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
// fetch multiple sites
|
// fetch multiple sites
|
||||||
std::vector<std::string> cfgSites({
|
std::vector<std::string> cfgSites({ url1.str(), url2.str() });
|
||||||
"http://127.0.0.1:" + std::to_string(port1) + "/validators",
|
|
||||||
"http://127.0.0.1:" + std::to_string(port2) + "/validators"});
|
|
||||||
|
|
||||||
auto sites = std::make_unique<ValidatorSite> (
|
auto sites = std::make_unique<ValidatorSite> (
|
||||||
env.app().getIOService(), env.app().validators(), journal);
|
env.app().getIOService(), env.app().validators(), journal);
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ public:
|
|||||||
BEAST_EXPECT(parseUrl (pUrl, "Mixed://domain/path"));
|
BEAST_EXPECT(parseUrl (pUrl, "Mixed://domain/path"));
|
||||||
BEAST_EXPECT(pUrl.scheme == "mixed");
|
BEAST_EXPECT(pUrl.scheme == "mixed");
|
||||||
BEAST_EXPECT(pUrl.path == "/path");
|
BEAST_EXPECT(pUrl.path == "/path");
|
||||||
|
BEAST_EXPECT(parseUrl (pUrl, "scheme://[::1]:123/path"));
|
||||||
|
BEAST_EXPECT(*pUrl.port == 123);
|
||||||
|
BEAST_EXPECT(pUrl.domain == "::1");
|
||||||
}
|
}
|
||||||
|
|
||||||
void testToString ()
|
void testToString ()
|
||||||
|
|||||||
64
src/test/beast/IPEndpointCommon.h
Normal file
64
src/test/beast/IPEndpointCommon.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2017 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <ripple/beast/net/IPEndpoint.h>
|
||||||
|
#include <ripple/basics/random.h>
|
||||||
|
|
||||||
|
namespace beast {
|
||||||
|
namespace IP {
|
||||||
|
|
||||||
|
inline Endpoint randomEP (bool v4 = true)
|
||||||
|
{
|
||||||
|
using namespace ripple;
|
||||||
|
auto dv4 = []() -> AddressV4::bytes_type {
|
||||||
|
return {{
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX))
|
||||||
|
}};
|
||||||
|
};
|
||||||
|
auto dv6 = []() -> AddressV6::bytes_type {
|
||||||
|
return {{
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX)),
|
||||||
|
static_cast<std::uint8_t>(rand_int<int>(1, UINT8_MAX))
|
||||||
|
}};
|
||||||
|
};
|
||||||
|
return Endpoint {
|
||||||
|
v4 ? Address { AddressV4 {dv4()} } : Address{ AddressV6 {dv6()} },
|
||||||
|
rand_int<std::uint16_t>(1, UINT16_MAX)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,10 +23,12 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ripple/beast/net/IPEndpoint.h>
|
#include <ripple/beast/net/IPEndpoint.h>
|
||||||
#include <ripple/beast/net/detail/Parse.h>
|
|
||||||
|
|
||||||
#include <ripple/beast/unit_test.h>
|
#include <ripple/beast/unit_test.h>
|
||||||
|
#include <ripple/basics/random.h>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <boost/asio/ip/address.hpp>
|
||||||
|
#include <boost/predef.h>
|
||||||
|
#include <test/beast/IPEndpointCommon.h>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@@ -37,91 +39,111 @@ namespace IP {
|
|||||||
class IPEndpoint_test : public unit_test::suite
|
class IPEndpoint_test : public unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void shouldParseV4 (std::string const& s, std::uint32_t value)
|
void shouldParseAddrV4 (
|
||||||
|
std::string const& s,
|
||||||
|
std::uint32_t value,
|
||||||
|
std::string const& normal = "")
|
||||||
{
|
{
|
||||||
std::pair <AddressV4, bool> const result (
|
boost::system::error_code ec;
|
||||||
AddressV4::from_string (s));
|
Address const result {Address::from_string (s, ec)};
|
||||||
|
if (! BEAST_EXPECTS(! ec, ec.message()))
|
||||||
if (BEAST_EXPECT(result.second))
|
return;
|
||||||
{
|
if (! BEAST_EXPECTS(result.is_v4(), s + " not v4"))
|
||||||
if (BEAST_EXPECT(result.first.value == value))
|
return;
|
||||||
{
|
if (! BEAST_EXPECTS(result.to_v4().to_ulong() == value,
|
||||||
BEAST_EXPECT(to_string (result.first) == s);
|
s + " value mismatch"))
|
||||||
}
|
return;
|
||||||
}
|
BEAST_EXPECTS(result.to_string () == (normal.empty() ? s : normal),
|
||||||
|
s + " as string");
|
||||||
}
|
}
|
||||||
|
|
||||||
void failParseV4 (std::string const& s)
|
void failParseAddr (std::string const& s)
|
||||||
{
|
{
|
||||||
unexpected (AddressV4::from_string (s).second);
|
boost::system::error_code ec;
|
||||||
|
auto a = Address::from_string (s, ec);
|
||||||
|
BEAST_EXPECTS(ec, s + " parses as " + a.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
void testAddressV4 ()
|
void testAddressV4 ()
|
||||||
{
|
{
|
||||||
testcase ("AddressV4");
|
testcase ("AddressV4");
|
||||||
|
|
||||||
BEAST_EXPECT(AddressV4().value == 0);
|
BEAST_EXPECT(AddressV4{}.to_ulong() == 0);
|
||||||
BEAST_EXPECT(is_unspecified (AddressV4()));
|
BEAST_EXPECT(is_unspecified (AddressV4{}));
|
||||||
BEAST_EXPECT(AddressV4(0x01020304).value == 0x01020304);
|
BEAST_EXPECT(AddressV4{0x01020304}.to_ulong() == 0x01020304);
|
||||||
BEAST_EXPECT(AddressV4(1, 2, 3, 4).value == 0x01020304);
|
AddressV4::bytes_type d = {{1,2,3,4}};
|
||||||
|
BEAST_EXPECT(AddressV4{d}.to_ulong() == 0x01020304);
|
||||||
|
|
||||||
unexpected (is_unspecified (AddressV4(1, 2, 3, 4)));
|
unexpected (is_unspecified (AddressV4{d}));
|
||||||
|
|
||||||
AddressV4 const v1 (1);
|
AddressV4 const v1 {1};
|
||||||
BEAST_EXPECT(AddressV4(v1).value == 1);
|
BEAST_EXPECT(AddressV4{v1}.to_ulong() == 1);
|
||||||
|
|
||||||
{
|
{
|
||||||
AddressV4 v;
|
AddressV4 v;
|
||||||
v = v1;
|
v = v1;
|
||||||
BEAST_EXPECT(v.value == v1.value);
|
BEAST_EXPECT(v.to_ulong() == v1.to_ulong());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
AddressV4 v;
|
AddressV4 v;
|
||||||
v [0] = 1;
|
auto d = v.to_bytes();
|
||||||
v [1] = 2;
|
d[0] = 1;
|
||||||
v [2] = 3;
|
d[1] = 2;
|
||||||
v [3] = 4;
|
d[2] = 3;
|
||||||
BEAST_EXPECT(v.value == 0x01020304);
|
d[3] = 4;
|
||||||
|
v = AddressV4{d};
|
||||||
|
BEAST_EXPECT(v.to_ulong() == 0x01020304);
|
||||||
}
|
}
|
||||||
|
|
||||||
BEAST_EXPECT(to_string (AddressV4(0x01020304)) == "1.2.3.4");
|
BEAST_EXPECT(AddressV4(0x01020304).to_string() == "1.2.3.4");
|
||||||
|
|
||||||
shouldParseV4 ("1.2.3.4", 0x01020304);
|
shouldParseAddrV4 ("1.2.3.4", 0x01020304);
|
||||||
shouldParseV4 ("255.255.255.255", 0xffffffff);
|
shouldParseAddrV4 ("255.255.255.255", 0xffffffff);
|
||||||
shouldParseV4 ("0.0.0.0", 0);
|
shouldParseAddrV4 ("0.0.0.0", 0);
|
||||||
|
|
||||||
failParseV4 (".");
|
failParseAddr (".");
|
||||||
failParseV4 ("..");
|
failParseAddr ("..");
|
||||||
failParseV4 ("...");
|
failParseAddr ("...");
|
||||||
failParseV4 ("....");
|
failParseAddr ("....");
|
||||||
failParseV4 ("1");
|
#if BOOST_OS_WINDOWS
|
||||||
failParseV4 ("1.");
|
// WINDOWS bug in asio - I don't think these should parse
|
||||||
failParseV4 ("1.2");
|
// at all, and in-fact they do not on mac/linux
|
||||||
failParseV4 ("1.2.");
|
shouldParseAddrV4 ("1", 0x00000001, "0.0.0.1");
|
||||||
failParseV4 ("1.2.3");
|
shouldParseAddrV4 ("1.2", 0x01000002, "1.0.0.2");
|
||||||
failParseV4 ("1.2.3.");
|
shouldParseAddrV4 ("1.2.3", 0x01020003, "1.2.0.3");
|
||||||
failParseV4 ("256.0.0.0");
|
#else
|
||||||
failParseV4 ("-1.2.3.4");
|
failParseAddr ("1");
|
||||||
|
failParseAddr ("1.2");
|
||||||
|
failParseAddr ("1.2.3");
|
||||||
|
#endif
|
||||||
|
failParseAddr ("1.");
|
||||||
|
failParseAddr ("1.2.");
|
||||||
|
failParseAddr ("1.2.3.");
|
||||||
|
failParseAddr ("256.0.0.0");
|
||||||
|
failParseAddr ("-1.2.3.4");
|
||||||
}
|
}
|
||||||
|
|
||||||
void testAddressV4Proxy ()
|
void testAddressV4Proxy ()
|
||||||
{
|
{
|
||||||
testcase ("AddressV4::Proxy");
|
testcase ("AddressV4::Bytes");
|
||||||
|
|
||||||
AddressV4 v4 (10, 0, 0, 1);
|
AddressV4::bytes_type d1 = {{10,0,0,1}};
|
||||||
BEAST_EXPECT(v4[0]==10);
|
AddressV4 v4 {d1};
|
||||||
BEAST_EXPECT(v4[1]==0);
|
BEAST_EXPECT(v4.to_bytes()[0]==10);
|
||||||
BEAST_EXPECT(v4[2]==0);
|
BEAST_EXPECT(v4.to_bytes()[1]==0);
|
||||||
BEAST_EXPECT(v4[3]==1);
|
BEAST_EXPECT(v4.to_bytes()[2]==0);
|
||||||
|
BEAST_EXPECT(v4.to_bytes()[3]==1);
|
||||||
|
|
||||||
BEAST_EXPECT((~((0xff)<<16)) == 0xff00ffff);
|
BEAST_EXPECT((~((0xff)<<16)) == 0xff00ffff);
|
||||||
|
|
||||||
v4[1] = 10;
|
auto d2 = v4.to_bytes();
|
||||||
BEAST_EXPECT(v4[0]==10);
|
d2[1] = 10;
|
||||||
BEAST_EXPECT(v4[1]==10);
|
v4 = AddressV4{d2};
|
||||||
BEAST_EXPECT(v4[2]==0);
|
BEAST_EXPECT(v4.to_bytes()[0]==10);
|
||||||
BEAST_EXPECT(v4[3]==1);
|
BEAST_EXPECT(v4.to_bytes()[1]==10);
|
||||||
|
BEAST_EXPECT(v4.to_bytes()[2]==0);
|
||||||
|
BEAST_EXPECT(v4.to_bytes()[3]==1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
@@ -130,76 +152,160 @@ public:
|
|||||||
{
|
{
|
||||||
testcase ("Address");
|
testcase ("Address");
|
||||||
|
|
||||||
std::pair <Address, bool> result (
|
boost::system::error_code ec;
|
||||||
Address::from_string ("1.2.3.4"));
|
Address result {Address::from_string ("1.2.3.4", ec)};
|
||||||
BEAST_EXPECT(result.second);
|
AddressV4::bytes_type d = {{1,2,3,4}};
|
||||||
if (BEAST_EXPECT(result.first.is_v4 ()))
|
BEAST_EXPECT(! ec);
|
||||||
BEAST_EXPECT(result.first.to_v4() == AddressV4 (1, 2, 3, 4));
|
BEAST_EXPECT(
|
||||||
|
result.is_v4 () &&
|
||||||
|
result.to_v4() == AddressV4{d});
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void shouldParseEPV4 (
|
||||||
|
std::string const& s,
|
||||||
|
AddressV4::bytes_type const& value,
|
||||||
|
std::uint16_t p,
|
||||||
|
std::string const& normal = "")
|
||||||
|
{
|
||||||
|
auto result {Endpoint::from_string_checked (s)};
|
||||||
|
if (! BEAST_EXPECT(result.second))
|
||||||
|
return;
|
||||||
|
if (! BEAST_EXPECT(result.first.address().is_v4 ()))
|
||||||
|
return;
|
||||||
|
if (! BEAST_EXPECT(result.first.address().to_v4() == AddressV4 {value}))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BEAST_EXPECT(result.first.port() == p);
|
||||||
|
BEAST_EXPECT(to_string (result.first) == (normal.empty() ? s : normal));
|
||||||
|
}
|
||||||
|
|
||||||
|
void shouldParseEPV6 (
|
||||||
|
std::string const& s,
|
||||||
|
AddressV6::bytes_type const& value,
|
||||||
|
std::uint16_t p,
|
||||||
|
std::string const& normal = "")
|
||||||
|
{
|
||||||
|
auto result {Endpoint::from_string_checked (s)};
|
||||||
|
if (! BEAST_EXPECT(result.second))
|
||||||
|
return;
|
||||||
|
if (! BEAST_EXPECT(result.first.address().is_v6 ()))
|
||||||
|
return;
|
||||||
|
if (! BEAST_EXPECT(result.first.address().to_v6() == AddressV6 {value}))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BEAST_EXPECT(result.first.port() == p);
|
||||||
|
BEAST_EXPECT(to_string (result.first) == (normal.empty() ? s : normal));
|
||||||
|
}
|
||||||
|
|
||||||
|
void failParseEP (std::string s)
|
||||||
|
{
|
||||||
|
auto a1 = Endpoint::from_string(s);
|
||||||
|
BEAST_EXPECTS(is_unspecified (a1), s + " parses as " + a1.to_string());
|
||||||
|
|
||||||
|
auto a2 = Endpoint::from_string(s);
|
||||||
|
BEAST_EXPECTS(is_unspecified (a2), s + " parses as " + a2.to_string());
|
||||||
|
|
||||||
|
boost::replace_last(s, ":", " ");
|
||||||
|
auto a3 = Endpoint::from_string(s);
|
||||||
|
BEAST_EXPECTS(is_unspecified (a3), s + " parses as " + a3.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
void testEndpoint ()
|
void testEndpoint ()
|
||||||
{
|
{
|
||||||
testcase ("Endpoint");
|
testcase ("Endpoint");
|
||||||
|
|
||||||
{
|
shouldParseEPV4("1.2.3.4", {{1,2,3,4}}, 0);
|
||||||
std::pair <Endpoint, bool> result (
|
shouldParseEPV4("1.2.3.4:5", {{1,2,3,4}}, 5);
|
||||||
Endpoint::from_string_checked ("1.2.3.4"));
|
shouldParseEPV4("1.2.3.4 5", {{1,2,3,4}}, 5, "1.2.3.4:5");
|
||||||
BEAST_EXPECT(result.second);
|
shouldParseEPV6(
|
||||||
if (BEAST_EXPECT(result.first.address().is_v4 ()))
|
"2001:db8:a0b:12f0::1",
|
||||||
{
|
{{32, 01, 13, 184, 10, 11, 18, 240, 0, 0, 0, 0, 0, 0, 0, 1}},
|
||||||
BEAST_EXPECT(result.first.address().to_v4() ==
|
0);
|
||||||
AddressV4 (1, 2, 3, 4));
|
shouldParseEPV6(
|
||||||
BEAST_EXPECT(result.first.port() == 0);
|
"[2001:db8:a0b:12f0::1]:8",
|
||||||
BEAST_EXPECT(to_string (result.first) == "1.2.3.4");
|
{{32, 01, 13, 184, 10, 11, 18, 240, 0, 0, 0, 0, 0, 0, 0, 1}},
|
||||||
}
|
8);
|
||||||
}
|
shouldParseEPV6(
|
||||||
|
"[2001:2002:2003:2004:2005:2006:2007:2008]:65535",
|
||||||
{
|
{{32, 1, 32, 2, 32, 3, 32, 4, 32, 5, 32, 6, 32, 7, 32, 8}},
|
||||||
std::pair <Endpoint, bool> result (
|
65535);
|
||||||
Endpoint::from_string_checked ("1.2.3.4:5"));
|
shouldParseEPV6(
|
||||||
BEAST_EXPECT(result.second);
|
"2001:2002:2003:2004:2005:2006:2007:2008 65535",
|
||||||
if (BEAST_EXPECT(result.first.address().is_v4 ()))
|
{{32, 1, 32, 2, 32, 3, 32, 4, 32, 5, 32, 6, 32, 7, 32, 8}},
|
||||||
{
|
65535,
|
||||||
BEAST_EXPECT(result.first.address().to_v4() ==
|
"[2001:2002:2003:2004:2005:2006:2007:2008]:65535");
|
||||||
AddressV4 (1, 2, 3, 4));
|
|
||||||
BEAST_EXPECT(result.first.port() == 5);
|
|
||||||
BEAST_EXPECT(to_string (result.first) == "1.2.3.4:5");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Endpoint ep;
|
Endpoint ep;
|
||||||
|
|
||||||
ep = Endpoint (AddressV4 (127,0,0,1), 80);
|
AddressV4::bytes_type d = {{127,0,0,1}};
|
||||||
|
ep = Endpoint (AddressV4 {d}, 80);
|
||||||
BEAST_EXPECT(! is_unspecified (ep));
|
BEAST_EXPECT(! is_unspecified (ep));
|
||||||
BEAST_EXPECT(! is_public (ep));
|
BEAST_EXPECT(! is_public (ep));
|
||||||
BEAST_EXPECT( is_private (ep));
|
BEAST_EXPECT( is_private (ep));
|
||||||
BEAST_EXPECT(! is_multicast (ep));
|
BEAST_EXPECT(! is_multicast (ep));
|
||||||
BEAST_EXPECT( is_loopback (ep));
|
BEAST_EXPECT( is_loopback (ep));
|
||||||
BEAST_EXPECT(to_string (ep) == "127.0.0.1:80");
|
BEAST_EXPECT(to_string (ep) == "127.0.0.1:80");
|
||||||
|
// same address as v4 mapped in ipv6
|
||||||
|
ep = Endpoint (AddressV6::v4_mapped(AddressV4 {d}), 80);
|
||||||
|
BEAST_EXPECT(! is_unspecified (ep));
|
||||||
|
BEAST_EXPECT(! is_public (ep));
|
||||||
|
BEAST_EXPECT( is_private (ep));
|
||||||
|
BEAST_EXPECT(! is_multicast (ep));
|
||||||
|
BEAST_EXPECT(! is_loopback (ep)); //mapped loopback is not a loopback
|
||||||
|
BEAST_EXPECTS(to_string (ep) == "[::ffff:127.0.0.1]:80", to_string (ep));
|
||||||
|
|
||||||
ep = Endpoint (AddressV4 (10,0,0,1));
|
d = {{10,0,0,1}};
|
||||||
BEAST_EXPECT(AddressV4::get_class (ep.to_v4()) == 'A');
|
ep = Endpoint (AddressV4 {d});
|
||||||
|
BEAST_EXPECT(get_class (ep.to_v4()) == 'A');
|
||||||
BEAST_EXPECT(! is_unspecified (ep));
|
BEAST_EXPECT(! is_unspecified (ep));
|
||||||
BEAST_EXPECT(! is_public (ep));
|
BEAST_EXPECT(! is_public (ep));
|
||||||
BEAST_EXPECT( is_private (ep));
|
BEAST_EXPECT( is_private (ep));
|
||||||
BEAST_EXPECT(! is_multicast (ep));
|
BEAST_EXPECT(! is_multicast (ep));
|
||||||
BEAST_EXPECT(! is_loopback (ep));
|
BEAST_EXPECT(! is_loopback (ep));
|
||||||
BEAST_EXPECT(to_string (ep) == "10.0.0.1");
|
BEAST_EXPECT(to_string (ep) == "10.0.0.1");
|
||||||
|
// same address as v4 mapped in ipv6
|
||||||
|
ep = Endpoint (AddressV6::v4_mapped(AddressV4 {d}));
|
||||||
|
BEAST_EXPECT(get_class (ep.to_v6().to_v4()) == 'A');
|
||||||
|
BEAST_EXPECT(! is_unspecified (ep));
|
||||||
|
BEAST_EXPECT(! is_public (ep));
|
||||||
|
BEAST_EXPECT( is_private (ep));
|
||||||
|
BEAST_EXPECT(! is_multicast (ep));
|
||||||
|
BEAST_EXPECT(! is_loopback (ep));
|
||||||
|
BEAST_EXPECTS(to_string (ep) == "::ffff:10.0.0.1", to_string(ep));
|
||||||
|
|
||||||
ep = Endpoint (AddressV4 (166,78,151,147));
|
d = {{166,78,151,147}};
|
||||||
|
ep = Endpoint (AddressV4 {d});
|
||||||
BEAST_EXPECT(! is_unspecified (ep));
|
BEAST_EXPECT(! is_unspecified (ep));
|
||||||
BEAST_EXPECT( is_public (ep));
|
BEAST_EXPECT( is_public (ep));
|
||||||
BEAST_EXPECT(! is_private (ep));
|
BEAST_EXPECT(! is_private (ep));
|
||||||
BEAST_EXPECT(! is_multicast (ep));
|
BEAST_EXPECT(! is_multicast (ep));
|
||||||
BEAST_EXPECT(! is_loopback (ep));
|
BEAST_EXPECT(! is_loopback (ep));
|
||||||
BEAST_EXPECT(to_string (ep) == "166.78.151.147");
|
BEAST_EXPECT(to_string (ep) == "166.78.151.147");
|
||||||
|
// same address as v4 mapped in ipv6
|
||||||
|
ep = Endpoint (AddressV6::v4_mapped(AddressV4 {d}));
|
||||||
|
BEAST_EXPECT(! is_unspecified (ep));
|
||||||
|
BEAST_EXPECT( is_public (ep));
|
||||||
|
BEAST_EXPECT(! is_private (ep));
|
||||||
|
BEAST_EXPECT(! is_multicast (ep));
|
||||||
|
BEAST_EXPECT(! is_loopback (ep));
|
||||||
|
BEAST_EXPECTS(to_string (ep) == "::ffff:166.78.151.147", to_string(ep));
|
||||||
|
|
||||||
|
// a private IPv6
|
||||||
|
AddressV6::bytes_type d2 = {{253,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}};
|
||||||
|
ep = Endpoint (AddressV6 {d2});
|
||||||
|
BEAST_EXPECT(! is_unspecified (ep));
|
||||||
|
BEAST_EXPECT(! is_public (ep));
|
||||||
|
BEAST_EXPECT( is_private (ep));
|
||||||
|
BEAST_EXPECT(! is_multicast (ep));
|
||||||
|
BEAST_EXPECT(! is_loopback (ep));
|
||||||
|
BEAST_EXPECTS(to_string (ep) == "fd00::1", to_string(ep));
|
||||||
|
|
||||||
{
|
{
|
||||||
ep = Endpoint::from_string ("192.0.2.112");
|
ep = Endpoint::from_string ("192.0.2.112");
|
||||||
BEAST_EXPECT(! is_unspecified (ep));
|
BEAST_EXPECT(! is_unspecified (ep));
|
||||||
BEAST_EXPECT(ep == Endpoint::from_string_altform ("192.0.2.112"));
|
BEAST_EXPECT(ep == Endpoint::from_string ("192.0.2.112"));
|
||||||
|
|
||||||
auto const ep1 = Endpoint::from_string ("192.0.2.112:2016");
|
auto const ep1 = Endpoint::from_string ("192.0.2.112:2016");
|
||||||
BEAST_EXPECT(! is_unspecified (ep1));
|
BEAST_EXPECT(! is_unspecified (ep1));
|
||||||
@@ -207,21 +313,21 @@ public:
|
|||||||
BEAST_EXPECT(ep1.port() == 2016);
|
BEAST_EXPECT(ep1.port() == 2016);
|
||||||
|
|
||||||
auto const ep2 =
|
auto const ep2 =
|
||||||
Endpoint::from_string_altform ("192.0.2.112:2016");
|
Endpoint::from_string ("192.0.2.112:2016");
|
||||||
BEAST_EXPECT(! is_unspecified (ep2));
|
BEAST_EXPECT(! is_unspecified (ep2));
|
||||||
BEAST_EXPECT(ep.address() == ep2.address());
|
BEAST_EXPECT(ep.address() == ep2.address());
|
||||||
BEAST_EXPECT(ep2.port() == 2016);
|
BEAST_EXPECT(ep2.port() == 2016);
|
||||||
BEAST_EXPECT(ep1 == ep2);
|
BEAST_EXPECT(ep1 == ep2);
|
||||||
|
|
||||||
auto const ep3 =
|
auto const ep3 =
|
||||||
Endpoint::from_string_altform ("192.0.2.112 2016");
|
Endpoint::from_string ("192.0.2.112 2016");
|
||||||
BEAST_EXPECT(! is_unspecified (ep3));
|
BEAST_EXPECT(! is_unspecified (ep3));
|
||||||
BEAST_EXPECT(ep.address() == ep3.address());
|
BEAST_EXPECT(ep.address() == ep3.address());
|
||||||
BEAST_EXPECT(ep3.port() == 2016);
|
BEAST_EXPECT(ep3.port() == 2016);
|
||||||
BEAST_EXPECT(ep2 == ep3);
|
BEAST_EXPECT(ep2 == ep3);
|
||||||
|
|
||||||
auto const ep4 =
|
auto const ep4 =
|
||||||
Endpoint::from_string_altform ("192.0.2.112 2016");
|
Endpoint::from_string ("192.0.2.112 2016");
|
||||||
BEAST_EXPECT(! is_unspecified (ep4));
|
BEAST_EXPECT(! is_unspecified (ep4));
|
||||||
BEAST_EXPECT(ep.address() == ep4.address());
|
BEAST_EXPECT(ep.address() == ep4.address());
|
||||||
BEAST_EXPECT(ep4.port() == 2016);
|
BEAST_EXPECT(ep4.port() == 2016);
|
||||||
@@ -232,87 +338,79 @@ public:
|
|||||||
BEAST_EXPECT(to_string(ep1) == to_string(ep4));
|
BEAST_EXPECT(to_string(ep1) == to_string(ep4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ep = Endpoint::from_string("[::]:2017");
|
||||||
|
BEAST_EXPECT(is_unspecified (ep));
|
||||||
|
BEAST_EXPECT(ep.port() == 2017);
|
||||||
|
BEAST_EXPECT(ep.address() == AddressV6{});
|
||||||
|
}
|
||||||
|
|
||||||
// Failures:
|
// Failures:
|
||||||
BEAST_EXPECT(is_unspecified (
|
failParseEP ("192.0.2.112:port");
|
||||||
Endpoint::from_string ("192.0.2.112:port")));
|
failParseEP ("ip:port");
|
||||||
BEAST_EXPECT(is_unspecified (
|
failParseEP ("");
|
||||||
Endpoint::from_string_altform ("192.0.2.112:port")));
|
failParseEP ("1.2.3.256");
|
||||||
BEAST_EXPECT(is_unspecified (
|
|
||||||
Endpoint::from_string_altform ("192.0.2.112 port")));
|
|
||||||
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
#if BOOST_OS_WINDOWS
|
||||||
Endpoint::from_string ("ip:port")));
|
// windows asio bugs...false positives
|
||||||
BEAST_EXPECT(is_unspecified (
|
shouldParseEPV4 ("255", {{0,0,0,255}}, 0, "0.0.0.255");
|
||||||
Endpoint::from_string_altform ("ip:port")));
|
shouldParseEPV4 ("512", {{0,0,2,0}}, 0, "0.0.2.0");
|
||||||
BEAST_EXPECT(is_unspecified (
|
shouldParseEPV4 ("1.2.3:80", {{1,2,0,3}}, 80, "1.2.0.3:80");
|
||||||
Endpoint::from_string_altform ("ip port")));
|
#else
|
||||||
|
failParseEP ("255");
|
||||||
|
failParseEP ("512");
|
||||||
|
failParseEP ("1.2.3:80");
|
||||||
|
#endif
|
||||||
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
failParseEP ("1.2.3.4:65536");
|
||||||
Endpoint::from_string("")));
|
failParseEP ("1.2.3.4:89119");
|
||||||
BEAST_EXPECT(is_unspecified (
|
failParseEP ("1.2.3:89119");
|
||||||
Endpoint::from_string_altform("")));
|
failParseEP ("[::1]:89119");
|
||||||
|
failParseEP ("[::az]:1");
|
||||||
|
failParseEP ("[1234:5678:90ab:cdef:1234:5678:90ab:cdef:1111]:1");
|
||||||
|
failParseEP ("[1234:5678:90ab:cdef:1234:5678:90ab:cdef:1111]:12345");
|
||||||
|
failParseEP ("abcdef:12345");
|
||||||
|
failParseEP ("[abcdef]:12345");
|
||||||
|
failParseEP ("foo.org 12345");
|
||||||
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
// test with hashed container
|
||||||
Endpoint::from_string("255")));
|
std::unordered_set<Endpoint> eps;
|
||||||
BEAST_EXPECT(is_unspecified (
|
constexpr auto items {100};
|
||||||
Endpoint::from_string_altform("255")));
|
float max_lf {0};
|
||||||
|
for (auto i = 0; i < items; ++i)
|
||||||
BEAST_EXPECT(is_unspecified (
|
{
|
||||||
Endpoint::from_string("512")));
|
eps.insert(randomEP(ripple::rand_int(0,1) == 1));
|
||||||
BEAST_EXPECT(is_unspecified (
|
max_lf = std::max(max_lf, eps.load_factor());
|
||||||
Endpoint::from_string_altform("512")));
|
}
|
||||||
|
BEAST_EXPECT(eps.bucket_count() >= items);
|
||||||
BEAST_EXPECT(is_unspecified (
|
BEAST_EXPECT(max_lf > 0.90);
|
||||||
Endpoint::from_string("1.2.3.256")));
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
|
||||||
Endpoint::from_string_altform("1.2.3.256")));
|
|
||||||
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
|
||||||
Endpoint::from_string("1.2.3:80")));
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
|
||||||
Endpoint::from_string_altform("1.2.3:80")));
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
|
||||||
Endpoint::from_string_altform("1.2.3 80")));
|
|
||||||
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
|
||||||
Endpoint::from_string("1.2.3.4:65536")));
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
|
||||||
Endpoint::from_string_altform("1.2.3:65536")));
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
|
||||||
Endpoint::from_string_altform("1.2.3 65536")));
|
|
||||||
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
|
||||||
Endpoint::from_string("1.2.3.4:89119")));
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
|
||||||
Endpoint::from_string_altform("1.2.3:89119")));
|
|
||||||
BEAST_EXPECT(is_unspecified (
|
|
||||||
Endpoint::from_string_altform("1.2.3 89119")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool parse (char const* text, T& t)
|
bool parse (std::string const& text, T& t)
|
||||||
{
|
{
|
||||||
std::string input (text);
|
std::istringstream stream {text};
|
||||||
std::istringstream stream (input);
|
|
||||||
stream >> t;
|
stream >> t;
|
||||||
return !stream.fail();
|
return !stream.fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void shouldPass (char const* text)
|
void shouldPass (std::string const& text, std::string const& normal="")
|
||||||
{
|
{
|
||||||
|
using namespace std::literals;
|
||||||
T t;
|
T t;
|
||||||
BEAST_EXPECT(parse (text, t));
|
BEAST_EXPECT(parse (text, t));
|
||||||
BEAST_EXPECT(to_string (t) == std::string (text));
|
BEAST_EXPECTS(to_string (t) == (normal.empty() ? text : normal),
|
||||||
|
"string mismatch for "s + text);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void shouldFail (char const* text)
|
void shouldFail (std::string const& text)
|
||||||
{
|
{
|
||||||
T t;
|
T t;
|
||||||
unexpected (parse (text, t));
|
unexpected (parse (text, t), text + " should not parse");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -325,14 +423,30 @@ public:
|
|||||||
shouldPass <T> ("168.127.149.132");
|
shouldPass <T> ("168.127.149.132");
|
||||||
shouldPass <T> ("168.127.149.132:80");
|
shouldPass <T> ("168.127.149.132:80");
|
||||||
shouldPass <T> ("168.127.149.132:54321");
|
shouldPass <T> ("168.127.149.132:54321");
|
||||||
|
shouldPass <T> ("2001:db8:a0b:12f0::1");
|
||||||
|
shouldPass <T> ("[2001:db8:a0b:12f0::1]:8");
|
||||||
|
shouldPass <T> ("2001:db8:a0b:12f0::1 8", "[2001:db8:a0b:12f0::1]:8");
|
||||||
|
shouldPass <T> ("[::1]:8");
|
||||||
|
shouldPass <T> ("[2001:2002:2003:2004:2005:2006:2007:2008]:65535");
|
||||||
|
|
||||||
shouldFail <T> ("");
|
|
||||||
shouldFail <T> ("255");
|
|
||||||
shouldFail <T> ("512");
|
|
||||||
shouldFail <T> ("1.2.3.256");
|
shouldFail <T> ("1.2.3.256");
|
||||||
|
shouldFail <T> ("");
|
||||||
|
#if BOOST_OS_WINDOWS
|
||||||
|
// windows asio bugs...false positives
|
||||||
|
shouldPass <T> ("512", "0.0.2.0");
|
||||||
|
shouldPass <T> ("255", "0.0.0.255");
|
||||||
|
shouldPass <T> ("1.2.3:80", "1.2.0.3:80");
|
||||||
|
#else
|
||||||
|
shouldFail <T> ("512");
|
||||||
|
shouldFail <T> ("255");
|
||||||
shouldFail <T> ("1.2.3:80");
|
shouldFail <T> ("1.2.3:80");
|
||||||
|
#endif
|
||||||
shouldFail <T> ("1.2.3:65536");
|
shouldFail <T> ("1.2.3:65536");
|
||||||
shouldFail <T> ("1.2.3:72131");
|
shouldFail <T> ("1.2.3:72131");
|
||||||
|
shouldFail <T> ("[::1]:89119");
|
||||||
|
shouldFail <T> ("[::az]:1");
|
||||||
|
shouldFail <T> ("[1234:5678:90ab:cdef:1234:5678:90ab:cdef:1111]:1");
|
||||||
|
shouldFail <T> ("[1234:5678:90ab:cdef:1234:5678:90ab:cdef:1111]:12345");
|
||||||
}
|
}
|
||||||
|
|
||||||
void run () override
|
void run () override
|
||||||
@@ -341,7 +455,6 @@ public:
|
|||||||
testAddressV4Proxy();
|
testAddressV4Proxy();
|
||||||
testAddress ();
|
testAddress ();
|
||||||
testEndpoint ();
|
testEndpoint ();
|
||||||
|
|
||||||
testParse <Endpoint> ("Parse Endpoint");
|
testParse <Endpoint> ("Parse Endpoint");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <ripple/protocol/SecretKey.h>
|
#include <ripple/protocol/SecretKey.h>
|
||||||
#include <ripple/protocol/Sign.h>
|
#include <ripple/protocol/Sign.h>
|
||||||
#include <ripple/basics/strHex.h>
|
#include <ripple/basics/strHex.h>
|
||||||
|
#include <test/jtx/envconfig.h>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/beast/core/detail/base64.hpp>
|
#include <boost/beast/core/detail/base64.hpp>
|
||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
@@ -55,7 +56,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
TrustedPublisherServer(
|
TrustedPublisherServer(
|
||||||
endpoint_type const& ep,
|
|
||||||
boost::asio::io_service& ios,
|
boost::asio::io_service& ios,
|
||||||
std::pair<PublicKey, SecretKey> keys,
|
std::pair<PublicKey, SecretKey> keys,
|
||||||
std::string const& manifest,
|
std::string const& manifest,
|
||||||
@@ -65,6 +65,9 @@ public:
|
|||||||
std::vector<Validator> const& validators)
|
std::vector<Validator> const& validators)
|
||||||
: sock_(ios), acceptor_(ios)
|
: sock_(ios), acceptor_(ios)
|
||||||
{
|
{
|
||||||
|
endpoint_type const& ep {
|
||||||
|
beast::IP::Address::from_string (ripple::test::getEnvLocalhostAddr()),
|
||||||
|
0}; // 0 means let OS pick the port based on what's available
|
||||||
std::string data = "{\"sequence\":" + std::to_string(sequence) +
|
std::string data = "{\"sequence\":" + std::to_string(sequence) +
|
||||||
",\"expiration\":" +
|
",\"expiration\":" +
|
||||||
std::to_string(expiration.time_since_epoch().count()) +
|
std::to_string(expiration.time_since_epoch().count()) +
|
||||||
|
|||||||
@@ -25,6 +25,15 @@
|
|||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
|
extern std::atomic<bool> envUseIPv4;
|
||||||
|
|
||||||
|
inline
|
||||||
|
const char *
|
||||||
|
getEnvLocalhostAddr()
|
||||||
|
{
|
||||||
|
return envUseIPv4 ? "127.0.0.1" : "::1";
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief initializes a config object for use with jtx::Env
|
/// @brief initializes a config object for use with jtx::Env
|
||||||
///
|
///
|
||||||
/// @param config the configuration object to be initialized
|
/// @param config the configuration object to be initialized
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ class JSONRPCClient : public AbstractClient
|
|||||||
parse_Port(pp, cfg[name], log);
|
parse_Port(pp, cfg[name], log);
|
||||||
if(pp.protocol.count("http") == 0)
|
if(pp.protocol.count("http") == 0)
|
||||||
continue;
|
continue;
|
||||||
using boost::asio::ip::address_v4;
|
using namespace boost::asio::ip;
|
||||||
if(*pp.ip == address_v4{0x00000000})
|
if(pp.ip && pp.ip->is_unspecified())
|
||||||
*pp.ip = address_v4{0x7f000001};
|
*pp.ip = pp.ip->is_v6() ? address{address_v6::loopback()} : address{address_v4::loopback()};
|
||||||
return { *pp.ip, *pp.port };
|
return { *pp.ip, *pp.port };
|
||||||
}
|
}
|
||||||
Throw<std::runtime_error>("Missing HTTP port");
|
Throw<std::runtime_error>("Missing HTTP port");
|
||||||
@@ -83,7 +83,7 @@ public:
|
|||||||
: ep_(getEndpoint(cfg))
|
: ep_(getEndpoint(cfg))
|
||||||
, stream_(ios_)
|
, stream_(ios_)
|
||||||
, rpc_version_(rpc_version)
|
, rpc_version_(rpc_version)
|
||||||
{
|
{
|
||||||
stream_.connect(ep_);
|
stream_.connect(ep_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,9 +64,9 @@ class WSClientImpl : public WSClient
|
|||||||
parse_Port(pp, cfg[name], log);
|
parse_Port(pp, cfg[name], log);
|
||||||
if(pp.protocol.count(ps) == 0)
|
if(pp.protocol.count(ps) == 0)
|
||||||
continue;
|
continue;
|
||||||
using boost::asio::ip::address_v4;
|
using namespace boost::asio::ip;
|
||||||
if(*pp.ip == address_v4{0x00000000})
|
if(pp.ip && pp.ip->is_unspecified())
|
||||||
*pp.ip = address_v4{0x7f000001};
|
*pp.ip = pp.ip->is_v6() ? address{address_v6::loopback()} : address{address_v4::loopback()};
|
||||||
return { *pp.ip, *pp.port };
|
return { *pp.ip, *pp.port };
|
||||||
}
|
}
|
||||||
Throw<std::runtime_error>("Missing WebSocket port");
|
Throw<std::runtime_error>("Missing WebSocket port");
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ void incPorts()
|
|||||||
port_base += 3;
|
port_base += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::atomic<bool> envUseIPv4 {false};
|
||||||
|
|
||||||
void
|
void
|
||||||
setupConfigForUnitTests (Config& cfg)
|
setupConfigForUnitTests (Config& cfg)
|
||||||
{
|
{
|
||||||
@@ -43,19 +45,21 @@ setupConfigForUnitTests (Config& cfg)
|
|||||||
cfg.legacy("database_path", "");
|
cfg.legacy("database_path", "");
|
||||||
cfg.setupControl(true, true, true);
|
cfg.setupControl(true, true, true);
|
||||||
cfg["server"].append("port_peer");
|
cfg["server"].append("port_peer");
|
||||||
cfg["port_peer"].set("ip", "127.0.0.1");
|
cfg["port_peer"].set("ip", getEnvLocalhostAddr());
|
||||||
cfg["port_peer"].set("port", port_peer);
|
cfg["port_peer"].set("port", port_peer);
|
||||||
cfg["port_peer"].set("protocol", "peer");
|
cfg["port_peer"].set("protocol", "peer");
|
||||||
|
|
||||||
cfg["server"].append("port_rpc");
|
cfg["server"].append("port_rpc");
|
||||||
cfg["port_rpc"].set("ip", "127.0.0.1");
|
cfg["port_rpc"].set("ip", getEnvLocalhostAddr());
|
||||||
|
cfg["port_rpc"].set("admin", getEnvLocalhostAddr());
|
||||||
cfg["port_rpc"].set("port", port_rpc);
|
cfg["port_rpc"].set("port", port_rpc);
|
||||||
cfg["port_rpc"].set("protocol", "http,ws2");
|
cfg["port_rpc"].set("protocol", "http,ws2");
|
||||||
cfg["port_rpc"].set("admin", "127.0.0.1");
|
|
||||||
cfg["server"].append("port_ws");
|
cfg["server"].append("port_ws");
|
||||||
cfg["port_ws"].set("ip", "127.0.0.1");
|
cfg["port_ws"].set("ip", getEnvLocalhostAddr());
|
||||||
|
cfg["port_ws"].set("admin", getEnvLocalhostAddr());
|
||||||
cfg["port_ws"].set("port", port_ws);
|
cfg["port_ws"].set("port", port_ws);
|
||||||
cfg["port_ws"].set("protocol", "ws");
|
cfg["port_ws"].set("protocol", "ws");
|
||||||
cfg["port_ws"].set("admin", "127.0.0.1");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace jtx {
|
namespace jtx {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <ripple/basics/make_SSLContext.h>
|
#include <ripple/basics/make_SSLContext.h>
|
||||||
#include <ripple/beast/core/CurrentThreadName.h>
|
#include <ripple/beast/core/CurrentThreadName.h>
|
||||||
#include <ripple/beast/unit_test.h>
|
#include <ripple/beast/unit_test.h>
|
||||||
|
#include <test/jtx/envconfig.h>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/asio/ssl.hpp>
|
#include <boost/asio/ssl.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
@@ -183,7 +184,8 @@ private:
|
|||||||
, server_(server)
|
, server_(server)
|
||||||
, test_(server_.test_)
|
, test_(server_.test_)
|
||||||
, acceptor_(test_.io_service_,
|
, acceptor_(test_.io_service_,
|
||||||
endpoint_type(address_type::from_string("127.0.0.1"), 0))
|
endpoint_type(beast::IP::Address::from_string(
|
||||||
|
test::getEnvLocalhostAddr()), 0))
|
||||||
, socket_(test_.io_service_)
|
, socket_(test_.io_service_)
|
||||||
, strand_(socket_.get_io_service())
|
, strand_(socket_.get_io_service())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,10 +21,18 @@
|
|||||||
#include <ripple/peerfinder/impl/Livecache.h>
|
#include <ripple/peerfinder/impl/Livecache.h>
|
||||||
#include <ripple/beast/unit_test.h>
|
#include <ripple/beast/unit_test.h>
|
||||||
#include <ripple/beast/clock/manual_clock.h>
|
#include <ripple/beast/clock/manual_clock.h>
|
||||||
|
#include <test/beast/IPEndpointCommon.h>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace PeerFinder {
|
namespace PeerFinder {
|
||||||
|
|
||||||
|
bool operator== (Endpoint const& a, Endpoint const& b)
|
||||||
|
{
|
||||||
|
return (a.hops == b.hops &&
|
||||||
|
a.address == b.address);
|
||||||
|
}
|
||||||
|
|
||||||
class Livecache_test : public beast::unit_test::suite
|
class Livecache_test : public beast::unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -32,38 +40,178 @@ public:
|
|||||||
|
|
||||||
// Add the address as an endpoint
|
// Add the address as an endpoint
|
||||||
template <class C>
|
template <class C>
|
||||||
void add (std::uint32_t index, std::uint16_t port, C& c)
|
inline void add (beast::IP::Endpoint ep, C& c, int hops = 0)
|
||||||
{
|
{
|
||||||
Endpoint ep;
|
Endpoint cep {ep, hops};
|
||||||
ep.hops = 0;
|
c.insert (cep);
|
||||||
ep.address = beast::IP::Endpoint (
|
|
||||||
beast::IP::AddressV4 (index), port);
|
|
||||||
c.insert (ep);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void testFetch ()
|
void testBasicInsert ()
|
||||||
{
|
{
|
||||||
|
testcase ("Basic Insert");
|
||||||
|
Livecache <> c (m_clock, beast::Journal());
|
||||||
|
BEAST_EXPECT(c.empty());
|
||||||
|
|
||||||
|
for (auto i = 0; i < 10; ++i)
|
||||||
|
add(beast::IP::randomEP(true), c);
|
||||||
|
|
||||||
|
BEAST_EXPECT(! c.empty());
|
||||||
|
BEAST_EXPECT(c.size() == 10);
|
||||||
|
|
||||||
|
for (auto i = 0; i < 10; ++i)
|
||||||
|
add(beast::IP::randomEP(false), c);
|
||||||
|
|
||||||
|
BEAST_EXPECT(! c.empty());
|
||||||
|
BEAST_EXPECT(c.size() == 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testInsertUpdate ()
|
||||||
|
{
|
||||||
|
testcase ("Insert/Update");
|
||||||
Livecache <> c (m_clock, beast::Journal());
|
Livecache <> c (m_clock, beast::Journal());
|
||||||
|
|
||||||
add (1, 1, c);
|
auto ep1 = Endpoint {beast::IP::randomEP(), 2};
|
||||||
add (2, 1, c);
|
c.insert(ep1);
|
||||||
add (3, 1, c);
|
BEAST_EXPECT(c.size() == 1);
|
||||||
add (4, 1, c);
|
// third position list will contain the entry
|
||||||
add (4, 2, c);
|
BEAST_EXPECT((c.hops.begin()+2)->begin()->hops == 2);
|
||||||
add (4, 3, c);
|
|
||||||
add (5, 1, c);
|
|
||||||
add (6, 1, c);
|
|
||||||
add (6, 2, c);
|
|
||||||
add (7, 1, c);
|
|
||||||
|
|
||||||
// VFALCO TODO!
|
auto ep2 = Endpoint {ep1.address, 4};
|
||||||
|
// this will not change the entry has higher hops
|
||||||
|
c.insert(ep2);
|
||||||
|
BEAST_EXPECT(c.size() == 1);
|
||||||
|
// still in third position list
|
||||||
|
BEAST_EXPECT((c.hops.begin()+2)->begin()->hops == 2);
|
||||||
|
|
||||||
pass();
|
auto ep3 = Endpoint {ep1.address, 2};
|
||||||
|
// this will not change the entry has the same hops as existing
|
||||||
|
c.insert(ep3);
|
||||||
|
BEAST_EXPECT(c.size() == 1);
|
||||||
|
// still in third position list
|
||||||
|
BEAST_EXPECT((c.hops.begin()+2)->begin()->hops == 2);
|
||||||
|
|
||||||
|
auto ep4 = Endpoint {ep1.address, 1};
|
||||||
|
c.insert(ep4);
|
||||||
|
BEAST_EXPECT(c.size() == 1);
|
||||||
|
// now at second position list
|
||||||
|
BEAST_EXPECT((c.hops.begin()+1)->begin()->hops == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testExpire ()
|
||||||
|
{
|
||||||
|
testcase ("Expire");
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
Livecache <> c (m_clock, beast::Journal());
|
||||||
|
|
||||||
|
auto ep1 = Endpoint {beast::IP::randomEP(), 1};
|
||||||
|
c.insert(ep1);
|
||||||
|
BEAST_EXPECT(c.size() == 1);
|
||||||
|
c.expire();
|
||||||
|
BEAST_EXPECT(c.size() == 1);
|
||||||
|
// verify that advancing to 1 sec before expiration
|
||||||
|
// leaves our entry intact
|
||||||
|
m_clock.advance(Tuning::liveCacheSecondsToLive - 1s);
|
||||||
|
c.expire();
|
||||||
|
BEAST_EXPECT(c.size() == 1);
|
||||||
|
// now advance to the point of expiration
|
||||||
|
m_clock.advance(1s);
|
||||||
|
c.expire();
|
||||||
|
BEAST_EXPECT(c.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void testHistogram ()
|
||||||
|
{
|
||||||
|
testcase ("Histogram");
|
||||||
|
constexpr auto num_eps = 40;
|
||||||
|
Livecache <> c (m_clock, beast::Journal());
|
||||||
|
for (auto i = 0; i < num_eps; ++i)
|
||||||
|
add(
|
||||||
|
beast::IP::randomEP(true),
|
||||||
|
c,
|
||||||
|
ripple::rand_int(0, static_cast<int>(Tuning::maxHops + 1)));
|
||||||
|
auto h = c.hops.histogram();
|
||||||
|
if(! BEAST_EXPECT(! h.empty()))
|
||||||
|
return;
|
||||||
|
std::vector <std::string> v;
|
||||||
|
boost::split (v, h, boost::algorithm::is_any_of (","));
|
||||||
|
auto sum = 0;
|
||||||
|
for (auto const& n : v)
|
||||||
|
{
|
||||||
|
auto val = boost::lexical_cast<int>(boost::trim_copy(n));
|
||||||
|
sum += val;
|
||||||
|
BEAST_EXPECT(val >= 0);
|
||||||
|
}
|
||||||
|
BEAST_EXPECT(sum == num_eps);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testShuffle ()
|
||||||
|
{
|
||||||
|
testcase ("Shuffle");
|
||||||
|
Livecache <> c (m_clock, beast::Journal());
|
||||||
|
for (auto i = 0; i < 100; ++i)
|
||||||
|
add(
|
||||||
|
beast::IP::randomEP(true),
|
||||||
|
c,
|
||||||
|
ripple::rand_int(0, static_cast<int>(Tuning::maxHops + 1)));
|
||||||
|
|
||||||
|
using at_hop = std::vector <ripple::PeerFinder::Endpoint>;
|
||||||
|
using all_hops = std::array <at_hop, 1 + Tuning::maxHops + 1>;
|
||||||
|
|
||||||
|
auto cmp_EP = [](Endpoint const& a, Endpoint const& b) {
|
||||||
|
return (b.hops < a.hops || (b.hops == a.hops && b.address < a.address));
|
||||||
|
};
|
||||||
|
all_hops before;
|
||||||
|
all_hops before_sorted;
|
||||||
|
for (auto i = std::make_pair(0, c.hops.begin());
|
||||||
|
i.second != c.hops.end(); ++i.first, ++i.second)
|
||||||
|
{
|
||||||
|
std::copy ((*i.second).begin(), (*i.second).end(),
|
||||||
|
std::back_inserter (before[i.first]));
|
||||||
|
std::copy ((*i.second).begin(), (*i.second).end(),
|
||||||
|
std::back_inserter (before_sorted[i.first]));
|
||||||
|
std::sort(
|
||||||
|
before_sorted[i.first].begin(),
|
||||||
|
before_sorted[i.first].end(),
|
||||||
|
cmp_EP);
|
||||||
|
}
|
||||||
|
|
||||||
|
c.hops.shuffle();
|
||||||
|
|
||||||
|
all_hops after;
|
||||||
|
all_hops after_sorted;
|
||||||
|
for (auto i = std::make_pair(0, c.hops.begin());
|
||||||
|
i.second != c.hops.end(); ++i.first, ++i.second)
|
||||||
|
{
|
||||||
|
std::copy ((*i.second).begin(), (*i.second).end(),
|
||||||
|
std::back_inserter (after[i.first]));
|
||||||
|
std::copy ((*i.second).begin(), (*i.second).end(),
|
||||||
|
std::back_inserter (after_sorted[i.first]));
|
||||||
|
std::sort(
|
||||||
|
after_sorted[i.first].begin(),
|
||||||
|
after_sorted[i.first].end(),
|
||||||
|
cmp_EP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// each hop bucket should contain the same items
|
||||||
|
// before and after sort, albeit in different order
|
||||||
|
bool all_match = true;
|
||||||
|
for (auto i = 0; i < before.size(); ++i)
|
||||||
|
{
|
||||||
|
BEAST_EXPECT(before[i].size() == after[i].size());
|
||||||
|
all_match = all_match && (before[i] == after[i]);
|
||||||
|
BEAST_EXPECT(before_sorted[i] == after_sorted[i]);
|
||||||
|
}
|
||||||
|
BEAST_EXPECT(! all_match);
|
||||||
}
|
}
|
||||||
|
|
||||||
void run () override
|
void run () override
|
||||||
{
|
{
|
||||||
testFetch ();
|
testBasicInsert ();
|
||||||
|
testInsertUpdate ();
|
||||||
|
testExpire ();
|
||||||
|
testHistogram ();
|
||||||
|
testShuffle ();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -63,15 +63,16 @@ public:
|
|||||||
|
|
||||||
void createGossip (Gossip& gossip)
|
void createGossip (Gossip& gossip)
|
||||||
{
|
{
|
||||||
int const v (10 + rand_int(9));
|
std::uint8_t const v (10 + rand_int(9));
|
||||||
int const n (10 + rand_int(9));
|
std::uint8_t const n (10 + rand_int(9));
|
||||||
gossip.items.reserve (n);
|
gossip.items.reserve (n);
|
||||||
for (int i = 0; i < n; ++i)
|
for (std::uint8_t i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
Gossip::Item item;
|
Gossip::Item item;
|
||||||
item.balance = 100 + rand_int(499);
|
item.balance = 100 + rand_int(499);
|
||||||
item.address = beast::IP::Endpoint (
|
beast::IP::AddressV4::bytes_type d =
|
||||||
beast::IP::AddressV4 (192, 0, 2, v + i));
|
{{192,0,2,static_cast<std::uint8_t>(v + i)}};
|
||||||
|
item.address = beast::IP::Endpoint { beast::IP::AddressV4 {d} };
|
||||||
gossip.items.push_back (item);
|
gossip.items.push_back (item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,8 +194,8 @@ public:
|
|||||||
Gossip g;
|
Gossip g;
|
||||||
Gossip::Item item;
|
Gossip::Item item;
|
||||||
item.balance = 100;
|
item.balance = 100;
|
||||||
item.address = beast::IP::Endpoint (
|
beast::IP::AddressV4::bytes_type d = {{192, 0, 2, 1}};
|
||||||
beast::IP::AddressV4 (192, 0, 2, 1));
|
item.address = beast::IP::Endpoint { beast::IP::AddressV4 {d} };
|
||||||
g.items.push_back (item);
|
g.items.push_back (item);
|
||||||
|
|
||||||
logic.importConsumers ("g", g);
|
logic.importConsumers ("g", g);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <ripple/protocol/Feature.h>
|
#include <ripple/protocol/Feature.h>
|
||||||
#include <ripple/protocol/JsonFields.h>
|
#include <ripple/protocol/JsonFields.h>
|
||||||
#include <test/jtx.h>
|
#include <test/jtx.h>
|
||||||
|
#include <test/jtx/envconfig.h>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <ripple/beast/utility/temp_dir.h>
|
#include <ripple/beast/utility/temp_dir.h>
|
||||||
#include <ripple/resource/ResourceManager.h>
|
#include <ripple/resource/ResourceManager.h>
|
||||||
@@ -265,7 +266,7 @@ class NoRippleCheckLimits_test : public beast::unit_test::suite
|
|||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
using namespace beast::IP;
|
using namespace beast::IP;
|
||||||
auto c = env.app().getResourceManager()
|
auto c = env.app().getResourceManager()
|
||||||
.newInboundEndpoint (Endpoint::from_string ("127.0.0.1"));
|
.newInboundEndpoint (Endpoint::from_string (test::getEnvLocalhostAddr()));
|
||||||
if (dropThreshold - c.balance() <= 20)
|
if (dropThreshold - c.balance() <= 20)
|
||||||
{
|
{
|
||||||
using clock_type = beast::abstract_clock <steady_clock>;
|
using clock_type = beast::abstract_clock <steady_clock>;
|
||||||
|
|||||||
@@ -178,8 +178,6 @@ public:
|
|||||||
testDynamicUNL()
|
testDynamicUNL()
|
||||||
{
|
{
|
||||||
using namespace test::jtx;
|
using namespace test::jtx;
|
||||||
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
|
||||||
using address_type = boost::asio::ip::address;
|
|
||||||
|
|
||||||
auto toStr = [](PublicKey const& publicKey) {
|
auto toStr = [](PublicKey const& publicKey) {
|
||||||
return toBase58(TokenType::NodePublic, publicKey);
|
return toBase58(TokenType::NodePublic, publicKey);
|
||||||
@@ -208,7 +206,9 @@ public:
|
|||||||
// Publisher list site unavailable
|
// Publisher list site unavailable
|
||||||
{
|
{
|
||||||
// Publisher site information
|
// Publisher site information
|
||||||
std::string siteURI = "http://127.0.0.1:1234/validators";
|
using namespace std::string_literals;
|
||||||
|
std::string siteURI =
|
||||||
|
"http://"s + getEnvLocalhostAddr() + ":1234/validators";
|
||||||
|
|
||||||
Env env{
|
Env env{
|
||||||
*this,
|
*this,
|
||||||
@@ -271,9 +271,6 @@ public:
|
|||||||
{
|
{
|
||||||
NetClock::time_point const expiration{3600s};
|
NetClock::time_point const expiration{3600s};
|
||||||
|
|
||||||
// 0 port means to use OS port selection
|
|
||||||
endpoint_type ep{address_type::from_string("127.0.0.1"), 0};
|
|
||||||
|
|
||||||
// Manage single thread io_service for server
|
// Manage single thread io_service for server
|
||||||
struct Worker : BasicApp
|
struct Worker : BasicApp
|
||||||
{
|
{
|
||||||
@@ -282,7 +279,6 @@ public:
|
|||||||
Worker w;
|
Worker w;
|
||||||
|
|
||||||
TrustedPublisherServer server(
|
TrustedPublisherServer server(
|
||||||
ep,
|
|
||||||
w.get_io_service(),
|
w.get_io_service(),
|
||||||
publisherSigningKeys,
|
publisherSigningKeys,
|
||||||
manifest,
|
manifest,
|
||||||
@@ -291,9 +287,9 @@ public:
|
|||||||
1,
|
1,
|
||||||
validators);
|
validators);
|
||||||
|
|
||||||
endpoint_type const & local_ep = server.local_endpoint();
|
std::stringstream uri;
|
||||||
std::string siteURI = "http://127.0.0.1:" +
|
uri << "http://" << server.local_endpoint() << "/validators";
|
||||||
std::to_string(local_ep.port()) + "/validators";
|
auto siteURI = uri.str();
|
||||||
|
|
||||||
Env env{
|
Env env{
|
||||||
*this,
|
*this,
|
||||||
|
|||||||
@@ -73,10 +73,10 @@ class ServerStatus_test :
|
|||||||
// which requires an http endpoint to talk to. In the connection
|
// which requires an http endpoint to talk to. In the connection
|
||||||
// failure test, this endpoint should never be used
|
// failure test, this endpoint should never be used
|
||||||
(*p)["server"].append("port_alt");
|
(*p)["server"].append("port_alt");
|
||||||
(*p)["port_alt"].set("ip", "127.0.0.1");
|
(*p)["port_alt"].set("ip", getEnvLocalhostAddr());
|
||||||
(*p)["port_alt"].set("port", "8099");
|
(*p)["port_alt"].set("port", "8099");
|
||||||
(*p)["port_alt"].set("protocol", "http");
|
(*p)["port_alt"].set("protocol", "http");
|
||||||
(*p)["port_alt"].set("admin", "127.0.0.1");
|
(*p)["port_alt"].set("admin", getEnvLocalhostAddr());
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ public:
|
|||||||
thread.get_io_service(), journal);
|
thread.get_io_service(), journal);
|
||||||
std::vector<Port> serverPort(1);
|
std::vector<Port> serverPort(1);
|
||||||
serverPort.back().ip =
|
serverPort.back().ip =
|
||||||
boost::asio::ip::address::from_string ("127.0.0.1"),
|
beast::IP::Address::from_string (getEnvLocalhostAddr()),
|
||||||
serverPort.back().port = 0;
|
serverPort.back().port = 0;
|
||||||
serverPort.back().protocol.insert("http");
|
serverPort.back().protocol.insert("http");
|
||||||
auto eps = s->ports (serverPort);
|
auto eps = s->ports (serverPort);
|
||||||
@@ -355,7 +355,7 @@ public:
|
|||||||
thread.get_io_service(), {});
|
thread.get_io_service(), {});
|
||||||
std::vector<Port> serverPort(1);
|
std::vector<Port> serverPort(1);
|
||||||
serverPort.back().ip =
|
serverPort.back().ip =
|
||||||
boost::asio::ip::address::from_string ("127.0.0.1"),
|
beast::IP::Address::from_string (getEnvLocalhostAddr()),
|
||||||
serverPort.back().port = 0;
|
serverPort.back().port = 0;
|
||||||
serverPort.back().protocol.insert("http");
|
serverPort.back().protocol.insert("http");
|
||||||
s->ports (serverPort);
|
s->ports (serverPort);
|
||||||
@@ -441,7 +441,7 @@ public:
|
|||||||
Env env {*this,
|
Env env {*this,
|
||||||
envconfig([](std::unique_ptr<Config> cfg) {
|
envconfig([](std::unique_ptr<Config> cfg) {
|
||||||
(*cfg).deprecatedClearSection("port_rpc");
|
(*cfg).deprecatedClearSection("port_rpc");
|
||||||
(*cfg)["port_rpc"].set("ip", "127.0.0.1");
|
(*cfg)["port_rpc"].set("ip", getEnvLocalhostAddr());
|
||||||
return cfg;
|
return cfg;
|
||||||
}),
|
}),
|
||||||
std::make_unique<CaptureLogs>(messages)};
|
std::make_unique<CaptureLogs>(messages)};
|
||||||
@@ -455,7 +455,7 @@ public:
|
|||||||
Env env {*this,
|
Env env {*this,
|
||||||
envconfig([](std::unique_ptr<Config> cfg) {
|
envconfig([](std::unique_ptr<Config> cfg) {
|
||||||
(*cfg).deprecatedClearSection("port_rpc");
|
(*cfg).deprecatedClearSection("port_rpc");
|
||||||
(*cfg)["port_rpc"].set("ip", "127.0.0.1");
|
(*cfg)["port_rpc"].set("ip", getEnvLocalhostAddr());
|
||||||
(*cfg)["port_rpc"].set("port", "0");
|
(*cfg)["port_rpc"].set("port", "0");
|
||||||
return cfg;
|
return cfg;
|
||||||
}),
|
}),
|
||||||
@@ -470,7 +470,7 @@ public:
|
|||||||
Env env {*this,
|
Env env {*this,
|
||||||
envconfig([](std::unique_ptr<Config> cfg) {
|
envconfig([](std::unique_ptr<Config> cfg) {
|
||||||
(*cfg).deprecatedClearSection("port_rpc");
|
(*cfg).deprecatedClearSection("port_rpc");
|
||||||
(*cfg)["port_rpc"].set("ip", "127.0.0.1");
|
(*cfg)["port_rpc"].set("ip", getEnvLocalhostAddr());
|
||||||
(*cfg)["port_rpc"].set("port", "8081");
|
(*cfg)["port_rpc"].set("port", "8081");
|
||||||
(*cfg)["port_rpc"].set("protocol", "");
|
(*cfg)["port_rpc"].set("protocol", "");
|
||||||
return cfg;
|
return cfg;
|
||||||
@@ -495,17 +495,17 @@ public:
|
|||||||
ConfigSection::importNodeDatabase ());
|
ConfigSection::importNodeDatabase ());
|
||||||
cfg->legacy("database_path", "");
|
cfg->legacy("database_path", "");
|
||||||
cfg->setupControl(true, true, true);
|
cfg->setupControl(true, true, true);
|
||||||
(*cfg)["port_peer"].set("ip", "127.0.0.1");
|
(*cfg)["port_peer"].set("ip", getEnvLocalhostAddr());
|
||||||
(*cfg)["port_peer"].set("port", "8080");
|
(*cfg)["port_peer"].set("port", "8080");
|
||||||
(*cfg)["port_peer"].set("protocol", "peer");
|
(*cfg)["port_peer"].set("protocol", "peer");
|
||||||
(*cfg)["port_rpc"].set("ip", "127.0.0.1");
|
(*cfg)["port_rpc"].set("ip", getEnvLocalhostAddr());
|
||||||
(*cfg)["port_rpc"].set("port", "8081");
|
(*cfg)["port_rpc"].set("port", "8081");
|
||||||
(*cfg)["port_rpc"].set("protocol", "http,ws2");
|
(*cfg)["port_rpc"].set("protocol", "http,ws2");
|
||||||
(*cfg)["port_rpc"].set("admin", "127.0.0.1");
|
(*cfg)["port_rpc"].set("admin", getEnvLocalhostAddr());
|
||||||
(*cfg)["port_ws"].set("ip", "127.0.0.1");
|
(*cfg)["port_ws"].set("ip", getEnvLocalhostAddr());
|
||||||
(*cfg)["port_ws"].set("port", "8082");
|
(*cfg)["port_ws"].set("port", "8082");
|
||||||
(*cfg)["port_ws"].set("protocol", "ws");
|
(*cfg)["port_ws"].set("protocol", "ws");
|
||||||
(*cfg)["port_ws"].set("admin", "127.0.0.1");
|
(*cfg)["port_ws"].set("admin", getEnvLocalhostAddr());
|
||||||
return cfg;
|
return cfg;
|
||||||
}),
|
}),
|
||||||
std::make_unique<CaptureLogs>(messages)};
|
std::make_unique<CaptureLogs>(messages)};
|
||||||
|
|||||||
Reference in New Issue
Block a user