0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-25 08:12:37 +01:00

ircd::server: Require service suffix for peer map keying; refactor host canonization.

This commit is contained in:
Jason Volk 2020-03-05 16:34:13 -08:00
parent 2e2b56e89f
commit f5d5f6de3b
4 changed files with 96 additions and 53 deletions

View file

@ -27,8 +27,8 @@ namespace ircd::net
string_view &host(hostport &);
string_view string(const mutable_buffer &out, const hostport &);
string_view canonize(const mutable_buffer &out, const hostport &, const uint16_t &port = 0);
std::string canonize(const hostport &, const uint16_t &port = 0);
string_view canonize(const mutable_buffer &out, const hostport &);
std::string canonize(const hostport &);
std::ostream &operator<<(std::ostream &, const hostport &);
}

View file

@ -31,8 +31,7 @@ struct ircd::server::peer
uint64_t id {++ids};
net::ipport remote;
std::string hostcanon;
std::string service;
std::string hostcanon; // hostname:service[:port]
net::open_opts open_opts;
std::list<link> links;
std::unique_ptr<err> e;

View file

@ -4431,40 +4431,49 @@ ircd::net::operator<<(std::ostream &s, const hostport &t)
}
std::string
ircd::net::canonize(const hostport &hp,
const uint16_t &port)
ircd::net::canonize(const hostport &hostport)
{
const size_t len
{
size(host(hp)) + 1 + 5 + 1 // optimistic ':' + portnum
size(host(hostport)) // host
+ 1 + size(service(hostport)) // ':' + service
+ 1 + 5 + 1 // ':' + portnum (optimistic)
};
return ircd::string(len, [&hp, &port]
return ircd::string(len, [&hostport]
(const mutable_buffer &buf)
{
return canonize(buf, hp, port);
return canonize(buf, hostport);
});
}
ircd::string_view
ircd::net::canonize(const mutable_buffer &buf,
const hostport &hp,
const uint16_t &port)
const hostport &hostport)
{
thread_local char tlbuf[rfc3986::DOMAIN_BUFSIZE * 2];
thread_local char tlbuf[2][rfc3986::DOMAIN_BUFSIZE * 2];
if(net::port(hp) == 0 || net::port(hp) == port)
assert(service(hostport));
if(unlikely(!service(hostport)))
throw error
{
"Missing service suffix in hostname:service string.",
};
if(port(hostport))
return fmt::sprintf
{
buf, "%s",
tolower(tlbuf, host(hp)),
buf, "%s:%s:%u",
tolower(tlbuf[0], host(hostport)),
tolower(tlbuf[1], service(hostport)),
port(hostport),
};
return fmt::sprintf
{
buf, "%s:%u",
tolower(tlbuf, host(hp)),
net::port(hp)
buf, "%s:%s",
tolower(tlbuf[0], host(hostport)),
tolower(tlbuf[1], service(hostport)),
};
}

View file

@ -17,6 +17,7 @@ namespace ircd::server
template<class F> static size_t accumulate_peers(F&&);
template<class F> static size_t accumulate_links(F&&);
template<class F> static size_t accumulate_tags(F&&);
static string_view canonize(const hostport &); // TLS buffer
// Internal control
static decltype(ircd::server::peers)::iterator
@ -126,14 +127,17 @@ ircd::server::init::interrupt()
ircd::server::peer &
ircd::server::get(const net::hostport &hostport)
{
thread_local char canonbuf[512];
const auto canonized
const auto hostcanon
{
net::canonize(canonbuf, hostport)
server::canonize(hostport)
};
auto it(peers.lower_bound(canonized));
if(it == peers.end() || it->first != canonized)
auto it
{
peers.lower_bound(hostcanon)
};
if(it == peers.end() || it->first != hostcanon)
it = create(hostport, it);
return *it->second;
@ -168,28 +172,47 @@ ircd::server::create(const net::hostport &hostport,
ircd::server::peer &
ircd::server::find(const net::hostport &hostport)
{
return *peers.at(host(hostport));
const auto hostcanon
{
server::canonize(hostport)
};
return *peers.at(hostcanon);
}
bool
ircd::server::exists(const net::hostport &hostport)
noexcept
{
return peers.find(host(hostport)) != end(peers);
const auto hostcanon
{
server::canonize(hostport)
};
return peers.find(hostcanon) != end(peers);
}
bool
ircd::server::errclear(const net::hostport &hostport)
{
const auto hostcanon
{
server::canonize(hostport)
};
const auto it
{
peers.find(host(hostport))
peers.find(hostcanon)
};
if(it == end(peers))
return false;
auto &peer(*it->second);
auto &peer
{
*it->second
};
return peer.err_clear();
}
@ -197,15 +220,19 @@ ircd::string_view
ircd::server::errmsg(const net::hostport &hostport)
noexcept
{
const auto it
const auto hostcanon
{
peers.find(host(hostport))
server::canonize(hostport)
};
if(it == end(peers))
return {};
const auto it
{
peers.find(hostcanon)
};
return it->second->err_msg();
return it != end(peers)?
it->second->err_msg():
string_view{};
}
bool
@ -316,6 +343,13 @@ ircd::server::accumulate_peers(F&& closure)
});
}
ircd::string_view
ircd::server::canonize(const net::hostport &hostport)
{
thread_local char buf[512];
return net::canonize(buf, hostport);
}
///////////////////////////////////////////////////////////////////////////////
//
// server/request.h
@ -383,14 +417,18 @@ __attribute__((stack_protect))
ircd::server::submit(const hostport &hostport,
request &request)
{
assert(request.tag == nullptr);
if(unlikely(ircd::run::level != ircd::run::level::RUN))
throw unavailable
{
"Unable to fulfill requests at this time."
};
assert(request.tag == nullptr);
auto &peer(server::get(hostport));
auto &peer
{
server::get(hostport)
};
peer.submit(request);
}
@ -577,34 +615,31 @@ ircd::server::peer::peer(const net::hostport &hostport,
{
net::canonize(hostport)
}
,service
{
// hostport arguments with a port of 0 are normal; if the port is such,
// and if we are supplied a service string an SRV query will be performed.
// For other port numbers, we ignore any service string and SRV won't be
// resolved.
!net::port(hostport)?
net::service(hostport):
string_view{}
}
,open_opts
{
std::move(open_opts)
open_opts
}
{
const net::hostport &canon{this->hostcanon};
const net::hostport &canon
{
this->hostcanon
};
this->open_opts.hostport.host = this->hostcanon;
this->open_opts.hostport.port = net::port(hostport);
this->open_opts.hostport.service = this->service;
// Ensure references are to this class's members
this->open_opts.hostport.host = host(canon);
this->open_opts.hostport.service = service(canon);
this->open_opts.hostport.port = port(hostport);
this->open_opts.server_name = this->hostcanon; // Send SNI for this name.
this->open_opts.common_name = this->hostcanon; // Cert verify this name.
// Send SNI for this name.
this->open_opts.server_name = host(canon);
if(rfc3986::valid(std::nothrow, rfc3986::parser::ip_address, host(this->open_opts.hostport)))
// Cert verify this name.
this->open_opts.common_name = host(canon);
if(rfc3986::valid(std::nothrow, rfc3986::parser::ip_address, host(canon)))
this->remote =
{
host(this->open_opts.hostport), port(this->open_opts.hostport)
host(canon), port(hostport)
};
this->open_opts.ipport = this->remote;