diff --git a/include/ircd/net/close.h b/include/ircd/net/close.h index 762dbc7bf..8ad75ae80 100644 --- a/include/ircd/net/close.h +++ b/include/ircd/net/close.h @@ -57,4 +57,10 @@ struct ircd::net::close_opts /// If specified, these socket options will be applied when conducting /// the disconnect (useful for adding an SO_LINGER time etc). const sock_opts *sopts { nullptr }; + + /// For portable clean disconnection shutdown(2) might be called prior to + /// close(2). Setting this option to dc::RST skips the shutdown(2) when + /// the caller deems it unnecessary. At this time it only affects non-SSL + /// sockets and in the future we will have io_uring(7) fuse these calls. + net::dc shutdown { dc::FIN }; }; diff --git a/ircd/client.cc b/ircd/client.cc index 35baa86b3..fb7c027da 100644 --- a/ircd/client.cc +++ b/ircd/client.cc @@ -587,7 +587,13 @@ try loghead(client), }; - client.close(net::dc::SSL_NOTIFY, net::close_ignore); + const net::close_opts opts + { + .type = net::dc::SSL_NOTIFY, + .shutdown = net::dc::RST, + }; + + client.close(opts, net::close_ignore); return false; } catch(const std::exception &e) diff --git a/ircd/net.cc b/ircd/net.cc index 2810167cc..274a9b759 100644 --- a/ircd/net.cc +++ b/ircd/net.cc @@ -1775,9 +1775,10 @@ try assert(!fini); log::debug { - log, "%s disconnect type:%s user[in:%zu out:%zu]", + log, "%s disconnect type:%s shut:%s user[in:%zu out:%zu]", loghead(*this), reflect(opts.type), + !ssl? reflect(opts.shutdown): "--"_sv, in.bytes, out.bytes }; @@ -1806,7 +1807,9 @@ try if(!ssl) { // Redirect SSL_NOTIFY to another strategy for non-SSL sockets. - sd.shutdown(ip::tcp::socket::shutdown_both); + if(opts.shutdown != dc::RST) + sd.shutdown(translate(opts.shutdown)); + sd.close(); break; }