probe fallback: basic TCP/UDP connectivity when capture service is offline

This commit is contained in:
Zac Gaetano 2026-05-22 17:26:26 -04:00
parent 4864db03f3
commit ceceedf201

View file

@ -650,13 +650,13 @@ router.delete('/:id', async (req, res, next) => {
}
});
// POST /probe - Test source connectivity.
// Tries the capture service first (full SRT/RTMP handshake + metadata).
// Falls back to a basic TCP/UDP reachability check if capture is offline.
// POST /probe - Probe a source URL for reachability.
// Tries the capture service first; falls back to basic TCP/UDP connectivity
// check when capture is not running.
router.post('/probe', async (req, res) => {
const { source_type, url } = req.body || {};
// Try capture service first — it can do a real SRT/RTMP handshake
// Try the capture service first (5s timeout)
try {
const r = await fetch('http://capture:3001/capture/probe', {
method: 'POST',
@ -689,11 +689,15 @@ router.post('/probe', async (req, res) => {
const port = parseInt(parsed.port, 10) || (isUdp ? 9000 : 1935);
const reachable = await (isUdp ? probeUdp(host, port) : probeTcp(host, port));
return res.json({
reachable,
mode: 'basic',
note: `Capture service offline · ${isUdp ? 'UDP' : 'TCP'} connectivity check only`,
...(reachable ? { source: `${host}:${port}` } : { error: `${host}:${port} did not respond` }),
...(reachable
? { source: `${host}:${port}` }
: { error: `${host}:${port} did not respond` }
),
});
});
@ -719,13 +723,13 @@ function probeUdp(host, port) {
try { sock.close(); } catch (_) {}
resolve(ok);
};
// ICMP port-unreachable will fire sock.on('error') within ~100ms if nothing is listening
sock.on('error', () => finish(false));
sock.send(Buffer.alloc(16, 0), 0, 16, port, host, (err) => {
if (err) return finish(false);
// If no ICMP port-unreachable arrives within 2.5s, assume port is open
// No ICMP error after 2.5s → assume something is listening
setTimeout(() => finish(true), 2500);
});
// Hard timeout — give up after 5s regardless
setTimeout(() => finish(false), 5000);
});
}