sipp是一個針對SIP協議進行測試的免費開源工具,可運行於windows/mac/linux,官方地址:http://sipp.sourceforge.net/。
一、安裝
本文只介紹mac上的安裝方式,其它平台(windows/linux)的安裝,可參考官方文檔 (注:感謝黃龍舟做的中文翻譯)
brew install sipp
mac上,直接用brew 一行命令搞定安裝,完成后,可用sipp -v查看版本號,參見下圖,目前的版本號是SIPp v3.6.0-PCAP-RTPSTREAM
二、uac/uas初體驗
安裝好以后,相信大家已經等不及要體驗一把,既然是打電話,就得有“主叫方(uac)”和“被叫方(uas)” (注:對uac、uas第1次接觸的同學,建議先移步 SIP協議學習筆記 )
2.1 啟動內置的uas場景
sipp -sn uas
如上圖所示,啟動uas后,會在本機開1個端口5061,然后下面會一些SIP信令的實時統計,INVITE文字在“右方向箭頭”右側,表示當前收到的INVITE請求數,180左側的“左方向箭頭”表示回應的振鈴消息數。現在只有被叫,並沒有主叫來電,所以Messages這一欄全是0
2.2 啟動內置的uac場景
sipp -sn uac 127.0.0.1:5061
注:最后的“ip:端口”,即為上一步uas啟動的ip地址和端口號,必須匹配。
此時,再回到uas的界面,Messages欄,就不再全是0了
這樣,主叫方(uac)打電話,被叫方(uas)接電話,基本的呼叫流程就通了。
三、理解配置文件
流程雖然跑通了,可能有同學會好奇,uas/uac這2個內置場景,具體邏輯長啥樣?為什么uac的界面,會有100/180/183這些響應碼,沒有其它4xx或5xx之類的碼?除uac/uas,還有其它內置場景嗎?
如上圖,直接輸入sipp,會看到有很多參數說明,其中-sn 表示加載默認的場景,除了uas/uac,還有regexp/branchc/branchs...等其它場景,有興趣的同學可以每種場景都試一下。
另外,還有一個很有用的-sd參數,可以把默認的場景配置,直接導出來,參考下面的命令:
這樣,就把默認的uac/uas這2個場景,導出成xml文件,方便后續研究。打開這2個文件看一下:
3.1 uac.xml

1 <?xml version="1.0" encoding="ISO-8859-1" ?> 2 <!DOCTYPE scenario SYSTEM "sipp.dtd"> 3 4 <scenario name="Basic Sipstone UAC"> 5 <send retrans="500"> 6 <![CDATA[ 7 8 INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0 9 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 10 From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 11 To: [service] <sip:[service]@[remote_ip]:[remote_port]> 12 Call-ID: [call_id] 13 CSeq: 1 INVITE 14 Contact: sip:sipp@[local_ip]:[local_port] 15 Max-Forwards: 70 16 Subject: Performance Test 17 Content-Type: application/sdp 18 Content-Length: [len] 19 20 v=0 21 o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] 22 s=- 23 c=IN IP[media_ip_type] [media_ip] 24 t=0 0 25 m=audio [media_port] RTP/AVP 0 26 a=rtpmap:0 PCMU/8000 27 28 ]]> 29 </send> 30 31 <recv response="100" 32 optional="true"> 33 </recv> 34 35 <recv response="180" optional="true"> 36 </recv> 37 38 <recv response="183" optional="true"> 39 </recv> 40 41 <recv response="200" rtd="true"> 42 </recv> 43 44 <!-- Packet lost can be simulated in any send/recv message by --> 45 <!-- by adding the 'lost = "10"'. Value can be [1-100] percent. --> 46 <send> 47 <![CDATA[ 48 49 ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0 50 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 51 From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 52 To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param] 53 Call-ID: [call_id] 54 CSeq: 1 ACK 55 Contact: sip:sipp@[local_ip]:[local_port] 56 Max-Forwards: 70 57 Subject: Performance Test 58 Content-Length: 0 59 60 ]]> 61 </send> 62 63 <!-- This delay can be customized by the -d command-line option --> 64 <pause/> 65 66 <send retrans="500"> 67 <![CDATA[ 68 69 BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0 70 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 71 From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 72 To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param] 73 Call-ID: [call_id] 74 CSeq: 2 BYE 75 Contact: sip:sipp@[local_ip]:[local_port] 76 Max-Forwards: 70 77 Subject: Performance Test 78 Content-Length: 0 79 80 ]]> 81 </send> 82 83 <recv response="200" crlf="true"> 84 </recv> 85 86 <!-- definition of the response time repartition table (unit is ms) --> 87 <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> 88 89 <!-- definition of the call length repartition table (unit is ms) --> 90 <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> 91 92 </scenario>
看着貌似一大堆,有點嚇人,但並不難理解:
a) 5-29行,第一段send,發送INVITE信令,即:准備打電話
b) 接下來的31-39行,表示期待收到被叫方回過來的100/180/183響應,注意這3小段,都是optional=true,表示預期的響應是可選的,即:對方可以發100/180/183,也可以不發。通俗點講,打一通電話過去,對方可能振鈴或不振鈴(比如:對方已經在通話中,或者話機有問題)
c) 41行,期待對方回200過來,這里沒有optional=true,表示不是可選的,如果收不到,就無法繼續。
d) 46-61行,表示上一步收到200后,主叫方發送ACK確認
e) 64行,pause暫停,但是並沒有指定暫停多久,看注釋,可以在啟動uac時,傳入“-d 暫停時間”指定,這一行相當於電話接起來,模擬雙方在通話,讓電話先不要斷。
f) 66-81行,表示uac發出bye掛斷信令,結束通話,注 retrans="500",表示如果發送失敗,500ms后,會重發。
3.2 uas.xml

