32#include <boost/spirit/include/karma_generate.hpp>
33#include <boost/spirit/include/karma_uint.hpp>
47 constexpr const char tld[] =
u8".onion";
48 constexpr const char unknown_host[] =
"<unknown tor host>";
50 constexpr const unsigned v2_length = 16;
51 constexpr const unsigned v3_length = 56;
53 constexpr const char base32_alphabet[] =
54 u8"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz234567";
56 expect<void> host_check(boost::string_ref host)
noexcept
58 if (!host.ends_with(tld))
61 host.remove_suffix(
sizeof(tld) - 1);
64 if (host.size() != v2_length && host.size() != v3_length)
66 if (host.find_first_not_of(base32_alphabet) != boost::string_ref::npos)
84 tor_address::tor_address(const boost::string_ref host, const std::
uint16_t port) noexcept
88 assert(host.size() <
sizeof(host_));
90 const std::size_t length = std::min(
sizeof(host_) - 1, host.size());
91 std::memcpy(host_, host.data(), length);
92 std::memset(host_ + length, 0,
sizeof(host_) - length);
103 static_assert(
sizeof(unknown_host) <=
sizeof(host_),
"bad buffer size");
104 std::memcpy(host_, unknown_host,
sizeof(unknown_host));
105 std::memset(host_ +
sizeof(unknown_host), 0,
sizeof(host_) -
sizeof(unknown_host));
111 const boost::string_ref
port =
112 address.substr(host.size() + (host.size() ==
address.size() ? 0 : 1));
116 std::uint16_t porti = default_port;
120 static_assert(v2_length <= v3_length,
"bad internal host size");
121 static_assert(v3_length +
sizeof(tld) ==
sizeof(tor_address::host_),
"bad internal host size");
122 return tor_address{host, porti};
128 if (in._load(src, hparent) && in.host.size() <
sizeof(host_) && (in.host == unknown_host || !host_check(in.host).has_error()))
130 std::memcpy(host_, in.host.data(), in.host.size());
131 std::memset(host_ + in.host.size(), 0,
sizeof(host_) - in.host.size());
135 static_assert(
sizeof(unknown_host) <=
sizeof(host_),
"bad buffer size");
136 std::memcpy(host_, unknown_host,
sizeof(unknown_host));
143 const tor_serialized out{std::string{host_}, port_};
144 return out.store(
dest, hparent);
150 std::memcpy(host_, rhs.host_,
sizeof(host_));
155 if (
this != std::addressof(rhs))
158 std::memcpy(host_, rhs.host_,
sizeof(host_));
165 static_assert(1 <=
sizeof(host_),
"host size too small");
166 return host_[0] ==
'<';
176 return std::strcmp(
host_str(), rhs.host_str()) < 0 ||
port() < rhs.port();
182 return std::strcmp(
host_str(), rhs.host_str()) == 0;
187 const std::size_t host_length = std::strlen(
host_str());
188 const std::size_t port_length =
189 port_ == 0 ? 0 : std::numeric_limits<std::uint16_t>::digits10 + 2;
192 out.reserve(host_length + port_length);
193 out.assign(
host_str(), host_length);
198 namespace karma = boost::spirit::karma;
199 karma::generate(std::back_inserter(out), karma::ushort_,
port());
bool _load(epee::serialization::portable_storage &src, epee::serialization::section *hparent)
Load from epee p2p format, and.
static expect< tor_address > make(boost::string_ref address, std::uint16_t default_port=0)
bool less(const tor_address &rhs) const noexcept
static const char * unknown_str() noexcept
bool equal(const tor_address &rhs) const noexcept
bool store(epee::serialization::portable_storage &dest, epee::serialization::section *hparent) const
Store in epee p2p format.
tor_address & operator=(const tor_address &rhs) noexcept
bool is_unknown() const noexcept
const char * host_str() const noexcept
std::uint16_t port() const noexcept
tor_address() noexcept
An object with port() == 0 and host_str() == unknown_str().
bool is_same_host(const tor_address &rhs) const noexcept
#define ELECTRONEUM_CHECK(...)
Check expect<void> and return errors in current scope.
#define KV_SERIALIZE(varialble)
#define END_KV_SERIALIZE_MAP()
#define BEGIN_KV_SERIALIZE_MAP()
@ invalid_port
Outside of 0-65535 range.
@ invalid_tor_address
Invalid base32 or length.
@ expected_tld
Expected a tld.
CXA_THROW_INFO_T void(* dest)(void *))