101 lines
3.0 KiB
JavaScript
101 lines
3.0 KiB
JavaScript
/**
|
|
* Optional SCM_RIGHTS-style logical FD duplication for the POSIX socket FD bridge
|
|
* (`BARE_OS_POSIX_SOCKET_SCM_RIGHTS=1`). See docs/reference/syscall-socket-contract.md.
|
|
*/
|
|
|
|
/**
|
|
* @param {Record<string, string | undefined>} env
|
|
*/
|
|
export function wantPosixSocketScmRights(env) {
|
|
const v = String(env?.BARE_OS_POSIX_SOCKET_SCM_RIGHTS ?? '')
|
|
.trim()
|
|
.toLowerCase()
|
|
return v === '1' || v === 'true'
|
|
}
|
|
|
|
/**
|
|
* @param {Record<string, string | undefined>} env
|
|
*/
|
|
export function bareOsScmRightsMaxFds(env) {
|
|
const raw = String(env?.BARE_OS_POSIX_SOCKET_SCM_RIGHTS_MAX_FDS ?? '').trim()
|
|
const n = Math.floor(Number(raw))
|
|
if (Number.isFinite(n) && n > 0) return Math.min(16, n)
|
|
return 4
|
|
}
|
|
|
|
/**
|
|
* @param {unknown[]} arr
|
|
* @returns {number[] | null}
|
|
*/
|
|
function collectFdsFromCmsgList(arr) {
|
|
/** @type {number[]} */
|
|
const fds = []
|
|
for (const item of arr) {
|
|
if (!item || typeof item !== 'object') return null
|
|
const o = /** @type {Record<string, unknown>} */ (item)
|
|
if (!Array.isArray(o.fds)) return null
|
|
for (const f of o.fds) {
|
|
const n = Number(f)
|
|
if (!Number.isFinite(n) || n < 0) return null
|
|
fds.push(n >>> 0)
|
|
}
|
|
}
|
|
return fds
|
|
}
|
|
|
|
/**
|
|
* @param {Record<string, unknown>} args
|
|
* @param {boolean} scmOn
|
|
* @param {number} maxFds
|
|
* @returns {{ ok: true, fds: number[] } | { ok: false, reject: string }}
|
|
*/
|
|
export function bareOsParseSendmsgScmRights(args, scmOn, maxFds) {
|
|
if (!args || typeof args !== 'object')
|
|
return { ok: true, fds: [] }
|
|
const ctl = args.control
|
|
if (ctl instanceof Uint8Array && ctl.byteLength > 0)
|
|
return { ok: false, reject: 'control' }
|
|
const clen = Number(args.controllen)
|
|
if (Number.isFinite(clen) && clen > 0)
|
|
return { ok: false, reject: 'controllen' }
|
|
const mh = args.msgHdr
|
|
if (mh && typeof mh === 'object') {
|
|
const mhc = /** @type {Record<string, unknown>} */ (mh).control
|
|
if (mhc instanceof Uint8Array && mhc.byteLength > 0)
|
|
return { ok: false, reject: 'msgHdr.control' }
|
|
}
|
|
|
|
/** @type {number[]} */
|
|
let fds = []
|
|
if (Array.isArray(args.cmsgs) && args.cmsgs.length > 0) {
|
|
const r = collectFdsFromCmsgList(args.cmsgs)
|
|
if (r === null) return { ok: false, reject: 'cmsgs' }
|
|
fds = fds.concat(r)
|
|
}
|
|
if (mh && typeof mh === 'object') {
|
|
const c2 = /** @type {Record<string, unknown>} */ (mh).cmsgs
|
|
if (Array.isArray(c2) && c2.length > 0) {
|
|
const r = collectFdsFromCmsgList(c2)
|
|
if (r === null) return { ok: false, reject: 'msgHdr.cmsgs' }
|
|
fds = fds.concat(r)
|
|
}
|
|
}
|
|
|
|
if (fds.length > maxFds) return { ok: false, reject: 'cmsgs_cap' }
|
|
if (!scmOn && fds.length > 0) return { ok: false, reject: 'cmsgs' }
|
|
return { ok: true, fds }
|
|
}
|
|
|
|
/**
|
|
* @param {unknown} slot
|
|
* @param {string} k decimal fd string
|
|
*/
|
|
export function bareOsEnsureSocketSlotAliasKeys(slot, k) {
|
|
if (!slot || typeof slot !== 'object') return
|
|
const s = /** @type {{ aliasKeys?: Set<string> }} */ (slot)
|
|
if (!s.aliasKeys || !(s.aliasKeys instanceof Set)) {
|
|
s.aliasKeys = new Set()
|
|
}
|
|
s.aliasKeys.add(k)
|
|
}
|