Commit 712dd339 authored by jan.koester's avatar jan.koester
Browse files

test

parent 79df8a75
Loading
Loading
Loading
Loading
+54 −1
Changes for src/posix/tcp.cpp: 54 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -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>
@@ -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
@@ -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 {
@@ -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() {