const net = require('net'); const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); const probeTcpPort = (host, port, timeoutMs = 500) => new Promise(resolve => { const socket = net.createConnection({ host, port }, () => { socket.end(); resolve(true); }); socket.on('error', () => resolve(false)); socket.setTimeout(timeoutMs, () => { socket.destroy(); resolve(false); }); }); /** Something is accepting connections on this port. */ const isTcpPortBusy = (host, port) => probeTcpPort(host, port); /** True if we can bind — more reliable than connect probe before GDB Server starts. */ const canBindTcpPort = (host, port) => new Promise(resolve => { const server = net.createServer(); server.once('error', () => resolve(false)); server.listen({ host, port }, () => { server.close(() => resolve(true)); }); }); const waitUntilTcpPortFree = async (host, port, timeoutMs = 10000) => { const startedAt = Date.now(); while (Date.now() - startedAt < timeoutMs) { if ((await canBindTcpPort(host, port)) && !(await isTcpPortBusy(host, port))) { return; } await wait(200); } throw new Error( `TCP 포트 ${port}(${host})이 아직 사용 중입니다. JLinkGDBServerCL을 종료한 뒤 몇 초 기다려 주세요.` ); }; const assertTcpPortFree = async (host, port, label = 'RTT') => { if (await canBindTcpPort(host, port)) return; throw new Error( `${label} 포트 ${port}(${host})이 이미 사용 중입니다. Receiver/Transmitter를 Stop한 뒤 몇 초 기다리거나, 작업 관리자에서 JLinkGDBServerCL 프로세스를 종료하세요.` ); }; module.exports = { isTcpPortBusy, canBindTcpPort, waitUntilTcpPortFree, assertTcpPortFree, };