1 <?xml version="1.0" encoding="ISO-8859-1" ?> 2 <!DOCTYPE scenario SYSTEM "sipp.dtd"> 3 4 <scenario name="Basic UAS responder"> 5 6 <recv request="INVITE" crlf="true"> 7 </recv> 8 9 <send> 10 <![CDATA[ 11 12 SIP/2.0 180 Ringing 13 [last_Via:] 14 [last_From:] 15 [last_To:];tag=[pid]SIPpTag01[call_number] 16 [last_Call-ID:] 17 [last_CSeq:] 18 Contact: <sip:[local_ip]:[local_port];transport=[transport]> 19 Content-Length: 0 20 21 ]]> 22 </send> 23 24 <send retrans="500"> 25 <![CDATA[ 26 27 SIP/2.0 200 OK 28 [last_Via:] 29 [last_From:] 30 [last_To:];tag=[pid]SIPpTag01[call_number] 31 [last_Call-ID:] 32 [last_CSeq:] 33 Contact: <sip:[local_ip]:[local_port];transport=[transport]> 34 Content-Type: application/sdp 35 Content-Length: [len] 36 37 v=0 38 o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] 39 s=- 40 c=IN IP[media_ip_type] [media_ip] 41 t=0 0 42 m=audio [media_port] RTP/AVP 0 43 a=rtpmap:0 PCMU/8000 44 45 ]]> 46 </send> 47 48 <recv request="ACK" 49 optional="true" 50 rtd="true" 51 crlf="true"> 52 </recv> 53 54 <recv request="BYE"> 55 </recv> 56 57 <send> 58 <![CDATA[ 59 60 SIP/2.0 200 OK 61 [last_Via:] 62 [last_From:] 63 [last_To:] 64 [last_Call-ID:] 65 [last_CSeq:] 66 Contact: <sip:[local_ip]:[local_port];transport=[transport]> 67 Content-Length: 0 68 69 ]]> 70 </send> 71 72 <!-- Keep the call open for a while in case the 200 is lost to be --> 73 <!-- able to retransmit it if we receive the BYE again. --> 74 <timewait milliseconds="4000"/> 75 76 <!-- definition of the response time repartition table (unit is ms) --> 77 <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> 78 79 <!-- definition of the call length repartition table (unit is ms) --> 80 <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> 81 82 </scenario>
a) 6-7行,等待主叫方發送INVITE信令。
b) 9-22行收到主叫方的INVITE請求后,先send 180響應,表示振鈴。
c) 24-46行,發送200 響應,表示被叫方已經ready.
d) 48-52行,期待對應發過來ACK確認(注:optional=true,表示可選),至此,通話已經建立。
e) 54-55行,等待被叫方發送掛斷信令BYE
f) 57-70行,發送200,通知主叫方掛斷完成。
g) 74行,等4秒,防止上一步的200響應由於網絡原因丟失,留4秒余量,讓對方重發BYE信令。
3.3 自定義scenario配置
除了內置的幾種場景,我們也可以自定義xml配置文件,比如:我們把內置的uas.xml/uac.xml簡化一下,讓主叫方發起呼叫后,被叫方直接掛斷(即:模擬被掛方拒接)
uac2.xml

