

SIPp 是一款常用的 SIP 协议性能测试工具,uas.xml 是其内置的用户代理服务器(UAS)场景配置文件。本文将从基础使用、代理适配修改、主动发送 BYE 消息配置三个维度,详细讲解 uas.xml 的相关操作。
获取 uas.xml 并编写启动脚本
首先,通过 SIPp 内置命令可直接导出默认 uas.xml 配置文件,执行以下命令即可:
sipp -sd uas > uas.xml为了便捷启动 UAS 服务,我们可以编写一个启动脚本uas.sh,将启动参数固化其中。脚本内容如下,需根据实际环境修改 LOCAL_IP(本地 IP 地址)和 LOCAL_PORT(本地端口,默认 SIP 端口为 5060):
#!/bin/bash
# 配置本地IP和端口(需根据实际环境调整)
LOCAL_IP=192.168.1.100
LOCAL_PORT=5060
# 启动SIPp UAS服务,指定配置文件、本地IP和端口
sipp -sf uas.xml -i $LOCAL_IP -p $LOCAL_PORT脚本核心参数说明:
脚本编写完成后,需赋予执行权限并启动,命令如下:
# 赋予脚本执行权限
chmod +x uas.sh
# 启动 UAS
./uas.sh启动成功后,FreeSWITCH 可直接呼叫 SIPp 监听的 IP 和端口,进行基础的 SIP 呼叫压力测试。
进阶:修改 uas.xml 以便适配 Kamailio 代理呼叫
若需通过 Kamailio(SIP 代理程序)实现 FreeSWITCH 与 SIPp 的呼叫交互,需对默认 uas.xml 进行三处关键修改,确保 SIP 消息能正确通过代理传递。
修改编码格式(支持中文注释)
默认 uas.xml 第一行编码为`ISO-8859-1`,不支持中文注释。将其修改为 `UTF-8` 编码,方便后续添加中文说明:
原内容:
<?xml version="1.0" encoding="ISO-8859-1" ?>修改后:
<?xml version="1.0" encoding="UTF-8" ?>接收 INVITE 消息时启用路由集保存
SIP 代理场景下,需保存路由集(Route Sets)以确保后续响应消息能正确回传给代理。找到接收 INVITE 消息的配置段,添加 rrs="true" 参数(rrs 即 Record Route Sets):
原内容:
<recv request="INVITE" crlf="true">
</recv>修改后:
<recv request="INVITE" crlf="true" rrs="true">
</recv>说明:启用 rrs="true" 后,SIPp 会保存接收消息中的路由信息,用于后续发送响应/请求时使用,适配有状态 SIP 代理场景。
响应消息中添加 Record-Route 头域
Record-Route 头域用于记录呼叫路径,确保后续消息(如 BYE)能沿原路径回传。需在 180 Ringing 和 200 OK 两个响应消息中添加 `[last_Record-Route:]` 占位符(自动复用接收消息中的 Record-Route 信息)。
原内容:
<send>
<![CDATA[
SIP/2.0 180 Ringing
[last_Via:]
[last_From:]
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Length: 0
]]>
</send>修改后(添加 [last_Record-Route:]):
<send>
<![CDATA[
SIP/2.0 180 Ringing
[last_Via:]
[last_From:]
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_Call-ID:]
[last_CSeq:]
[last_Record-Route:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Length: 0
]]>
</send>原内容:
<send retrans="500">
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
[last_From:]
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Type: application/sdp
Content-Length: [len]
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=ptime:20
]]>
</send>修改后(添加 [last_Record-Route:]):
<send retrans="500">
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
[last_From:]
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_Call-ID:]
[last_CSeq:]
[last_Record-Route:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Type: application/sdp
Content-Length: [len]
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=ptime:20
]]>
</send>适配代理的 uas.xml 完整内容
整合上述修改后,完整的 uas.xml 如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<!-- This program is free software; you can redistribute it and/or -->
<!-- modify it under the terms of the GNU General Public License as -->
<!-- published by the Free Software Foundation; either version 2 of the -->
<!-- License, or (at your option) any later version. -->
<!-- -->
<!-- This program is distributed in the hope that it will be useful, -->
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
<!-- GNU General Public License for more details. -->
<!-- -->
<!-- You should have received a copy of the GNU General Public License -->
<!-- along with this program; if not, write to the -->
<!-- Free Software Foundation, Inc., -->
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
<!-- -->
<!-- Sipp default 'uas' scenario. -->
<!-- -->
<scenario name="Basic UAS responder">
<!-- By adding rrs="true" (Record Route Sets), the route sets -->
<!-- are saved and used for following messages sent. Useful to test -->
<!-- against stateful SIP proxies/B2BUAs. -->
<!-- Adding ignoresdp="true" here would ignore the SDP data: that -->
<!-- can be useful if you want to reject reINVITEs and keep the -->
<!-- media stream flowing. -->
<recv request="INVITE" crlf="true" rrs="true">
</recv>
<!-- The '[last_*]' keyword is replaced automatically by the -->
<!-- specified header if it was present in the last message received -->
<!-- (except if it was a retransmission). If the header was not -->
<!-- present or if no message has been received, the '[last_*]' -->
<!-- keyword is discarded, and all bytes until the end of the line -->
<!-- are also discarded. -->
<!-- -->
<!-- If the specified header was present several times in the -->
<!-- message, all occurrences are concatenated (CRLF separated) -->
<!-- to be used in place of the '[last_*]' keyword. -->
<send>
<![CDATA[
SIP/2.0 180 Ringing
[last_Via:]
[last_From:]
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_Call-ID:]
[last_CSeq:]
[last_Record-Route:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Length: 0
]]>
</send>
<send retrans="500">
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
[last_Record-Route:]
[last_From:]
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_Call-ID:]
[last_CSeq:]
[last_Record-Route:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Type: application/sdp
Content-Length: [len]
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000
]]>
</send>
<recv request="ACK"
optional="true"
rtd="true"
crlf="true">
</recv>
<recv request="BYE">
</recv>
<send>
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
[last_From:]
[last_To:]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Length: 0
]]>
</send>
<!-- Keep the call open for a while in case the 200 is lost to be -->
<!-- able to retransmit it if we receive the BYE again. -->
<timewait milliseconds="4000"/>
<!-- definition of the response time repartition table (unit is ms) -->
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
<!-- definition of the call length repartition table (unit is ms) -->
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
</scenario>uas_send_bye.xml 实现 SIPp 主动发送 BYE
默认 uas.xml 中,SIPp 作为 UAS 被动接收主叫发送的 BYE 消息。若需让 SIPp 主动发起挂断(即主动发送 BYE 消息),可创建uas_send_bye.xml 配置文件,核心逻辑是:接收 ACK 消息后,提取呼叫信息,主动构造并发送 BYE 消息。
核心修改说明
相较于适配代理的 uas.xml,uas_send_bye.xml 主要增加/修改了以下部分:
uas_send_bye.xml 完整内容:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<!-- This program is free software; you can redistribute it and/or -->
<!-- modify it under the terms of the GNU General Public License as -->
<!-- published by the Free Software Foundation; either version 2 of the -->
<!-- License, or (at your option) any later version. -->
<!-- -->
<!-- This program is distributed in the hope that it will be useful, -->
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
<!-- GNU General Public License for more details. -->
<!-- -->
<!-- You should have received a copy of the GNU General Public License -->
<!-- along with this program; if not, write to the -->
<!-- Free Software Foundation, Inc., -->
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
<!-- -->
<!-- Sipp default 'uas' scenario. -->
<!-- -->
<scenario name="Basic UAS responder">
<!-- By adding rrs="true" (Record Route Sets), the route sets -->
<!-- are saved and used for following messages sent. Useful to test -->
<!-- against stateful SIP proxies/B2BUAs. -->
<!-- Adding ignoresdp="true" here would ignore the SDP data: that -->
<!-- can be useful if you want to reject reINVITEs and keep the -->
<!-- media stream flowing. -->
<recv request="INVITE" crlf="true" rrs="true">
</recv>
<!-- The '[last_*]' keyword is replaced automatically by the -->
<!-- specified header if it was present in the last message received -->
<!-- (except if it was a retransmission). If the header was not -->
<!-- present or if no message has been received, the '[last_*]' -->
<!-- keyword is discarded, and all bytes until the end of the line -->
<!-- are also discarded. -->
<!-- -->
<!-- If the specified header was present several times in the -->
<!-- message, all occurrences are concatenated (CRLF separated) -->
<!-- to be used in place of the '[last_*]' keyword. -->
<send>
<![CDATA[
SIP/2.0 180 Ringing
[last_Via:]
[last_From:]
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_Call-ID:]
[last_CSeq:]
[last_Record-Route:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Length: 0
]]>
</send>
<send retrans="500">
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
[last_Record-Route:]
[last_From:]
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_Call-ID:]
[last_CSeq:]
[last_Record-Route:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Type: application/sdp
Content-Length: [len]
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000
]]>
</send>
<recv request="ACK" rrs="true">
<action>
<ereg regexp=": *(.*)" search_in="hdr" header="To" assign_to="_,us"/><!-- with tag -->
<ereg regexp=": *(.*)" search_in="hdr" header="From" assign_to="_,them"/>
</action>
</recv>
<Reference variables="_"/>
<pause/>
<send start_txn="bye" retrans="500">
<![CDATA[
BYE [next_url] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
[routes]
From: [$us]
To: [$them]
[last_Call-ID:]
CSeq: [cseq] BYE
Contact: sip:[service]@[local_ip]:[local_port]
Content-Length: 0
]]>
</send>
<recv response="200" response_txn="bye"/>
<!-- definition of the response time repartition table (unit is ms) -->
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
<!-- definition of the call length repartition table (unit is ms) -->
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
</scenario>关键说明:
编写(或者修改) 自己的 XML scenarios 有一个很大的好处就是可以熟悉 SIP 规范。
本文分享自 FreeSWITCH中文社区 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!