/** * Ephemeral TCP/UDP fallback when bind/listen hits EADDRINUSE (see BARE_OS_BIND_FALLBACK). */ export const BARE_OS_BIND_FALLBACK_ENV = 'BARE_OS_BIND_FALLBACK' /** * When unset or truthy, retry with port `0` after EADDRINUSE. Set `0` / `false` for strict bind. * @param {Record | null | undefined} env */ export function bindFallbackEnabled(env) { if (!env || typeof env !== 'object') return true const v = env[BARE_OS_BIND_FALLBACK_ENV] if (v === '0' || v === 'false') return false return true } /** @param {unknown} err */ export function isAddrInUse(err) { const o = err && typeof err === 'object' ? err : null const code = o && (o.code || o.errno) if (code === 'EADDRINUSE') return true const msg = String((o && /** @type {{ message?: string }} */ (o).message) || err || '').toLowerCase() return msg.includes('eaddrinuse') || msg.includes('address already in use') } /** * @param {{ address?: () => unknown }} server * @param {number} fallback */ export function readListeningTcpPort(server, fallback) { try { const a = server.address && typeof server.address === 'function' ? server.address() : null if (a && typeof a === 'object' && Number.isFinite(/** @type {{ port?: number }} */ (a).port)) return Number(/** @type {{ port?: number }} */ (a).port) } catch { /* ignore */ } return fallback } /** * `listen(port, host, cb)` + `once('error')` / `off('error')` (net.Server / http.Server). * @param {{ listen: Function, address?: Function, once: Function, off: Function }} server * @param {number} preferredPort * @param {string} host * @param {Record | null | undefined} env * @returns {Promise<{ port: number }>} */ export async function listenTcpWithFallback(server, preferredPort, host, env) { const tryOnce = (port) => new Promise((resolve, reject) => { const onErr = (e) => { try { server.off('error', onErr) } catch { /* ignore */ } reject(e) } server.once('error', onErr) try { server.listen(port, host, () => { try { server.off('error', onErr) } catch { /* ignore */ } resolve(null) }) } catch (e) { try { server.off('error', onErr) } catch { /* ignore */ } reject(e) } }) try { await tryOnce(preferredPort) } catch (e) { if ( bindFallbackEnabled(env) && isAddrInUse(e) && preferredPort !== 0 ) { await tryOnce(0) } else { throw e } } const port = readListeningTcpPort(server, preferredPort) return { port } }