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.
55 lines
1.5 KiB
TypeScript
55 lines
1.5 KiB
TypeScript
/**
|
|
* SIP URI and SDP body rewriting helpers.
|
|
*/
|
|
|
|
import type { IEndpoint } from './types.ts';
|
|
|
|
const SIP_URI_RE = /(sips?:)([^@>;,\s]+@)?([^>;,\s:]+)(:\d+)?/g;
|
|
|
|
/**
|
|
* Replaces the host:port in every `sip:` / `sips:` URI found in `value`.
|
|
*/
|
|
export function rewriteSipUri(value: string, host: string, port: number): string {
|
|
return value.replace(SIP_URI_RE, (_m, scheme: string, userpart?: string) =>
|
|
`${scheme}${userpart || ''}${host}:${port}`);
|
|
}
|
|
|
|
/**
|
|
* Rewrites the connection address (`c=`) and audio media port (`m=audio`)
|
|
* in an SDP body. Returns the rewritten body together with the original
|
|
* endpoint that was replaced (if any).
|
|
*/
|
|
export function rewriteSdp(
|
|
body: string,
|
|
ip: string,
|
|
port: number,
|
|
): { body: string; original: IEndpoint | null } {
|
|
let origAddr: string | null = null;
|
|
let origPort: number | null = null;
|
|
|
|
const out = body
|
|
.replace(/\r\n/g, '\n')
|
|
.split('\n')
|
|
.map((line) => {
|
|
if (line.startsWith('c=IN IP4 ')) {
|
|
origAddr = line.slice('c=IN IP4 '.length).trim();
|
|
return `c=IN IP4 ${ip}`;
|
|
}
|
|
if (line.startsWith('m=audio ')) {
|
|
const parts = line.split(' ');
|
|
if (parts.length >= 2) {
|
|
origPort = parseInt(parts[1], 10);
|
|
parts[1] = String(port);
|
|
}
|
|
return parts.join(' ');
|
|
}
|
|
return line;
|
|
})
|
|
.join('\r\n');
|
|
|
|
return {
|
|
body: out,
|
|
original: origAddr && origPort ? { address: origAddr, port: origPort } : null,
|
|
};
|
|
}
|