From aaaeec1efd58a4dc4d77822ae85bbffa72d2a372 Mon Sep 17 00:00:00 2001 From: Hemanth Date: Thu, 26 Jun 2025 23:43:39 +0530 Subject: [PATCH] rtsp client connection --- package.json | 1 + server/monitor-types/RtspMonitorType.js | 56 +++++++++++++++++++++++++ server/uptime-kuma-server.js | 2 + 3 files changed, 59 insertions(+) create mode 100644 server/monitor-types/RtspMonitorType.js diff --git a/package.json b/package.json index 97b7bc339..327be7598 100644 --- a/package.json +++ b/package.json @@ -133,6 +133,7 @@ "qs": "~6.10.4", "redbean-node": "~0.3.0", "redis": "~4.5.1", + "rtsp-client": "^1.4.5", "semver": "~7.5.4", "socket.io": "~4.8.0", "socket.io-client": "~4.8.0", diff --git a/server/monitor-types/RtspMonitorType.js b/server/monitor-types/RtspMonitorType.js new file mode 100644 index 000000000..bc4f57486 --- /dev/null +++ b/server/monitor-types/RtspMonitorType.js @@ -0,0 +1,56 @@ +const RTSPClient = require("rtsp-client"); +const { log, UP, DOWN } = require("../../src/util"); +class RtspMonitorType { + name = "rtsp"; + + /** + * @param {Object} monitor - monitor config containing rtspUrl and timeout + * @param {Object} heartbeat - object to update with status and message + */ + async check(monitor, heartbeat) { + const url = monitor.rtspUrl; + const timeoutMs = (monitor.timeout || 10) * 1000; + + heartbeat.status = DOWN; + heartbeat.msg = "Starting RTSP stream check..."; + + if (!url || !url.startsWith("rtsp://")) { + heartbeat.status = DOWN; + heartbeat.msg = "Invalid RTSP URL"; + return; + } + + const client = new RTSPClient(); + + // Timeout promise to kill hanging connections + const timeoutPromise = new Promise((_, reject) => + setTimeout(() => reject(new Error("RTSP connection timed out")), timeoutMs) + ); + + try { + // Use Promise.race to enforce timeout + await Promise.race([ + (async () => { + await client.connect(url); + const describe = await client.describe(); + await client.close(); + + heartbeat.status = UP; + heartbeat.msg = "RTSP stream is accessible"; + })(), + timeoutPromise, + ]); + } catch (error) { + heartbeat.status = DOWN; + heartbeat.msg = `Error: ${error.message}`; + log.debug("monitor", `[${monitor.name}] RTSP check failed: ${error.message}`); + try { + await client.close(); + } catch {} + } + } +} + +module.exports = { + RtspMonitorType, +}; diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index a04e6bd49..b410ae85a 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -119,6 +119,7 @@ class UptimeKumaServer { UptimeKumaServer.monitorTypeList["mongodb"] = new MongodbMonitorType(); UptimeKumaServer.monitorTypeList["rabbitmq"] = new RabbitMqMonitorType(); UptimeKumaServer.monitorTypeList["manual"] = new ManualMonitorType(); + UptimeKumaServer.monitorTypeList["rtsp"] = new RtspMonitorType(); // Allow all CORS origins (polling) in development let cors = undefined; @@ -560,4 +561,5 @@ const { SNMPMonitorType } = require("./monitor-types/snmp"); const { MongodbMonitorType } = require("./monitor-types/mongodb"); const { RabbitMqMonitorType } = require("./monitor-types/rabbitmq"); const { ManualMonitorType } = require("./monitor-types/manual"); +const {RtspMonitorType}= require("./monitor-types/RtspMonitorType") const Monitor = require("./model/monitor");