1 <?xml version="1.0" encoding="ISO-8859-1" ?> 2 <!DOCTYPE scenario SYSTEM "sipp.dtd"> 3 4 <scenario name="Basic Sipstone UAC"> 5 6 <send retrans="500"> 7 <![CDATA[ 8 9 INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0 10 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 11 From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 12 To: [service] <sip:[service]@[remote_ip]:[remote_port]> 13 Call-ID: [call_id] 14 CSeq: 1 INVITE 15 Contact: sip:sipp@[local_ip]:[local_port] 16 Max-Forwards: 70 17 Subject: Performance Test 18 Content-Type: application/sdp 19 Content-Length: [len] 20 21 v=0 22 o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] 23 s=- 24 c=IN IP[media_ip_type] [media_ip] 25 t=0 0 26 m=audio [media_port] RTP/AVP 0 27 a=rtpmap:0 PCMU/8000 28 29 ]]> 30 </send> 31 32 <recv response="200" rtd="true"> 33 </recv> 34 35 <send retrans="500"> 36 <![CDATA[ 37 38 BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0 39 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 40 From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 41 To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param] 42 Call-ID: [call_id] 43 CSeq: 2 BYE 44 Contact: sip:sipp@[local_ip]:[local_port] 45 Max-Forwards: 70 46 Subject: Performance Test 47 Content-Length: 0 48 49 ]]> 50 </send> 51 52 <!-- definition of the response time repartition table (unit is ms) --> 53 <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> 54 55 <!-- definition of the call length repartition table (unit is ms) --> 56 <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> 57 58 </scenario>
uas2.xml

1 <?xml version="1.0" encoding="ISO-8859-1" ?> 2 <!DOCTYPE scenario SYSTEM "sipp.dtd"> 3 4 <scenario name="Basic UAS responder"> 5 6 <recv request="INVITE" crlf="true"> 7 </recv> 8 9 <send retrans="500"> 10 <![CDATA[ 11 12 SIP/2.0 200 OK 13 [last_Via:] 14 [last_From:] 15 [last_To:];tag=[pid]SIPpTag01[call_number] 16 [last_Call-ID:] 17 [last_CSeq:] 18 Contact: <sip:[local_ip]:[local_port];transport=[transport]> 19 Content-Type: application/sdp 20 Content-Length: [len] 21 22 v=0 23 o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] 24 s=- 25 c=IN IP[media_ip_type] [media_ip] 26 t=0 0 27 m=audio [media_port] RTP/AVP 0 28 a=rtpmap:0 PCMU/8000 29 30 ]]> 31 </send> 32 33 <recv request="BYE"> 34 </recv> 35 36 <!-- definition of the response time repartition table (unit is ms) --> 37 <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> 38 39 <!-- definition of the call length repartition table (unit is ms) --> 40 <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> 41 42 </scenario>
使用時,可以用參數-sf加載xml文件
三、使用數據文件
3.1 簡單數據文件
測試時,通常需要模擬不同的主被叫號碼,前面的測試中,可能有同學注意到了uac.xml中,From/To是寫死的用戶sipp,能否動態替換用戶名呢?當然可以!
SEQUENTIAL #This line will be ignored 1001;1019 1002;1018 1003;1017 1004;1016
創建一個uac_data.csv的文件,內容參考上面。第1行的SEQUENTIAL表示順序讀取,#行表示注釋,第3行開始,定義數據行,每行2列,在uac.xml配置文件中,可以用[field0]、[field1]來占位替換,即:
重新跑一下uac場景,這次要新加參數 -inf uac_data.csv,同時為了方便驗證SIP報文內容,加上-trace_msg
sipp -sf uac.xml -inf uac_data.csv 127.0.0.1:5060 -trace_msg
跑起來后,應該在當前目錄生成類似uac_xxx_messages.log的日志文件,打開看看占位符[field0]/[field1]是否被替換了。
3.2 動態數據文件
如果模擬的主/被號很多,一行行手動寫有點麻煩,可以用下面的方式自動生成
SEQUENTIAL,PRINTF=999 1%03d;2%03d
其中PRINTF=N,表示生成多少行,而下面的%03d為占位符,真正運行時,會生成
SEQUENTIAL,PRINTF=999 1000;2000 1001;2001 1002;2002 1003;2003 ...
四、與freeswitch交互
假設要自動測試1個場景:主叫方撥打1開頭的內線號碼 ,被叫方自動應答。可以在freeswitch的diaplan里,加這么一段:(注:mac上默認的配置文件為/usr/local/freeswitch/conf/dialplan/default.xml)

