diff --git a/include/ircd/net/write.h b/include/ircd/net/write.h index c13c49e67..ef418a67f 100644 --- a/include/ircd/net/write.h +++ b/include/ircd/net/write.h @@ -15,6 +15,10 @@ namespace ircd::net { using const_buffers = vector_view; + // Observers + size_t flushing(const socket &); + size_t writable(const socket &); + // Non-blocking; writes at most one system-determined amount of // bytes or less with at most a single syscall. size_t write_one(socket &, const const_buffers &); diff --git a/ircd/net.cc b/ircd/net.cc index 2f9568098..fddb2d84c 100644 --- a/ircd/net.cc +++ b/ircd/net.cc @@ -331,6 +331,44 @@ ircd::net::write_one(socket &socket, return socket.write_one(buffers); } +/// Bytes remaining for transmission (in the kernel) +size_t +ircd::net::writable(const socket &socket) +{ + const ssize_t write_bufsz + ( + net::write_bufsz(socket) + ); + + const ssize_t flushing + ( + net::flushing(socket) + ); + + assert(write_bufsz >= flushing); + return std::max(write_bufsz - flushing, 0L); +} + +/// Bytes buffered for transmission (in the kernel) +size_t +ircd::net::flushing(const socket &socket) +{ + const ip::tcp::socket &sd(socket); + const auto &fd + { + mutable_cast(sd).lowest_layer().native_handle() + }; + + long value(0); + #ifdef TIOCOUTQ + syscall(::ioctl, fd, TIOCOUTQ, &value); + #else + #warning "TIOCOUTQ is not defined on this platform." + #endif + + return value; +} + /////////////////////////////////////////////////////////////////////////////// // // net/read.h