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:
parent
6ec9867843
commit
7f2eb104b6
3 changed files with 71 additions and 56 deletions
|
@ -63,12 +63,13 @@ struct ircd::net::acceptor
|
||||||
// Handshake stack
|
// Handshake stack
|
||||||
bool handle_sni(SSL &, int &ad);
|
bool handle_sni(SSL &, int &ad);
|
||||||
string_view handle_alpn(SSL &, const vector_view<const string_view> &in);
|
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;
|
void handshake(const error_code &, const std::shared_ptr<socket>, const decltype(handshaking)::const_iterator) noexcept;
|
||||||
|
|
||||||
// Acceptance stack
|
// Acceptance stack
|
||||||
static bool proffer_default(listener &, const ipport &);
|
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;
|
void accept(const error_code &, const std::shared_ptr<socket>) noexcept;
|
||||||
|
|
||||||
// Accept next
|
// Accept next
|
||||||
|
|
114
ircd/net.cc
114
ircd/net.cc
|
@ -1590,46 +1590,30 @@ noexcept try
|
||||||
};
|
};
|
||||||
|
|
||||||
--accepting;
|
--accepting;
|
||||||
if(!check_accept_error(ec, *sock))
|
if(unlikely(!check_accept_error(ec, *sock)))
|
||||||
|
{
|
||||||
|
allow(*this);
|
||||||
|
net::close(*sock, dc::RST, close_ignore);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto &remote
|
const auto &remote
|
||||||
{
|
{
|
||||||
remote_ipport(*sock)
|
remote_ipport(*sock)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call the proffer-callback if available. This allows the application
|
if(unlikely(!check_handshake_limit(*sock, remote)))
|
||||||
// to check whether to allow or deny this remote before the handshake.
|
|
||||||
if(pcb && !pcb(*listener_, remote))
|
|
||||||
{
|
{
|
||||||
|
allow(*this);
|
||||||
net::close(*sock, dc::RST, close_ignore);
|
net::close(*sock, dc::RST, close_ignore);
|
||||||
return;
|
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);
|
net::close(*sock, dc::RST, close_ignore);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1664,9 +1648,9 @@ catch(const ctx::interrupted &e)
|
||||||
thread_local char ecbuf[64];
|
thread_local char ecbuf[64];
|
||||||
log::debug
|
log::debug
|
||||||
{
|
{
|
||||||
log, "%s acceptor interrupted %s %s",
|
log, "%s acceptor interrupted %s :%s",
|
||||||
loghead(*sock),
|
|
||||||
loghead(*this),
|
loghead(*this),
|
||||||
|
loghead(*sock),
|
||||||
string(ecbuf, ec)
|
string(ecbuf, ec)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1675,30 +1659,14 @@ catch(const ctx::interrupted &e)
|
||||||
assert(!ec_);
|
assert(!ec_);
|
||||||
joining.notify_all();
|
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)
|
catch(const std::exception &e)
|
||||||
{
|
{
|
||||||
assert(bool(sock));
|
assert(bool(sock));
|
||||||
log::error
|
log::error
|
||||||
{
|
{
|
||||||
log, "%s %s in accept(): %s",
|
log, "%s acceptor error in accept() %s :%s",
|
||||||
loghead(*sock),
|
|
||||||
loghead(*this),
|
loghead(*this),
|
||||||
|
loghead(*sock),
|
||||||
e.what()
|
e.what()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1715,6 +1683,7 @@ catch(const std::exception &e)
|
||||||
bool
|
bool
|
||||||
ircd::net::acceptor::check_accept_error(const error_code &ec,
|
ircd::net::acceptor::check_accept_error(const error_code &ec,
|
||||||
socket &sock)
|
socket &sock)
|
||||||
|
const
|
||||||
{
|
{
|
||||||
using std::errc;
|
using std::errc;
|
||||||
|
|
||||||
|
@ -1727,14 +1696,58 @@ ircd::net::acceptor::check_accept_error(const error_code &ec,
|
||||||
if(system_category(ec)) switch(ec.value())
|
if(system_category(ec)) switch(ec.value())
|
||||||
{
|
{
|
||||||
case int(errc::operation_canceled):
|
case int(errc::operation_canceled):
|
||||||
return false;
|
throw ctx::interrupted();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw_system_error(ec);
|
thread_local char ecbuf[64];
|
||||||
__builtin_unreachable();
|
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
|
/// Default proffer callback which accepts this connection and allows the
|
||||||
|
@ -1841,6 +1854,7 @@ catch(const std::exception &e)
|
||||||
void
|
void
|
||||||
ircd::net::acceptor::check_handshake_error(const error_code &ec,
|
ircd::net::acceptor::check_handshake_error(const error_code &ec,
|
||||||
socket &sock)
|
socket &sock)
|
||||||
|
const
|
||||||
{
|
{
|
||||||
using std::errc;
|
using std::errc;
|
||||||
|
|
||||||
|
|
|
@ -265,6 +265,10 @@ _listener_proffer(net::listener &listener,
|
||||||
return false;
|
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)))
|
if(unlikely(client::map.size() >= size_t(client::settings::max_client)))
|
||||||
{
|
{
|
||||||
log::warning
|
log::warning
|
||||||
|
@ -288,10 +292,6 @@ _listener_proffer(net::listener &listener,
|
||||||
return false;
|
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))
|
if(client::count(ipport) >= size_t(client::settings::max_client_per_peer))
|
||||||
{
|
{
|
||||||
log::dwarning
|
log::dwarning
|
||||||
|
|
Loading…
Reference in a new issue