1 <extension name="auto-answer-sample"> 2 <condition field="destination_number" expression="^10\d+$"> 3 <action application="log" data="******** auto-answer-and-echo **********"/> 4 <action application="answer"/> 5 <action application="echo"/> 6 </condition> 7 </extension>
然后用軟電話工具,測試一下:
如上圖,用zoiper終端,以1000身份注冊到freeswitch后,撥打1010號碼 ,在freeswitch的控制台,看到已經自動接聽,然后echo,說明diaplan確實生效了。
用sipp如何來自動測試這一場景呢?顯然對於sipp來說,這是一個uac場景,我們寫一段uac_auto_answer.xml

1 <?xml version="1.0" encoding="ISO-8859-1" ?> 2 <!DOCTYPE scenario SYSTEM "sipp.dtd"> 3 4 <scenario name="uac_auto_answer_test"> 5 6 <!-- 發起呼叫 --> 7 <send retrans="500"> 8 <![CDATA[ 9 10 INVITE sip:[field1]@[remote_ip]:[remote_port] SIP/2.0 11 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 12 From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 13 To: [field1] <sip:[field1]@[remote_ip]:[remote_port]> 14 Call-ID: [call_id] 15 CSeq: 1 INVITE 16 Contact: sip:[field0]@[local_ip]:[local_port] 17 Max-Forwards: 70 18 Subject: Performance Test 19 Content-Type: application/sdp 20 Content-Length: [len] 21 22 v=0 23 o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] 24 s=- 25 c=IN IP[media_ip_type] [media_ip] 26 t=0 0 27 m=audio [media_port] RTP/AVP 0 28 a=rtpmap:0 PCMU/8000 29 30 ]]> 31 </send> 32 33 <!-- 期待freeswitch回200 --> 34 <recv response="200" rtd="true"> 35 </recv> 36 37 <!-- 期望電話接通后,暫停,由-d參數控制通話時長 --> 38 <pause/> 39 40 <!-- 通話結束后,自動掛斷 --> 41 <send retrans="500"> 42 <![CDATA[ 43 44 BYE sip:[field1]@[remote_ip]:[remote_port] SIP/2.0 45 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 46 From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 47 To: [field1] <sip:[field1]@[remote_ip]:[remote_port]>[peer_tag_param] 48 Call-ID: [call_id] 49 CSeq: 2 BYE 50 Contact: sip:[field0]@[local_ip]:[local_port] 51 Max-Forwards: 70 52 Subject: Performance Test 53 Content-Length: 0 54 55 ]]> 56 </send> 57 58 <!-- definition of the response time repartition table (unit is ms) --> 59 <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> 60 61 <!-- definition of the call length repartition table (unit is ms) --> 62 <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> 63 64 </scenario>
看上去,貌似沒啥問題,定義相應的數據文件uac_auto_answer_data.csv
SEQUENTIAL #callerNumber,destNumber 1000;1010 1001;1011
跑一把:
sipp -sf uac_auto_answer.xml -inf uac_auto_answer_data.csv 192.168.7.101:5070 -l 1 -d 10000 -trace_msg -trace_err
其中192.168.7.101:5070 為本機freeswitch的ip和端口號
可以看到,並沒有預期的200響應,freeswitch的控制台上,也沒看到預期的answer, echo響應
查看sipp生成的error日志,可以看到
'2021-05-16 15:12:01.801909 1621149121.801909: Aborting call on unexpected message for Call-Id '14-90540@192.168.7.101': while expecting '200' (index 1), received 'SIP/2.0 407 Proxy Authentication Required
很多這種錯誤:received 'SIP/2.0 407 Proxy Authentication Required,憑經驗,但凡跟Authentication相關的,多半跟驗證有關。
先關閉freeswitch的auth驗證,方法如下:
a) /usr/local/freeswitch/conf/vars.xml中,把 internal_auth_calls改成false
<X-PRE-PROCESS cmd="set" data="internal_auth_calls=false"/>
b) /usr/local/freeswitch/conf/autoload_configs/acl.conf.xml
1 <list name="domains" default="deny"> 2 <!-- domain= is special it scans the domain from the directory to build the ACL --> 3 <node type="allow" domain="$${domain}"/> 4 <!-- use cidr= if you wish to allow ip ranges to this domains acl. --> 5 <!-- 把執行sipp機器所在網段,加入到allow列表 --> 6 <node type="allow" cidr="192.168.7.0/24"/> 7 </list>
參考第6行,把相應的網段加到allow列表里。
重啟freeswitch后,再跑一把,會發現仍然沒有預期的返回,sipp終端的messages列,期望的200仍然沒有返回。此時freeswitch控制台,有下列輸出:
同時sipp的錯誤日志時,有很多487的返回:
'2021-05-16 15:31:48.012115 1621150308.012115: Dead call 1-96258@192.168.7.101 (aborted at index 1), received 'SIP/2.0 487 Request Terminated
說明freeswitch的SIP返回報文,跟我們想得不一樣,並不是直接返回了200,這時候就要祭出大招:tcpdump抓包工具(注:這里故意為了演示如何使用抓包工具,如果對freeswitch有經驗的同學,可能一眼就能看出freeswitch會先返回100響應碼)
如何抓包,也要有思路,既然用zoiper軟電話工具,能正常跑通,說明freeswitch肯定是沒問題的,那我們就抓zoiper與freeswitch之間的SIP包,抓包步驟:
先確認要抓哪塊網卡:
tcpdump -D會列出本機所有網卡,然后用ifconfig看下各網卡的ip
本文所有測試,都是在mac筆記本上執行的,跟freeswitch相關的ip,只有127.0.0.1及192.168.7.101,也就是上圖中的網卡lo0、en0
注:可能有同學會問,5070在上圖中,lsof -i:5070,不就只有192.168.7.101嗎?為啥還要關注127.0.0.1 ?
輸入命令:
sudo tcpdump -i en0 port 5070 -vv -w sip_en0.log
即:抓取網卡en0上,端口號為5070的數據包,並將結果寫入sip_en0.log中。抓包工具開啟后,軟電話zoiper呼叫1010,奇怪的是電話接通后,tcpdump里Got 0,也就是並未抓到數據!
然后嘗試抓取127.0.0.1所在網卡lo0,同樣的操作,這次有數據了!(這也就解釋了前面的為什么要關注127.0.0.1所在網卡的原因)
打開抓包的數據文件sip_lo0.log,大致內容如下(已做了整理,方便閱讀):
# 1、 Zoiper向freeswitch 發送INVITE INVITE sip:1011@192.168.7.101:5070;transport=UDP SIP/2.0 Via: SIP/2.0/UDP 192.168.7.101:5061;branch=z9hG4bK-d8754z-37e95a74eab22936-1---d8754z-;rport Max-Forwards: 70 Contact: <sip:1000@192.168.7.101:5061> To: <sip:1011@192.168.7.101:5070>;transport=UDP From: "jimmy"<sip:1000@192.168.7.101:5070>;transport=UDP;tag=cfb0773d Call-ID: ZjFmMTExZThiNGE5ZWM3YzNiZTMyNWY0ZWUxMTVkMTE. CSeq: 1 INVITE Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, NOTIFY, REFER, MESSAGE, OPTIONS, INFO Content-Type: application/sdp User-Agent: Zoiper rev.1809 Content-Length: 306 v=0 o=Z 0 0 IN IP4 192.168.7.101 s=Z c=IN IP4 192.168.7.101 t=0 0 m=audio 8000 RTP/AVP 3 110 98 8 0 101 a=rtpmap:3 GSM/8000 a=rtpmap:110 speex/8000 a=rtpmap:98 iLBC/8000 a=fmtp:98 mode=30 a=rtpmap:8 PCMA/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-15 a=sendrecv # 2、 Freeswitch回應100 Trying SIP/2.0 100 Trying Via: SIP/2.0/UDP 192.168.7.101:5061;branch=z9hG4bK-d8754z-37e95a74eab22936-1---d8754z-;rport=5061 From: "jimmy" <sip:1000@192.168.7.101:5070>;transport=UDP;tag=cfb0773d To: <sip:1011@192.168.7.101:5070>;transport=UDP Call-ID: ZjFmMTExZThiNGE5ZWM3YzNiZTMyNWY0ZWUxMTVkMTE. CSeq: 1 INVITE User-Agent: FreeSWITCH-mod_sofia/1.10.2-release~64bit Content-Length: 0 # 3、 Freeswitch回應200 OK SIP/2.0 200 OK Via: SIP/2.0/UDP 192.168.7.101:5061;branch=z9hG4bK-d8754z-37e95a74eab22936-1---d8754z-;rport=5061 From: "jimmy" <sip:1000@192.168.7.101:5070>;transport=UDP;tag=cfb0773d To: <sip:1011@192.168.7.101:5070>;transport=UDP;tag=8BZ2eg0QStH7H Call-ID: ZjFmMTExZThiNGE5ZWM3YzNiZTMyNWY0ZWUxMTVkMTE. CSeq: 1 INVITE Contact: <sip:1011@192.168.7.101:5070;transport=udp> User-Agent: FreeSWITCH-mod_sofia/1.10.2-release~64bit Accept: application/sdp Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE Supported: timer, path, replaces Allow-Events: talk, hold, conference, presence, as-feature-event, dialog, line-seize, call-info, sla, include-session-description, presence.winfo, message-summary, refer Content-Type: application/sdp Content-Disposition: session Content-Length: 222 Remote-Party-ID: "1011" <sip:1011@192.168.7.101>;party=calling;privacy=off;screen=no v=0 o=FreeSWITCH 1621133187 1621133188 IN IP4 192.168.7.101 s=FreeSWITCH c=IN IP4 192.168.7.101 t=0 0 m=audio 18838 RTP/AVP 8 101 a=rtpmap:8 PCMA/8000 a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-16 a=ptime:20 # 4、 Zoiper發送ACK ACK sip:1011@192.168.7.101:5070;transport=udp SIP/2.0 Via: SIP/2.0/UDP 192.168.7.101:5061;branch=z9hG4bK-d8754z-20ff2eafb70e0d57-1---d8754z-;rport Max-Forwards: 70 Contact: <sip:1000@192.168.7.101:5061> To: <sip:1011@192.168.7.101:5070>;transport=UDP;tag=8BZ2eg0QStH7H From: "jimmy"<sip:1000@192.168.7.101:5070>;transport=UDP;tag=cfb0773d Call-ID: ZjFmMTExZThiNGE5ZWM3YzNiZTMyNWY0ZWUxMTVkMTE. CSeq: 1 ACK User-Agent: Zoiper rev.1809 Content-Length: 0 # 5、Zoiper發送BYE BYE sip:1011@192.168.7.101:5070;transport=udp SIP/2.0 Via: SIP/2.0/UDP 192.168.7.101:5061;branch=z9hG4bK-d8754z-f07268afb96f7be8-1---d8754z-;rport Max-Forwards: 70 Contact: <sip:1000@192.168.7.101:5061> To: <sip:1011@192.168.7.101:5070>;transport=UDP;tag=8BZ2eg0QStH7H From: "jimmy"<sip:1000@192.168.7.101:5070>;transport=UDP;tag=cfb0773d Call-ID: ZjFmMTExZThiNGE5ZWM3YzNiZTMyNWY0ZWUxMTVkMTE. CSeq: 2 BYE User-Agent: Zoiper rev.1809 Content-Length: 0 # 6、FreeSWITCH回應200 SIP/2.0 200 OK Via: SIP/2.0/UDP 192.168.7.101:5061;branch=z9hG4bK-d8754z-f07268afb96f7be8-1---d8754z-;rport=5061 From: "jimmy" <sip:1000@192.168.7.101:5070>;transport=UDP;tag=cfb0773d To: <sip:1011@192.168.7.101:5070>;transport=UDP;tag=8BZ2eg0QStH7H Call-ID: ZjFmMTExZThiNGE5ZWM3YzNiZTMyNWY0ZWUxMTVkMTE. CSeq: 2 BYE User-Agent: FreeSWITCH-mod_sofia/1.10.2-release~64bit Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE Supported: timer, path, replaces Content-Length: 0
可以發現,FreeSwitch收到INVITE后,並不是直接回的200,而是先回了100。所以uac的xml要調整一下:

