diff --git a/services/mam-api/src/routes/recorders.js b/services/mam-api/src/routes/recorders.js index 01e52ea..f233a46 100644 --- a/services/mam-api/src/routes/recorders.js +++ b/services/mam-api/src/routes/recorders.js @@ -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); }); }