mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 07:23:53 +01:00
ircd::net: Improve listener interface w/ instance reference in callbacks.
This commit is contained in:
parent
d639eceba2
commit
aeea524ac9
6 changed files with 51 additions and 30 deletions
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
60
ircd/net.cc
60
ircd/net.cc
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue