Loading src/posix/tcp.cpp +54 −1 Changes for src/posix/tcp.cpp: 54 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <cstdio> #include <cstring> #include <cerrno> #include <climits> #include <chrono> #include <iostream> #include <unistd.h> Loading @@ -40,6 +41,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <fcntl.h> #include <sys/un.h> #include <netinet/tcp.h> #if defined(__FreeBSD__) || defined(__OpenBSD__) #include <sys/sysctl.h> #endif #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 Loading @@ -54,6 +58,46 @@ namespace { // ~127s) before the next resolved address is even tried. Mirrors the // timeout already used on the Windows side of this same call. constexpr int kConnectAttemptTimeoutMs = 10000; // listen(2) silently clamps its backlog to this host's kernel limit. Read the // limit when listen() is called so getMaxconnections() reflects the backlog we // actually requested from the kernel (also used to size event buffers). int kernelListenBacklogLimit() { #if defined(__linux__) FILE* file = std::fopen("/proc/sys/net/core/somaxconn", "r"); if (!file) return 0; long value = 0; const bool valid = std::fscanf(file, "%ld", &value) == 1 && value > 0 && value <= INT_MAX; std::fclose(file); return valid ? static_cast<int>(value) : 0; #elif defined(__FreeBSD__) int value = 0; size_t length = sizeof(value); return ::sysctlbyname("kern.ipc.soacceptqueue", &value, &length, nullptr, 0) == 0 && length == sizeof(value) && value > 0 ? value : 0; #elif defined(__OpenBSD__) int mib[2] = {CTL_KERN, KERN_SOMAXCONN}; int value = 0; size_t length = sizeof(value); return ::sysctl(mib, 2, &value, &length, nullptr, 0) == 0 && length == sizeof(value) && value > 0 ? value : 0; #else return 0; #endif } const char* kernelListenBacklogSetting() { #if defined(__linux__) return "net.core.somaxconn"; #elif defined(__FreeBSD__) return "kern.ipc.soacceptqueue"; #elif defined(__OpenBSD__) return "kern.somaxconn"; #else return "kernel listen backlog limit"; #endif } } namespace netplus { Loading Loading @@ -178,12 +222,21 @@ void tcp::bind() { void tcp::listen() { if (_Listening) return; if (::listen(_Socket, _Maxconnections) < 0) { const int requested = _Maxconnections; const int kernelLimit = kernelListenBacklogLimit(); const int backlog = kernelLimit > 0 && requested > kernelLimit ? kernelLimit : requested; if (::listen(_Socket, backlog) < 0) { NetException e; e[NetException::Critical] << "tcp::listen failed: " << strerror(errno); throw e; } _Maxconnections = backlog; _Listening = true; if (backlog != requested) { std::cerr << "netplus::tcp::listen: requested backlog " << requested << " exceeds " << kernelListenBacklogSetting() << "=" << kernelLimit << "; using " << backlog << std::endl; } } void tcp::setNonBlock() { Loading Loading
src/posix/tcp.cpp +54 −1 Changes for src/posix/tcp.cpp: 54 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <cstdio> #include <cstring> #include <cerrno> #include <climits> #include <chrono> #include <iostream> #include <unistd.h> Loading @@ -40,6 +41,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <fcntl.h> #include <sys/un.h> #include <netinet/tcp.h> #if defined(__FreeBSD__) || defined(__OpenBSD__) #include <sys/sysctl.h> #endif #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 Loading @@ -54,6 +58,46 @@ namespace { // ~127s) before the next resolved address is even tried. Mirrors the // timeout already used on the Windows side of this same call. constexpr int kConnectAttemptTimeoutMs = 10000; // listen(2) silently clamps its backlog to this host's kernel limit. Read the // limit when listen() is called so getMaxconnections() reflects the backlog we // actually requested from the kernel (also used to size event buffers). int kernelListenBacklogLimit() { #if defined(__linux__) FILE* file = std::fopen("/proc/sys/net/core/somaxconn", "r"); if (!file) return 0; long value = 0; const bool valid = std::fscanf(file, "%ld", &value) == 1 && value > 0 && value <= INT_MAX; std::fclose(file); return valid ? static_cast<int>(value) : 0; #elif defined(__FreeBSD__) int value = 0; size_t length = sizeof(value); return ::sysctlbyname("kern.ipc.soacceptqueue", &value, &length, nullptr, 0) == 0 && length == sizeof(value) && value > 0 ? value : 0; #elif defined(__OpenBSD__) int mib[2] = {CTL_KERN, KERN_SOMAXCONN}; int value = 0; size_t length = sizeof(value); return ::sysctl(mib, 2, &value, &length, nullptr, 0) == 0 && length == sizeof(value) && value > 0 ? value : 0; #else return 0; #endif } const char* kernelListenBacklogSetting() { #if defined(__linux__) return "net.core.somaxconn"; #elif defined(__FreeBSD__) return "kern.ipc.soacceptqueue"; #elif defined(__OpenBSD__) return "kern.somaxconn"; #else return "kernel listen backlog limit"; #endif } } namespace netplus { Loading Loading @@ -178,12 +222,21 @@ void tcp::bind() { void tcp::listen() { if (_Listening) return; if (::listen(_Socket, _Maxconnections) < 0) { const int requested = _Maxconnections; const int kernelLimit = kernelListenBacklogLimit(); const int backlog = kernelLimit > 0 && requested > kernelLimit ? kernelLimit : requested; if (::listen(_Socket, backlog) < 0) { NetException e; e[NetException::Critical] << "tcp::listen failed: " << strerror(errno); throw e; } _Maxconnections = backlog; _Listening = true; if (backlog != requested) { std::cerr << "netplus::tcp::listen: requested backlog " << requested << " exceeds " << kernelListenBacklogSetting() << "=" << kernelLimit << "; using " << backlog << std::endl; } } void tcp::setNonBlock() { Loading