Files
bare-operating-system/packages/bare-os-booter/test.bare-os-bind-fallback.js
T
Raven Scott 80485468f0 feat(booter): ephemeral port fallback on EADDRINUSE
Retry listen(0)/bind(0) when the preferred port is taken, gated by
BARE_OS_BIND_FALLBACK (default on; set 0/false for strict bind).

- Add lib/bare-os-bind-fallback.js and use it from bare-os-www-initd and
  bare-openssh (including privilege-path + holesail actual port).
- POSIX socket bridge in index.js: TCP listen and UDP bind fallbacks.
- bare-holesail + bare-holesail-managed: retry Holesail ready(); persist
  resolved listen port in managed state when it changes.
- Add test.bare-os-bind-fallback.js.
2026-04-23 20:39:50 -04:00

67 lines
1.9 KiB
JavaScript

import test from 'brittle'
import net from 'node:net'
import {
bindFallbackEnabled,
isAddrInUse,
listenTcpWithFallback,
readListeningTcpPort,
BARE_OS_BIND_FALLBACK_ENV
} from './lib/bare-os-bind-fallback.js'
test('bindFallbackEnabled', (t) => {
t.ok(bindFallbackEnabled({}))
t.ok(bindFallbackEnabled({ [BARE_OS_BIND_FALLBACK_ENV]: '1' }))
t.absent(bindFallbackEnabled({ [BARE_OS_BIND_FALLBACK_ENV]: '0' }))
t.absent(bindFallbackEnabled({ [BARE_OS_BIND_FALLBACK_ENV]: 'false' }))
})
test('isAddrInUse', (t) => {
t.ok(isAddrInUse(Object.assign(new Error('x'), { code: 'EADDRINUSE' })))
t.absent(isAddrInUse(Object.assign(new Error('x'), { code: 'ENOENT' })))
t.ok(isAddrInUse(new Error('listen EADDRINUSE: address already in use')))
})
test('listenTcpWithFallback picks ephemeral when preferred port busy', async (t) => {
const hog = net.createServer()
await new Promise((resolve, reject) => {
hog.once('error', reject)
hog.listen(0, '127.0.0.1', resolve)
})
const hogPort = readListeningTcpPort(hog, 0)
t.ok(Number.isFinite(hogPort) && hogPort > 0)
const srv = net.createServer()
const { port } = await listenTcpWithFallback(
srv,
hogPort,
'127.0.0.1',
{}
)
t.not(port, hogPort)
t.ok(port > 0)
await new Promise((resolve) => srv.close(resolve))
await new Promise((resolve) => hog.close(resolve))
})
test('listenTcpWithFallback strict env rethrows EADDRINUSE', async (t) => {
const hog = net.createServer()
await new Promise((resolve, reject) => {
hog.once('error', reject)
hog.listen(0, '127.0.0.1', resolve)
})
const hogPort = readListeningTcpPort(hog, 0)
const srv = net.createServer()
try {
await listenTcpWithFallback(srv, hogPort, '127.0.0.1', {
[BARE_OS_BIND_FALLBACK_ENV]: '0'
})
t.fail('expected EADDRINUSE')
} catch (e) {
t.ok(isAddrInUse(e))
}
await new Promise((resolve) => hog.close(resolve))
})