0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-25 16:22:35 +01:00

ircd::net: Improve listener interface w/ instance reference in callbacks.

This commit is contained in:
Jason Volk 2019-01-18 09:42:44 -08:00
parent d639eceba2
commit aeea524ac9
6 changed files with 51 additions and 30 deletions

View file

@ -38,7 +38,7 @@ struct ircd::client
static ctx::dock dock;
static uint64_t ctr; // monotonic
static void create(const std::shared_ptr<socket> &);
static void create(net::listener &, const std::shared_ptr<socket> &);
static size_t count(const net::ipport &remote); // cmp is by IP only, not port
static void terminate_all();
static void interrupt_all();

View file

@ -24,6 +24,7 @@ struct ircd::net::listener::acceptor
static log::log log;
static conf::item<milliseconds> timeout;
net::listener *listener;
std::string name;
std::string opts;
size_t backlog;
@ -35,6 +36,7 @@ struct ircd::net::listener::acceptor
size_t accepting {0};
size_t handshaking {0};
bool interrupting {false};
bool handle_set {false};
ctx::dock joining;
void configure(const json::object &opts);
@ -48,13 +50,14 @@ struct ircd::net::listener::acceptor
void accept(const error_code &ec, std::shared_ptr<socket>, std::weak_ptr<acceptor>) noexcept;
// Accept next
void next();
bool set_handle();
// Acceptor shutdown
bool interrupt() noexcept;
void join() noexcept;
acceptor(const string_view &name,
acceptor(net::listener &,
const string_view &name,
const json::object &opts,
listener::callback,
listener::proffer);

View file

@ -22,8 +22,8 @@ namespace ircd::net
struct ircd::net::listener
{
struct acceptor;
using callback = std::function<void (const std::shared_ptr<socket> &)>;
using proffer = std::function<bool (const ipport &)>;
using callback = std::function<void (listener &, const std::shared_ptr<socket> &)>;
using proffer = std::function<bool (listener &, const ipport &)>;
IRCD_EXCEPTION(net::error, error)
@ -34,6 +34,8 @@ struct ircd::net::listener
explicit operator json::object() const;
string_view name() const;
bool start();
listener(const string_view &name,
const json::object &options,
callback,

View file

@ -254,7 +254,8 @@ ircd::client::terminate_all()
}
void
ircd::client::create(const std::shared_ptr<socket> &sock)
ircd::client::create(net::listener &,
const std::shared_ptr<socket> &sock)
{
const auto client
{

View file

@ -952,12 +952,9 @@ ircd::net::listener::listener(const string_view &name,
proffer pcb)
:acceptor
{
std::make_shared<struct acceptor>(name, opts, std::move(cb), std::move(pcb))
std::make_shared<struct acceptor>(*this, name, opts, std::move(cb), std::move(pcb))
}
{
// Starts the first asynchronous accept. This has to be done out here after
// the acceptor's shared object is constructed.
acceptor->next();
}
/// Cancels all pending accepts and handshakes and waits (yields ircd::ctx)
@ -970,6 +967,14 @@ noexcept
acceptor->join();
}
bool
ircd::net::listener::start()
{
return acceptor && !acceptor->handle_set?
acceptor->set_handle():
false;
}
ircd::string_view
ircd::net::listener::name()
const
@ -1088,12 +1093,17 @@ ircd::net::operator<<(std::ostream &s, const struct listener::acceptor &a)
// listener::acceptor::acceptor
//
ircd::net::listener::acceptor::acceptor(const string_view &name,
ircd::net::listener::acceptor::acceptor(net::listener &listener,
const string_view &name,
const json::object &opts,
listener::callback cb,
listener::proffer pcb)
try
:name
:listener
{
&listener
}
,name
{
name
}
@ -1223,24 +1233,27 @@ catch(const boost::system::system_error &e)
/// Sets the next asynchronous handler to start the next accept sequence.
/// Each call to next() sets one handler which handles the connect for one
/// socket. After the connect, an asynchronous SSL handshake handler is set
/// for the socket, and next() is called again to setup for the next socket
/// too.
void
ircd::net::listener::acceptor::next()
/// for the socket.
bool
ircd::net::listener::acceptor::set_handle()
try
{
auto sock(std::make_shared<ircd::socket>(ssl));
/*
log::debug
assert(!handle_set);
handle_set = true;
const unwind::exceptional unset{[this]
{
log, "%s: socket(%p) is the next socket to accept",
string(logheadbuf, *this),
sock.get()
handle_set = false;
}};
auto sock
{
std::make_shared<ircd::socket>(ssl)
};
*/
++accepting;
ip::tcp::socket &sd(*sock);
a.async_accept(sd, std::bind(&acceptor::accept, this, ph::_1, sock, weak_from(*this)));
return true;
}
catch(const std::exception &e)
{
@ -1262,8 +1275,12 @@ noexcept try
if(unlikely(a.expired()))
return;
--accepting;
assert(bool(sock));
assert(handle_set);
assert(accepting > 0);
handle_set = false;
--accepting;
log::debug
{
log, "%s: accepted(%zu) %s %s",
@ -1278,7 +1295,7 @@ noexcept try
// Call the proffer-callback if available. This allows the application
// to check whether to allow or deny this remote before the handshake.
if(pcb && !pcb(remote_ipport(*sock)))
if(pcb && !pcb(*listener, remote_ipport(*sock)))
{
net::close(*sock, dc::RST, close_ignore);
return;
@ -1362,10 +1379,7 @@ ircd::net::listener::acceptor::check_accept_error(const error_code &ec,
throw ctx::interrupted();
if(likely(!ec))
{
this->next();
return true;
}
if(system_category(ec)) switch(ec.value())
{
@ -1401,7 +1415,7 @@ noexcept try
check_handshake_error(ec, *sock);
sock->cancel_timeout();
assert(bool(cb));
cb(sock);
cb(*listener, sock);
}
catch(const ctx::interrupted &e)
{

View file

@ -159,7 +159,8 @@ load_listener(const m::event &event)
}
static bool
_listener_proffer(const net::ipport &ipport)
_listener_proffer(net::listener &,
const net::ipport &ipport)
{
if(unlikely(ircd::run::level != ircd::run::level::RUN))
{