1 <?xml version="1.0" encoding="ISO-8859-1" ?> 2 <!DOCTYPE scenario SYSTEM "sipp.dtd"> 3 4 <scenario name="Basic Sipstone UAC"> 5 6 <send retrans="500"> 7 <![CDATA[ 8 9 INVITE sip:[field1]@[remote_ip]:[remote_port] SIP/2.0 10 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 11 From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 12 To: [field1] <sip:[field1]@[remote_ip]:[remote_port]> 13 Call-ID: [call_id] 14 CSeq: 1 INVITE 15 Contact: sip:[field0]@[local_ip]:[local_port] 16 Max-Forwards: 70 17 Subject: Performance Test 18 Content-Type: application/sdp 19 Content-Length: [len] 20 21 v=0 22 o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip] 23 s=- 24 c=IN IP[media_ip_type] [media_ip] 25 t=0 0 26 m=audio [media_port] RTP/AVP 0 27 a=rtpmap:0 PCMU/8000 28 29 ]]> 30 </send> 31 32 <!-- 加上這個100的接收 --> 33 <recv response="100"> 34 </recv> 35 36 <recv response="200"> 37 </recv> 38 39 <!-- 從抓包來看,zoiper有發送了ACK,但是sipp加上后,一直發不成功,先注釋掉 --> 40 <!-- <send retrans="500"> 41 <![CDATA[ 42 43 ACK sip:[field1]@[remote_ip]:[remote_port] SIP/2.0 44 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 45 From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 46 To: [field1] <sip:[field1]@[remote_ip]:[remote_port]>[peer_tag_param] 47 Call-ID: [call_id] 48 CSeq: 1 ACK 49 Contact: sip:[field0]@[local_ip]:[local_port] 50 Max-Forwards: 70 51 Subject: Performance Test 52 Content-Length: 0 53 54 ]]> 55 </send> --> 56 57 <pause/> 58 59 <send retrans="500"> 60 <![CDATA[ 61 BYE sip:[field1]@[remote_ip]:[remote_port] SIP/2.0 62 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] 63 From: [field0] <sip:[field0]@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number] 64 To: [field1] <sip:[field1]@[remote_ip]:[remote_port]>[peer_tag_param] 65 Call-ID: [call_id] 66 CSeq: 2 BYE 67 Contact: sip:[field0]@[local_ip]:[local_port] 68 Max-Forwards: 70 69 Subject: Performance Test 70 Content-Length: 0 71 ]]> 72 </send> 73 74 <!-- freeswitch收到BYE后,會回200 --> 75 <recv response="200"> 76 </recv> 77 78 <!-- definition of the response time repartition table (unit is ms) --> 79 <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/> 80 81 <!-- definition of the call length repartition table (unit is ms) --> 82 <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/> 83 84 </scenario>
然后再執行,終於跑起來了!
Freeswitch的控制台,也正常輸出了answer, echo等信息
相信大家看完本文后,對sipp的使用已經入門了,如果遇到復雜場景,不知道如何寫sipp xml時,建議多利用日志文件及抓包工具。