Full-featured SIP router with multi-provider trunking, browser softphone via WebRTC, real-time Opus/G.722/PCM transcoding in Rust, RNNoise ML noise suppression, Kokoro neural TTS announcements, and a Lit-based web dashboard with live call monitoring and REST API.
72 lines
2.0 KiB
TypeScript
72 lines
2.0 KiB
TypeScript
/**
|
|
* Unified RTP port pool — replaces the three separate allocators
|
|
* in sipproxy.ts, calloriginator.ts, and webrtcbridge.ts.
|
|
*
|
|
* Allocates even-numbered UDP ports from a configured range.
|
|
* Each allocation binds a dgram socket and returns it ready to use.
|
|
*/
|
|
|
|
import dgram from 'node:dgram';
|
|
|
|
export interface IRtpAllocation {
|
|
port: number;
|
|
sock: dgram.Socket;
|
|
}
|
|
|
|
export class RtpPortPool {
|
|
private min: number;
|
|
private max: number;
|
|
private allocated = new Map<number, dgram.Socket>();
|
|
private log: (msg: string) => void;
|
|
|
|
constructor(min: number, max: number, log: (msg: string) => void) {
|
|
this.min = min % 2 === 0 ? min : min + 1; // ensure even start
|
|
this.max = max;
|
|
this.log = log;
|
|
}
|
|
|
|
/**
|
|
* Allocate an even-numbered port and bind a UDP socket to it.
|
|
* Returns null if the pool is exhausted.
|
|
*/
|
|
allocate(): IRtpAllocation | null {
|
|
for (let port = this.min; port < this.max; port += 2) {
|
|
if (this.allocated.has(port)) continue;
|
|
|
|
const sock = dgram.createSocket('udp4');
|
|
try {
|
|
sock.bind(port, '0.0.0.0');
|
|
} catch {
|
|
try { sock.close(); } catch { /* ignore */ }
|
|
continue;
|
|
}
|
|
this.allocated.set(port, sock);
|
|
this.log(`[rtp-pool] allocated port ${port} (${this.allocated.size} in use)`);
|
|
return { port, sock };
|
|
}
|
|
this.log('[rtp-pool] WARN: port pool exhausted');
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Release a port back to the pool and close its socket.
|
|
*/
|
|
release(port: number): void {
|
|
const sock = this.allocated.get(port);
|
|
if (!sock) return;
|
|
try { sock.close(); } catch { /* ignore */ }
|
|
this.allocated.delete(port);
|
|
this.log(`[rtp-pool] released port ${port} (${this.allocated.size} in use)`);
|
|
}
|
|
|
|
/** Number of currently allocated ports. */
|
|
get size(): number {
|
|
return this.allocated.size;
|
|
}
|
|
|
|
/** Total capacity (number of even ports in range). */
|
|
get capacity(): number {
|
|
return Math.floor((this.max - this.min) / 2);
|
|
}
|
|
}
|