Commit 860e4278 authored by jan.koester's avatar jan.koester
Browse files

test

parent cc665827
Loading
Loading
Loading
Loading
+5 −0
Changes for config/proxyplus.yaml: 5 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -66,6 +66,11 @@ proxyplus:
    # load-balanced upstream connections, and each WebSocket tunnel's socket pair + its own
    # kqueue/epoll fd. 0 = leave the OS/login-class default alone.
    max_open_files: 65536
    # Idle connections (no read/write activity) are closed after this many seconds --
    # reclaims fds an upstream/client never properly closed (root cause of the same
    # fd-exhaustion incident max_open_files guards against). 0 = never time out idle
    # connections (the old, pre-fix behavior).
    idle_connection_timeout_seconds: 120

  pid_file: "/run/proxyplus.pid"
  recovery_mode: false
+3 −0
Changes for src/config/BootstrapConfig.cpp: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ const std::set<std::string> &knownLeafPatterns() {
        "/proxyplus/process/user",
        "/proxyplus/process/group",
        "/proxyplus/process/max_open_files",
        "/proxyplus/process/idle_connection_timeout_seconds",
        "/proxyplus/pid_file",
        "/proxyplus/recovery_mode",
        "/proxyplus/maintenance_mode",
@@ -223,6 +224,8 @@ void BootstrapConfig::loadAndValidate() {
    cfg.processUser = readValue(conf, "/proxyplus/process/user", "");
    cfg.processGroup = readValue(conf, "/proxyplus/process/group", "");
    cfg.maxOpenFiles = readInt(conf, "/proxyplus/process/max_open_files", 65536);
    cfg.idleConnectionTimeoutSeconds =
        readInt(conf, "/proxyplus/process/idle_connection_timeout_seconds", 120);
    cfg.pidFile = readValue(conf, "/proxyplus/pid_file", "");

    cfg.recoveryMode = readBool(conf, "/proxyplus/recovery_mode", false) ? RecoveryMode::Recover
+11 −0
Changes for src/config/BootstrapConfig.h: 11 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -88,6 +88,17 @@ struct AppConfig {
    // alone (opt-out escape hatch for a platform where this is managed externally).
    int maxOpenFiles = 65536;

    // Forwarded to libhttppp::HttpEvent's idleTimeoutSeconds ctor param (see httpd.h) --
    // closes an accepted connection once it's gone this long with no read/write activity,
    // reclaiming exactly the fd leak that produced the "Too many open files" incident
    // maxOpenFiles's comment above references. Unlike maxOpenFiles's 0=opt-out convention,
    // this defaults to a positive value: the whole point is for proxyplus to fix its own
    // root-caused leak out of the box, not require every deployment to remember to opt in.
    // 2 minutes is generous enough not to kill a legitimately slow-but-alive client while
    // still being short enough to reclaim genuinely abandoned connections. 0 still means
    // "disabled" for anyone who explicitly wants the old always-open behavior.
    int idleConnectionTimeoutSeconds = 120;

    RecoveryMode recoveryMode = RecoveryMode::Normal;
    MaintenanceMode maintenanceMode = MaintenanceMode::Off;
};
+4 −2
Changes for src/http/HttpProxyServer.cpp: 4 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -113,8 +113,10 @@ HttpProxyController::HttpProxyController(std::vector<netplus::socket *> serverSo
                                          auth::IAuthService &authService,
                                          plugin::PluginManager &pluginManager,
                                          lb::LoadBalancer &loadBalancer,
                                          tls::AcmeChallengeStore *acmeChallenges)
    : libhttppp::HttpEvent(std::move(serverSockets))
                                          tls::AcmeChallengeStore *acmeChallenges,
                                          int idleTimeoutSeconds)
    : libhttppp::HttpEvent(std::move(serverSockets), /*timeout=*/1000, /*h2OffloadThreads=*/0,
                            idleTimeoutSeconds)
    , _listenerLabel(std::move(listenerLabel))
    , _tlsActive(tlsActive)
    , _configStore(configStore)
+12 −3
Changes for src/http/HttpProxyServer.h: 12 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ public:
    // acmeChallenges is nullptr unless this listener should answer ACME HTTP-01 challenges
    // (see docs/ARCHITECTURE.md's Let's Encrypt section) -- typically only the plain-HTTP
    // listener on port 80 needs it.
    // idleTimeoutSeconds is forwarded straight to the libhttppp::HttpEvent base (see its own
    // doc comment in httpd.h) -- default 0 keeps today's behavior for any caller that doesn't
    // pass it explicitly; main.cpp's real call sites pass AppConfig::idleConnectionTimeoutSeconds.
    HttpProxyController(std::vector<netplus::socket *> serverSockets,
                         std::string listenerLabel,
                         bool tlsActive,
@@ -32,7 +35,8 @@ public:
                         auth::IAuthService &authService,
                         plugin::PluginManager &pluginManager,
                         lb::LoadBalancer &loadBalancer,
                         tls::AcmeChallengeStore *acmeChallenges = nullptr);
                         tls::AcmeChallengeStore *acmeChallenges = nullptr,
                         int idleTimeoutSeconds = 0);

    void RequestEvent(libhttppp::HttpRequest &curreq, const int tid, ULONG_PTR args) override;

@@ -74,6 +78,8 @@ private:
// from a worker thread after privileges have been dropped.
class HttpProxyServer {
public:
    // idleTimeoutSeconds: see HttpProxyController's own doc comment above -- threaded down
    // into the controller it constructs internally in run().
    HttpProxyServer(config::ListenerConfig listener,
                     std::string certPath,
                     std::string keyPath,
@@ -81,7 +87,8 @@ public:
                     auth::IAuthService &authService,
                     plugin::PluginManager &pluginManager,
                     lb::LoadBalancer &loadBalancer,
                     tls::AcmeChallengeStore *acmeChallenges = nullptr);
                     tls::AcmeChallengeStore *acmeChallenges = nullptr,
                     int idleTimeoutSeconds = 0);

    // SNI virtual hosting variant: certsByHostname carries one CertificateBundle per domain
    // sharing this listener (see ListenerConfig::tlsProfiles) instead of the single cert/key
@@ -92,7 +99,8 @@ public:
                     auth::IAuthService &authService,
                     plugin::PluginManager &pluginManager,
                     lb::LoadBalancer &loadBalancer,
                     tls::AcmeChallengeStore *acmeChallenges = nullptr);
                     tls::AcmeChallengeStore *acmeChallenges = nullptr,
                     int idleTimeoutSeconds = 0);

    void run();

@@ -119,6 +127,7 @@ private:
    plugin::PluginManager &_pluginManager;
    lb::LoadBalancer &_loadBalancer;
    tls::AcmeChallengeStore *_acmeChallenges;
    int _idleTimeoutSeconds;
};

} // namespace proxyplus::httpproxy
Loading