若無法透過遠端解決,常需要在本地端進行分析
常用的方式是請客戶抓包,再用wireshark 去解析.
但若看不出所以然,就需要去模擬客戶的行為.
sipp是一個蠻簡單的工具,可以去模擬UAC 或 UAS的行為.
把需要的scenario, header等寫入script ,再去執行即可.
安裝和基本教學在官網裏有詳細的介紹,這裏就不多說了.
http://sipp.sourceforge.net/
底下是以sipp模擬UAC,也就是一般俗稱的CALLER(發話端)
命令如下:
sipp [remote_ip]:[remote_port] -i [local_ip] -p [local_port] -s [service] -sf xxx.xml -l 1
其中 remote_ip為受話IP,可以是SIP SERVER,或CALLEE(受話端)
local ip則為 UAC本身的ip
-s 則為UAC的電話號碼
-sf 則為 script file,
-l 1 指的是執行一次.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- Start Register -->
<!-- usage: sipp [remote_ip]:[remote_port] -i [local_ip] -p [local_port] -s [service] -sf xxx.xml -l 1 -->
<!-- usage: sipp 10.10.10.100:5060 -i 10.10.10.100 -p 5061 -s 5422818 -sf UAC_BasicCaller.xml -r 1 -m 1-->
<scenario name="BasicCaller">
<send>
<![CDATA[
INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/UDP [local_ip]:[local_port];branch=[branch]
From: <sip:7010@[local_ip]:[local_port]>;tag=[call_number]
To: <sip:[service]@[remote_ip]:[remote_port]>
Call-ID: [call_id]
CSeq: [cseq] INVITE
Contact: <sip:7010@[local_ip]:[local_port]>
Max-Forwards: 70
User-Agent: fredspqa
Content-Type: application/sdp
Content-Length: [len]
v=0
o=SIPP 31094920 31094920 IN IP4 [local_ip]
s=Session
c=IN IP4 [local_ip]
t=0 0
m=audio 33302 RTP/AVP 8
a=rtpmap:8 PCMA/8000
]]>
</send>
<recv response="100" rtd="true">
</recv>
<recv response="180" optional="true">
</recv>
<recv response="183" optional="true">
</recv>
<recv response="200" rtd="true">
<action>
<ereg regexp=".*" search_in="hdr" header="To:" assign_to="2"/>
<ereg regexp=".*" search_in="hdr" header="From:" assign_to="3"/>
<ereg regexp=".*" search_in="hdr" header="Via:" assign_to="4"/>
</action>
</recv>
<send>
<![CDATA[
ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via:[$4]
From: [$2]
To: [$3]
Call-ID: [call_id]
CSeq: [cseq] ACK
Contact: <sip:7010@[local_ip]:[local_port]>
Max-Forwards: 70
User-Agent: fredspqa
Content-Length: 0
]]>
</send>
<!-- wait another port ready -->
<pause milliseconds="3000">
</pause>
<send retrans="30000">
<![CDATA[
BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/UDP [local_ip]:[local_port];branch=[branch]
From: <sip:7010@[local_ip]:[local_port]>;tag=[call_number]
To: <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
Call-ID: [call_id]
CSeq: [cseq] BYE
Contact: <sip:7010@[local_ip]:[local_port]>
Max-Forwards: 70
User-Agent: fredspqa
Content-Length: [len]
Content-Type: application/PulseCharge+xml
<?xml version="1.0"?>
<charging-info state="stop">
</charging-info>
]]>
</send>
<recv response="200">
</recv>
</scenario>
底下範例則為 以 sipp 當為UAS(受話端或 SIP server)
命令為
sipp -i 10.10.10.10 -sf uas.xml
這個scenario一開始會持續的等待INVITE.
收到INVITE後會回180RING,
等0.5SEC後回 200 OK
最後再送BYE模擬掛電話的動作
<?xml version="1.0" encoding="windows-1252"?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<!-- usage: -->
<!-- sipp 10.10.10.10:5060 -i 10.10.10.10 -p 5061 -sf register.xml -r 1 -m 1 -->
<!-- sipp -i 10.10.10.10 -sf uas.xml -->
<!-- -->
<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. -->
<recv request="INVITE" crlf="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 occurences are concatenated (CRLF seperated) -->
<!-- to be used in place of the '[last_*]' keyword. -->
<send>
<![CDATA[
SIP/2.0 180 Ringing
[last_Via:]
[last_From:]
[last_To:];tag=[call_number]
[last_Call-ID:]
[last_CSeq:]
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=[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
]]>
</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. -->
<pause 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>