113 lines
4.1 KiB
TypeScript
113 lines
4.1 KiB
TypeScript
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);
|