0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-27 07:54:05 +01:00

ircd::net::acceptor: Refactor error and limit handling branches; fix reset.

This commit is contained in:
Jason Volk 2020-03-03 14:12:28 -08:00
parent 6ec9867843
commit 7f2eb104b6
3 changed files with 71 additions and 56 deletions

View file

@ -63,12 +63,13 @@ struct ircd::net::acceptor
// Handshake stack
bool handle_sni(SSL &, int &ad);
string_view handle_alpn(SSL &, const vector_view<const string_view> &in);
void check_handshake_error(const error_code &ec, socket &);
void check_handshake_error(const error_code &ec, socket &) const;
void handshake(const error_code &, const std::shared_ptr<socket>, const decltype(handshaking)::const_iterator) noexcept;
// Acceptance stack
static bool proffer_default(listener &, const ipport &);
bool check_accept_error(const error_code &ec, socket &);
bool check_handshake_limit(socket &, const ipport &) const;
bool check_accept_error(const error_code &ec, socket &) const;
void accept(const error_code &, const std::shared_ptr<socket>) noexcept;
// Accept next

View file

@ -1590,46 +1590,30 @@ noexcept try
};
--accepting;
if(!check_accept_error(ec, *sock))
if(unlikely(!check_accept_error(ec, *sock)))
{
allow(*this);
net::close(*sock, dc::RST, close_ignore);
return;
}
const auto &remote
{
remote_ipport(*sock)
};
// 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(*listener_, remote))
if(unlikely(!check_handshake_limit(*sock, remote)))
{
allow(*this);
net::close(*sock, dc::RST, close_ignore);
return;
}
if(unlikely(handshaking_count(*this) >= size_t(handshaking_max)))
// Call the proffer-callback. This allows the application to check whether
// to allow or deny this remote before the handshake, as well as setting
// the next accept to shape the kernel's queue.
if(!pcb(*listener_, remote))
{
log::dwarning
{
log, "%s refusing to handshake %s; exceeds maximum of %zu handshakes.",
loghead(*sock),
loghead(*this),
size_t(handshaking_max),
};
net::close(*sock, dc::RST, close_ignore);
return;
}
if(unlikely(handshaking_count(*this, remote) >= size_t(handshaking_max_per_peer)))
{
log::dwarning
{
log, "%s refusing to handshake %s; exceeds maximum of %zu handshakes to them.",
loghead(*sock),
loghead(*this),
size_t(handshaking_max_per_peer),
};
net::close(*sock, dc::RST, close_ignore);
return;
}
@ -1664,9 +1648,9 @@ catch(const ctx::interrupted &e)
thread_local char ecbuf[64];
log::debug
{
log, "%s acceptor interrupted %s %s",
loghead(*sock),
log, "%s acceptor interrupted %s :%s",
loghead(*this),
loghead(*sock),
string(ecbuf, ec)
};
@ -1675,30 +1659,14 @@ catch(const ctx::interrupted &e)
assert(!ec_);
joining.notify_all();
}
catch(const std::system_error &e)
{
assert(bool(sock));
log::derror
{
log, "%s %s in accept(): %s",
loghead(*sock),
loghead(*this),
e.what()
};
error_code ec_;
sock->sd.close(ec_);
assert(!ec_);
joining.notify_all();
}
catch(const std::exception &e)
{
assert(bool(sock));
log::error
{
log, "%s %s in accept(): %s",
loghead(*sock),
log, "%s acceptor error in accept() %s :%s",
loghead(*this),
loghead(*sock),
e.what()
};
@ -1715,6 +1683,7 @@ catch(const std::exception &e)
bool
ircd::net::acceptor::check_accept_error(const error_code &ec,
socket &sock)
const
{
using std::errc;
@ -1727,14 +1696,58 @@ ircd::net::acceptor::check_accept_error(const error_code &ec,
if(system_category(ec)) switch(ec.value())
{
case int(errc::operation_canceled):
return false;
throw ctx::interrupted();
default:
break;
}
throw_system_error(ec);
__builtin_unreachable();
thread_local char ecbuf[64];
log::derror
{
log, "%s in accept %s :%s",
loghead(*this),
loghead(sock),
string(ecbuf, ec),
};
return false;
}
/// Checks performed for whether handshaking limits have been reached before
/// allowing a handshake.
bool
ircd::net::acceptor::check_handshake_limit(socket &sock,
const ipport &remote)
const
{
if(unlikely(handshaking_count(*this) >= size_t(handshaking_max)))
{
log::warning
{
log, "%s refusing to handshake %s; exceeds maximum of %zu handshakes.",
loghead(sock),
loghead(*this),
size_t(handshaking_max),
};
return false;
}
if(unlikely(handshaking_count(*this, remote) >= size_t(handshaking_max_per_peer)))
{
log::dwarning
{
log, "%s refusing to handshake %s; exceeds maximum of %zu handshakes to them.",
loghead(sock),
loghead(*this),
size_t(handshaking_max_per_peer),
};
return false;
}
return true;
}
/// Default proffer callback which accepts this connection and allows the
@ -1841,6 +1854,7 @@ catch(const std::exception &e)
void
ircd::net::acceptor::check_handshake_error(const error_code &ec,
socket &sock)
const
{
using std::errc;

View file

@ -265,6 +265,10 @@ _listener_proffer(net::listener &listener,
return false;
}
// Sets the asynchronous handler for the next accept. We can play with
// delaying this call under certain conditions to provide flow control.
allow(listener);
if(unlikely(client::map.size() >= size_t(client::settings::max_client)))
{
log::warning
@ -288,10 +292,6 @@ _listener_proffer(net::listener &listener,
return false;
}
// Sets the asynchronous handler for the next accept. We can play with
// delaying this call under certain conditions to provide flow control.
allow(listener);
if(client::count(ipport) >= size_t(client::settings::max_client_per_peer))
{
log::dwarning