From 22a0ed6061006740486e4cae9971c666e0d1257a Mon Sep 17 00:00:00 2001 From: benji2k2 Date: Sat, 20 Dec 2025 10:26:13 +0100 Subject: [PATCH 1/2] fix(docker): handle the state "unhealthy" as `DOWN` instead of `PENDING` (#6292) Co-authored-by: Frank Elsinga --- server/model/monitor.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index eff8add94..d0f71e815 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -768,12 +768,14 @@ class Monitor extends BeanModel { let res = await axios.request(options); if (res.data.State.Running) { - if (res.data.State.Health && res.data.State.Health.Status !== "healthy") { - bean.status = PENDING; - bean.msg = res.data.State.Health.Status; - } else { + if (res.data.State.Health.Status === "healthy") { bean.status = UP; bean.msg = res.data.State.Health ? res.data.State.Health.Status : res.data.State.Status; + } else if (res.data.State.Health.Status === "unhealthy") { + throw Error("Container State is unhealthy"); + } else { + bean.status = PENDING; + bean.msg = res.data.State.Health.Status; } } else { throw Error("Container State is " + res.data.State.Status); From f3c76dbc6fa9ddac72ae631635a79f031c3517c4 Mon Sep 17 00:00:00 2001 From: Shaan Date: Sat, 20 Dec 2025 18:35:53 +0600 Subject: [PATCH 2/2] feat: Add XMPP dialog in STARTTLS routine (#6508) --- server/monitor-types/tcp.js | 41 ++++++++++++++++++++++++++++++----- test/backend-test/test-tcp.js | 22 +++++++++++++++++++ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/server/monitor-types/tcp.js b/server/monitor-types/tcp.js index e71973b1f..5223d2e25 100644 --- a/server/monitor-types/tcp.js +++ b/server/monitor-types/tcp.js @@ -54,12 +54,32 @@ class TCPMonitorType extends MonitorType { const preTLS = () => new Promise((resolve, reject) => { - let timeout; + let dialogTimeout; + let bannerTimeout; socket_ = net.connect(monitor.port, monitor.hostname); const onTimeout = () => { log.debug(this.name, `[${monitor.name}] Pre-TLS connection timed out`); - reject("Connection timed out"); + doReject("Connection timed out"); + }; + + const onBannerTimeout = () => { + log.debug(this.name, `[${monitor.name}] Pre-TLS timed out waiting for banner`); + // No banner. Could be a XMPP server? + socket_.write(``); + }; + + const doResolve = () => { + dialogTimeout && clearTimeout(dialogTimeout); + bannerTimeout && clearTimeout(bannerTimeout); + resolve({ socket: socket_ }); + }; + + const doReject = (error) => { + dialogTimeout && clearTimeout(dialogTimeout); + bannerTimeout && clearTimeout(bannerTimeout); + socket_.end(); + reject(error); }; socket_.on("connect", () => { @@ -70,10 +90,10 @@ class TCPMonitorType extends MonitorType { const response = data.toString(); const response_ = response.toLowerCase(); log.debug(this.name, `[${monitor.name}] Pre-TLS response: ${response}`); + clearTimeout(bannerTimeout); switch (true) { case response_.includes("start tls") || response_.includes("begin tls"): - timeout && clearTimeout(timeout); - resolve({ socket: socket_ }); + doResolve(); break; case response.startsWith("* OK") || response.match(/CAPABILITY.+STARTTLS/): socket_.write("a001 STARTTLS\r\n"); @@ -84,8 +104,16 @@ class TCPMonitorType extends MonitorType { case response.includes("250-STARTTLS"): socket_.write("STARTTLS\r\n"); break; + case response_.includes(""); + break; + case response_.includes(""): + break; default: - reject(`Unexpected response: ${response}`); + doReject(`Unexpected response: ${response}`); } }); socket_.on("error", error => { @@ -93,7 +121,8 @@ class TCPMonitorType extends MonitorType { reject(error); }); socket_.setTimeout(1000 * TIMEOUT, onTimeout); - timeout = setTimeout(onTimeout, 1000 * TIMEOUT); + dialogTimeout = setTimeout(onTimeout, 1000 * TIMEOUT); + bannerTimeout = setTimeout(onBannerTimeout, 1000 * 1.5); }); const reuseSocket = monitor.smtpSecurity === "starttls" ? await preTLS() : {}; diff --git a/test/backend-test/test-tcp.js b/test/backend-test/test-tcp.js index 46a4d12dd..98f168c24 100644 --- a/test/backend-test/test-tcp.js +++ b/test/backend-test/test-tcp.js @@ -185,4 +185,26 @@ describe("TCP Monitor", () => { regex ); }); + test("XMPP server with valid certificate (STARTTLS)", async t => { + const tcpMonitor = new TCPMonitorType(); + + const monitor = { + hostname: "xmpp.earth", + port: 5222, + smtpSecurity: "starttls", + isEnabledExpiryNotification: () => true, + handleTlsInfo: async tlsInfo => { + return tlsInfo; + }, + }; + + const heartbeat = { + msg: "", + status: PENDING, + }; + + await tcpMonitor.check(monitor, heartbeat, {}); + + assert.strictEqual(heartbeat.status, UP); + }); });