From c40f8e7ba5a4c73f3c5cdc897f64c7f79a4c092d Mon Sep 17 00:00:00 2001 From: Eddie Fiorentine Date: Tue, 19 Nov 2024 19:40:23 -0500 Subject: [PATCH 1/5] Feature: SIP options ping Monitor Type using sipsak binary --- server/monitor-types/sip-options.js | 61 +++++++++++++++++++++++++++++ server/uptime-kuma-server.js | 4 +- src/lang/en.json | 1 + src/pages/EditMonitor.vue | 17 +++++--- 4 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 server/monitor-types/sip-options.js diff --git a/server/monitor-types/sip-options.js b/server/monitor-types/sip-options.js new file mode 100644 index 000000000..fc0bbff7e --- /dev/null +++ b/server/monitor-types/sip-options.js @@ -0,0 +1,61 @@ +const { MonitorType } = require("./monitor-type"); +const { UP, log } = require("../../src/util"); +const { exec } = require("promisify-child-process"); + +class SIPMonitorType extends MonitorType { + name = "sip-options"; + supportsConditions = false; + + /** + * Run the monitoring check on the given monitor + * @param {Monitor} monitor Monitor to check + * @param {Heartbeat} heartbeat Monitor heartbeat to update + * @param {UptimeKumaServer} server Uptime Kuma server + * @returns {Promise} + */ + async check(monitor, heartbeat, _server) { + try { + let sipsakOutput = await this.runSipSak(monitor.hostname, monitor.port, 3000); + this.parseSipsakResponse(sipsakOutput, heartbeat); + } catch (err) { + throw new Error(`Error checking Sipsak: ${err} ${err.message} ${err.stack}`); + } + } + + /** + * Runs Sipsak options ping + * @param {string} hostname SIP server address to send options. + * @param {number} timeout timeout of options reply + * @returns {Promise} A Promise that resolves to the output of the Sipsak options ping + * @throws Will throw an error if the command execution encounters any error. + */ + async runSipSak(hostname, port, timeout) { + const { stdout, stderr } = await exec(`sipsak -s sip:${hostname}:${port} --from sip:sipsak@${hostname} -v`,{timeout:timeout}); + if (stderr){ + console.error(`Error in stderr: ${stderr.toString()}`); + } + if (!stdout && stderr && stderr.toString()) { + throw new Error(`Error in output: ${stderr.toString()}`); + } + if (stdout && stdout.toString()) { + return stdout.toString(); + } else { + throw new Error("No output from sipsak"); + } + } + + parseSipsakResponse(res, heartbeat){ + let lines = res.split("\n"); + for (let line of lines){ + if (line.includes("200 OK")){ + heartbeat.status = UP; + heartbeat.msg = line; + break; + } + } + } +} + +module.exports = { + SIPMonitorType, +}; diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index 062f098d7..63102ea04 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -116,6 +116,7 @@ class UptimeKumaServer { UptimeKumaServer.monitorTypeList["snmp"] = new SNMPMonitorType(); UptimeKumaServer.monitorTypeList["mongodb"] = new MongodbMonitorType(); UptimeKumaServer.monitorTypeList["rabbitmq"] = new RabbitMqMonitorType(); + UptimeKumaServer.monitorTypeList["sip-options"] = new SIPMonitorType(); // Allow all CORS origins (polling) in development let cors = undefined; @@ -554,4 +555,5 @@ const { MqttMonitorType } = require("./monitor-types/mqtt"); const { SNMPMonitorType } = require("./monitor-types/snmp"); const { MongodbMonitorType } = require("./monitor-types/mongodb"); const { RabbitMqMonitorType } = require("./monitor-types/rabbitmq"); -const Monitor = require("./model/monitor"); +const Monitor = require("./model/monitor");const { SIPMonitorType } = require("./monitor-types/sip-options"); + diff --git a/src/lang/en.json b/src/lang/en.json index e215f1031..911bacfbf 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -405,6 +405,7 @@ "socket": "Socket", "tcp": "TCP / HTTP", "tailscalePingWarning": "In order to use the Tailscale Ping monitor, you need to install Uptime Kuma without Docker and also install Tailscale client on your server.", + "sipsakPingWarning": "In order to use the SIP Options Ping monitor, you need to install Uptime Kuma without Docker and also install Sipsak client on your server.", "Docker Container": "Docker Container", "Container Name / ID": "Container Name / ID", "Docker Host": "Docker Host", diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index a83f91cab..b8334458f 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -88,9 +88,12 @@ + + @@ -106,6 +109,10 @@ {{ $t("tailscalePingWarning") }} + +
@@ -281,8 +288,8 @@ - -
+ +
- -
+ +
From 783e228406806b0f479c566f0945ee6648585fcc Mon Sep 17 00:00:00 2001 From: Eddie Fiorentine Date: Tue, 19 Nov 2024 19:42:45 -0500 Subject: [PATCH 2/5] fix: SIP Options monitor would always write an error to log because sipsak by default writes DEBUG to stderr --- server/monitor-types/sip-options.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/server/monitor-types/sip-options.js b/server/monitor-types/sip-options.js index fc0bbff7e..99b75e415 100644 --- a/server/monitor-types/sip-options.js +++ b/server/monitor-types/sip-options.js @@ -31,9 +31,6 @@ class SIPMonitorType extends MonitorType { */ async runSipSak(hostname, port, timeout) { const { stdout, stderr } = await exec(`sipsak -s sip:${hostname}:${port} --from sip:sipsak@${hostname} -v`,{timeout:timeout}); - if (stderr){ - console.error(`Error in stderr: ${stderr.toString()}`); - } if (!stdout && stderr && stderr.toString()) { throw new Error(`Error in output: ${stderr.toString()}`); } From 5cff54e52d3ebcb375429867fa5bd914db971b9e Mon Sep 17 00:00:00 2001 From: Eddie Fiorentine Date: Tue, 19 Nov 2024 19:52:37 -0500 Subject: [PATCH 3/5] fix: cleanup JSdocs --- server/monitor-types/sip-options.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/server/monitor-types/sip-options.js b/server/monitor-types/sip-options.js index 99b75e415..1ca60ad22 100644 --- a/server/monitor-types/sip-options.js +++ b/server/monitor-types/sip-options.js @@ -12,6 +12,7 @@ class SIPMonitorType extends MonitorType { * @param {Heartbeat} heartbeat Monitor heartbeat to update * @param {UptimeKumaServer} server Uptime Kuma server * @returns {Promise} + * @throws Will throw an error if the command execution encounters any error. */ async check(monitor, heartbeat, _server) { try { @@ -25,6 +26,7 @@ class SIPMonitorType extends MonitorType { /** * Runs Sipsak options ping * @param {string} hostname SIP server address to send options. + * @param {number} port SIP server port * @param {number} timeout timeout of options reply * @returns {Promise} A Promise that resolves to the output of the Sipsak options ping * @throws Will throw an error if the command execution encounters any error. @@ -41,6 +43,12 @@ class SIPMonitorType extends MonitorType { } } + /** + * + * @param {string} res + * @param {object} heartbeat + * @returns {void} + */ parseSipsakResponse(res, heartbeat){ let lines = res.split("\n"); for (let line of lines){ From e5477fba0d1d59dadfa43384ff0009ff530821aa Mon Sep 17 00:00:00 2001 From: Eddie Fiorentine Date: Tue, 19 Nov 2024 19:55:18 -0500 Subject: [PATCH 4/5] add newline --- server/uptime-kuma-server.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index 63102ea04..41d9a1c46 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -555,5 +555,6 @@ const { MqttMonitorType } = require("./monitor-types/mqtt"); const { SNMPMonitorType } = require("./monitor-types/snmp"); const { MongodbMonitorType } = require("./monitor-types/mongodb"); const { RabbitMqMonitorType } = require("./monitor-types/rabbitmq"); -const Monitor = require("./model/monitor");const { SIPMonitorType } = require("./monitor-types/sip-options"); +const { SIPMonitorType } = require("./monitor-types/sip-options"); +const Monitor = require("./model/monitor"); From b40dbf7db76421da29242b1553522485afa5d4ec Mon Sep 17 00:00:00 2001 From: Eddie Fiorentine Date: Tue, 19 Nov 2024 20:13:06 -0500 Subject: [PATCH 5/5] lint fixes --- server/monitor-types/sip-options.js | 21 ++++++++++----------- src/pages/EditMonitor.vue | 2 +- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/server/monitor-types/sip-options.js b/server/monitor-types/sip-options.js index 1ca60ad22..0237ed890 100644 --- a/server/monitor-types/sip-options.js +++ b/server/monitor-types/sip-options.js @@ -1,5 +1,5 @@ const { MonitorType } = require("./monitor-type"); -const { UP, log } = require("../../src/util"); +const { UP } = require("../../src/util"); const { exec } = require("promisify-child-process"); class SIPMonitorType extends MonitorType { @@ -10,7 +10,7 @@ class SIPMonitorType extends MonitorType { * Run the monitoring check on the given monitor * @param {Monitor} monitor Monitor to check * @param {Heartbeat} heartbeat Monitor heartbeat to update - * @param {UptimeKumaServer} server Uptime Kuma server + * @param {UptimeKumaServer} _server Uptime Kuma server * @returns {Promise} * @throws Will throw an error if the command execution encounters any error. */ @@ -32,7 +32,7 @@ class SIPMonitorType extends MonitorType { * @throws Will throw an error if the command execution encounters any error. */ async runSipSak(hostname, port, timeout) { - const { stdout, stderr } = await exec(`sipsak -s sip:${hostname}:${port} --from sip:sipsak@${hostname} -v`,{timeout:timeout}); + const { stdout, stderr } = await exec(`sipsak -s sip:${hostname}:${port} --from sip:sipsak@${hostname} -v`, { timeout: timeout }); if (!stdout && stderr && stderr.toString()) { throw new Error(`Error in output: ${stderr.toString()}`); } @@ -44,22 +44,21 @@ class SIPMonitorType extends MonitorType { } /** - * - * @param {string} res - * @param {object} heartbeat - * @returns {void} + * @param {string} res response to be parsed + * @param {object} heartbeat heartbeat object to update + * @returns {void} returns nothing */ - parseSipsakResponse(res, heartbeat){ + parseSipsakResponse(res, heartbeat) { let lines = res.split("\n"); - for (let line of lines){ - if (line.includes("200 OK")){ + for (let line of lines) { + if (line.includes("200 OK")) { heartbeat.status = UP; heartbeat.msg = line; break; } } } -} +} module.exports = { SIPMonitorType, diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index b8334458f..211cba56e 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -93,7 +93,7 @@ +