This commit is contained in:
xiao.xiong
2025-10-19 23:46:41 +08:00
parent 7bbf6e6a18
commit 39a70de606
5 changed files with 394 additions and 0 deletions

113
server/src/lib.ts Normal file
View File

@@ -0,0 +1,113 @@
interface SipMessageConfig {
targetIp?: string;
targetPort?: number;
macLocalIp?: string;
senderSip?: string;
senderIp?: string;
receiverSip?: string;
receiverIp?: string;
}
export async function sendSipMessage(config: SipMessageConfig = {}): Promise<void> {
// 配置参数(使用默认值或传入的配置)
const targetIp = config.targetIp || "192.168.3.3"; // 设备eth1的IP转发入口
const targetPort = config.targetPort || 5060; // 转发端口
const macLocalIp = config.macLocalIp || "192.168.3.33"; // Mac的本地IP与Via头部一致
const senderSip = config.senderSip || "3011302"; // 发送方SIP用户
const senderIp = config.senderIp || "192.168.9.57"; // 设备eth0的IP转发后源IP
const receiverSip = config.receiverSip || "3019901"; // 接收方SIP用户
const receiverIp = config.receiverIp || "192.168.9.4"; // 目标IP
// 生成唯一标识
const callId = `${Math.floor(Date.now() / 1000)}`; // 基于时间戳的Call-ID
const tag = `${Math.floor(Date.now() % 1000000)}`; // 随机tag
const branch = `z9hG4bK${Math.floor(Date.now() / 1000)}`; // Via分支标识
// XML消息体业务数据
const xmlBody = `<?xml version="1.0" encoding="UTF-8" ?>
<params>
<to>sip:${receiverSip}@${receiverIp}:5060</to>
<elev>1</elev>
<direct>2</direct>
<floor>13</floor>
<family>2</family>
<app>elev</app>
<event>appoint</event>
<event_url>/elev/appoint</event_url>
</params>`;
// 计算消息体长度(使用字符串长度 + utf8编码估算
const contentLength = new TextEncoder().encode(xmlBody).length;
// 构造SIP MESSAGE请求严格使用\r\n换行
const sipMessage = `MESSAGE sip:${receiverSip}@${receiverIp}:5060 SIP/2.0\r\n` +
`Via: SIP/2.0/UDP ${macLocalIp}:5060;rport;branch=${branch}\r\n` +
`From: <sip:${senderSip}@${senderIp}:5060>;tag=${tag}\r\n` +
`To: <sip:${receiverSip}@${receiverIp}:5060>\r\n` +
`Call-ID: ${callId}@${macLocalIp}\r\n` +
`CSeq: 20 MESSAGE\r\n` +
`Content-Type: text/plain\r\n` +
`Max-Forwards: 70\r\n` +
`User-Agent: DnakeVoip v1.0\r\n` +
`Content-Length: ${contentLength}\r\n\r\n` +
`${xmlBody}`;
return new Promise((resolve, reject) => {
try {
console.log(`准备发送SIP消息到 ${targetIp}:${targetPort}`);
console.log('\n发送的消息内容');
console.log(sipMessage);
resolve();
} catch (error: any) {
console.log(`处理失败:${error.message}`);
reject(error);
}
});
}
// 使用默认配置的便捷函数
export function sendDefaultSipMessage(): Promise<void> {
return sendSipMessage();
}
// 使用Node.js原生dgram模块的实现需要@types/node
export function getSipMessageWithDgram(config: SipMessageConfig = {}): string {
const targetIp = config.targetIp || "192.168.3.3";
const macLocalIp = config.macLocalIp || "192.168.3.33";
const senderSip = config.senderSip || "3011302";
const senderIp = config.senderIp || "192.168.9.57";
const receiverSip = config.receiverSip || "3019901";
const receiverIp = config.receiverIp || "192.168.9.4";
const callId = `${Math.floor(Date.now() / 1000)}`;
const tag = `${Math.floor(Date.now() % 1000000)}`;
const branch = `z9hG4bK${Math.floor(Date.now() / 1000)}`;
const xmlBody = `<?xml version="1.0" encoding="UTF-8" ?>
<params>
<to>sip:${receiverSip}@${receiverIp}:5060</to>
<elev>1</elev>
<direct>2</direct>
<floor>13</floor>
<family>2</family>
<app>elev</app>
<event>appoint</event>
<event_url>/elev/appoint</event_url>
</params>`;
const contentLength = new TextEncoder().encode(xmlBody).length;
return `MESSAGE sip:${receiverSip}@${receiverIp}:5060 SIP/2.0\r\n` +
`Via: SIP/2.0/UDP ${macLocalIp}:5060;rport;branch=${branch}\r\n` +
`From: <sip:${senderSip}@${senderIp}:5060>;tag=${tag}\r\n` +
`To: <sip:${receiverSip}@${receiverIp}:5060>\r\n` +
`Call-ID: ${callId}@${macLocalIp}\r\n` +
`CSeq: 20 MESSAGE\r\n` +
`Content-Type: text/plain\r\n` +
`Max-Forwards: 70\r\n` +
`User-Agent: DnakeVoip v1.0\r\n` +
`Content-Length: ${contentLength}\r\n\r\n` +
`${xmlBody}`;
}
// sendDefaultSipMessage().catch(console.error);