Files
dnake/server/src/lib.ts
xiao.xiong 39a70de606 update
2025-10-19 23:46:41 +08:00

113 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);