mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-04 18:55:49 +00:00
183 lines
4.9 KiB
C++
183 lines
4.9 KiB
C++
//------------------------------------------------------------------------------
|
|
/*
|
|
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.
|
|
*/
|
|
//==============================================================================
|
|
|
|
#include <ripple/beast/net/IPEndpoint.h>
|
|
#include <boost/algorithm/string.hpp>
|
|
|
|
namespace beast {
|
|
namespace IP {
|
|
|
|
Endpoint::Endpoint() : m_port(0)
|
|
{
|
|
}
|
|
|
|
Endpoint::Endpoint(Address const& addr, Port port) : m_addr(addr), m_port(port)
|
|
{
|
|
}
|
|
|
|
std::optional<Endpoint>
|
|
Endpoint::from_string_checked(std::string const& s)
|
|
{
|
|
if (s.size() <= 64)
|
|
{
|
|
std::stringstream is(boost::trim_copy(s));
|
|
Endpoint endpoint;
|
|
is >> endpoint;
|
|
if (!is.fail() && is.rdbuf()->in_avail() == 0)
|
|
return endpoint;
|
|
}
|
|
return {};
|
|
}
|
|
|
|
Endpoint
|
|
Endpoint::from_string(std::string const& s)
|
|
{
|
|
if (std::optional<Endpoint> const result = from_string_checked(s))
|
|
return *result;
|
|
return Endpoint{};
|
|
}
|
|
|
|
std::string
|
|
Endpoint::to_string() const
|
|
{
|
|
std::string s;
|
|
s.reserve(
|
|
(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;
|
|
}
|
|
|
|
bool
|
|
operator==(Endpoint const& lhs, Endpoint const& rhs)
|
|
{
|
|
return lhs.address() == rhs.address() && lhs.port() == rhs.port();
|
|
}
|
|
|
|
bool
|
|
operator<(Endpoint const& lhs, Endpoint const& rhs)
|
|
{
|
|
if (lhs.address() < rhs.address())
|
|
return true;
|
|
if (lhs.address() > rhs.address())
|
|
return false;
|
|
return lhs.port() < rhs.port();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
std::istream&
|
|
operator>>(std::istream& is, Endpoint& endpoint)
|
|
{
|
|
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;
|
|
|
|
while (is && is.rdbuf()->in_avail() > 0 && is.get(i))
|
|
{
|
|
// NOTE: There is a legacy data format
|
|
// that allowed space to be used as address / port separator
|
|
// 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.setstate(std::ios_base::failbit);
|
|
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;
|
|
is >> port;
|
|
if (is.fail())
|
|
return is;
|
|
endpoint = Endpoint(addr, port);
|
|
}
|
|
else
|
|
endpoint = Endpoint(addr);
|
|
|
|
return is;
|
|
}
|
|
|
|
} // namespace IP
|
|
} // namespace beast
|