zl程序教程

您现在的位置是:首页 >  Java

当前栏目

SIP菜鸟如何学SIP

2023-02-18 16:23:33 时间

在学习SIP之前,我们首先要了解什么是SIP

SIP是一个应用层的控制协议,可以用来建立、修改、和终止多媒体会话(或者会议)例如Internet电话。SIP在建立和维持终止多媒体会话协议上,支持5个方面:

  • 用户定位:检查终端用户的位置,用于通讯。
  • 用户有效性:检查用户参与会话的意愿程度。
  • 用户能力:检查媒体和媒体参数。
  • 建立会话:“ringing”,建立会话参数在呼叫方和被叫方。
  • 会话管理:包括发送和终止会话,修改会话参数,激活服务等等。

了解完SIP之后我们应该来认识一下SIP协议的格式

SIP消息体结构与HTTP协议结构相似,均由三部分组成:

  • 请求行(request-line) or 状态行(status-line)
  • 消息头(header)
  • 正文(body)

请求行:

  • 格式:Method Request-URI SIP-Version
  • eg:INVITE sip:10087@dev.xswitch.cn SIP/2.0
  • method的主要几种消息方法:

状态行:

  • 格式:SIP-Version Status-Code
  • 如:SIP/2.0 200 OK

下面简单列出一些常见的状态码:

消息头:

INVITE sip:10087@dev.xswitch.cn SIP/2.0
Record-Route: <sip:192.168.31.188:15060;lr=on;nat=yes>
Via: SIP/2.0/UDP 192.168.31.188:15060;branch=z9hG4bK986d.1c537238ae43750e62a423ddf7fe078c.0
Via: SIP/2.0/UDP 172.18.0.1:61789;received=172.18.0.1;rport=61789;branch=z9hG4bKPjTu0TroBVkc2BuxTbvQ4ODaYdk83-ljf9
Max-Forwards: 69
From: "10086USER" <sip:10086@dev.xswitch.cn>;tag=xav30sssdGzvtGLUJV7uwjtvKVZra6nl
To: sip:10087@dev.xswitch.cn
Contact: <sip:10086@172.18.0.1:61789;ob;alias=172.18.0.1~61789~1>
Call-ID: 01YPOzp4pT.DDQs5VapOAu9EEy7kss3I
CSeq: 10584 INVITE
Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
Supported: replaces, 100rel, norefersub
User-Agent: Telephone 1.5.2
Content-Type: application/sdp
Content-Length:   471

各消息头简介:

消息体:

消息编码协议头:

v=0
o=- 3874185567 3874185567 IN IP4 172.18.0.1
s=pjmedia
b=AS:117
t=0 0
a=X-nat:0
m=audio 4000 RTP/AVP 96 9 8 0 101 102
c=IN IP4 172.18.0.1
b=TIAS:96000
a=rtpmap:96 opus/48000/2
a=fmtp:96 useinbandfec=1
a=rtpmap:9 G722/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:101 telephone-event/48000
a=fmtp:101 0-16
a=rtpmap:102 telephone-event/8000
a=fmtp:102 0-16
a=rtcp:4001 IN IP4 172.18.0.1
a=ssrc:2122978608 cname:0d505733158cdc19

完整流程Demo:

环境说明:

  • 环境:docker + kamailio + freeswitch
  • 本地 en0 网卡地址:192.168.31.188
  • Kamailio IP:172.18.0.188 代理端口:15060
  • FreeSWITCH IP:172.18.0.14

INVITE消息呼叫源 192.168.31.188 分机号 10086 发送一个会话请求,呼叫10087的分机,注意此时的call-id:01YPOzp4pT.DDQs5VapOAu9EEy7kss3I,留着后面做对比。

INVITE sip:10087@dev.xswitch.cn SIP/2.0
Record-Route: <sip:192.168.31.188:15060;lr=on;nat=yes>
Via: SIP/2.0/UDP 192.168.31.188:15060;branch=z9hG4bK986d.1c537238ae43750e62a423ddf7fe078c.0
Via: SIP/2.0/UDP 172.18.0.1:61789;received=172.18.0.1;rport=61789;branch=z9hG4bKPjTu0TroBVkc2BuxTbvQ4ODaYdk83-ljf9
Max-Forwards: 69
From: "10086USER" <sip:10086@dev.xswitch.cn>;tag=xav30sssdGzvtGLUJV7uwjtvKVZra6nl
To: sip:10087@dev.xswitch.cn
Contact: <sip:10086@172.18.0.1:61789;ob;alias=172.18.0.1~61789~1>
Call-ID: 01YPOzp4pT.DDQs5VapOAu9EEy7kss3I
CSeq: 10584 INVITE
Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
Supported: replaces, 100rel, norefersub
User-Agent: Telephone 1.5.2
Content-Type: application/sdp
Content-Length:   471
P-SRC-IP: 172.18.0.1

100 Trying 消息:

freeswitch告诉客户端,已收到请求,正准备呼叫目标10087

注意,这里的via头域的172.18.0.188,是kam的ip地址,因为此处是kam负责dispatch代理分发的。

至此,10086和fs的通话已经建立。对于fs这种b2bua的模式来说已经生成了一个channel。接下来,freeswitch将通过sip协议生成另一个channel。

SIP/2.0 100 Trying
Via: SIP/2.0/UDP 192.168.31.188:15060;branch=z9hG4bK986d.1c537238ae43750e62a423ddf7fe078c.0;received=172.18.0.188
From: "10086USER" <sip:10086@dev.xswitch.cn>;tag=xav30sssdGzvtGLUJV7uwjtvKVZra6nl
To: sip:10087@dev.xswitch.cn
Call-ID: 01YPOzp4pT.DDQs5VapOAu9EEy7kss3I
CSeq: 10584 INVITE
User-Agent: FreeSWITCH-mod_sofia/1.10.8-dev+git~20211222T004816Z~c7280c7e93~64bit
Content-Length: 0

生成另一个channel:

再次出现了一个invite消息头,但是call-id变了,变成了6e0d4d6e-1d00-4326-b82d-f2eb3bac236e。Via头域里的ip地址也变成了freeswtich容器的地址172.18.0.14,表明fs开始着手呼叫目标号码。

INVITE sip:10087@dev.xswitch.cn;dest=extension SIP/2.0
Via: SIP/2.0/UDP 172.18.0.14:17060;rport;branch=z9hG4bK9FNpKQ6v9aSea
Route: <sip:172.18.0.188:15060>
Max-Forwards: 68
From: "10086USER" <sip:10086@172.18.0.14>;tag=6vSBy8BgceeDQ
To: <sip:10087@dev.xswitch.cn;dest=extension>
Call-ID: 6e0d4d6e-1d00-4326-b82d-f2eb3bac236e
CSeq: 58044591 INVITE
Contact: <sip:mod_sofia@172.18.0.14:17060>
User-Agent: FreeSWITCH-mod_sofia/1.10.8-dev+git~20211222T004816Z~c7280c7e93~64bit
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, refer
Content-Type: application/sdp
Content-Disposition: session
Content-Length: 248
P-SRC-IP: 172.18.0.1
X-FS-Session: c540ce3b-ef41-4cd8-b1ef-4081f678baa0
X-User-Fallback-Proxy: sip:192.168.7.8:5080;transport=tcp
X-FS-Support: update_display,send_info
Remote-Party-ID: "10086USER" <sip:10086@172.18.0.14>;party=calling;screen=yes;privacy=off

再次出现100 trying:

回复10087目标号码已经准备好了。注意,此时的回复是目标端10087回复给freeswitch的。

SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/UDP 172.18.0.14:17060;rport=17060;branch=z9hG4bK9FNpKQ6v9aSea;received=172.18.0.14
From: "10086USER" <sip:10086@172.18.0.14>;tag=6vSBy8BgceeDQ
To: <sip:10087@dev.xswitch.cn;dest=extension>
Call-ID: 6e0d4d6e-1d00-4326-b82d-f2eb3bac236e
CSeq: 58044591 INVITE
Server: kamailio (5.5.2 (x86_64/linux))
Content-Length: 0

183 progres消息:

这个是freeswiitch回复给10086客户端的,此时10087振铃,10086播放回铃音。

SIP/2.0 183 Session Progress
Via: SIP/2.0/UDP 192.168.31.188:15060;branch=z9hG4bK986d.1c537238ae43750e62a423ddf7fe078c.0;received=172.18.0.188
Via: SIP/2.0/UDP 172.18.0.1:61789;received=172.18.0.1;rport=61789;branch=z9hG4bKPjTu0TroBVkc2BuxTbvQ4ODaYdk83-ljf9
Record-Route: <sip:192.168.31.188:15060;lr=on;nat=yes>
From: "10086USER" <sip:10086@dev.xswitch.cn>;tag=xav30sssdGzvtGLUJV7uwjtvKVZra6nl
To: <sip:10087@dev.xswitch.cn>;tag=5K0jvDUcF5QtB
Call-ID: 01YPOzp4pT.DDQs5VapOAu9EEy7kss3I
CSeq: 10584 INVITE
Contact: <sip:10087@172.18.0.14:17060;transport=udp>
User-Agent: FreeSWITCH-mod_sofia/1.10.8-dev+git~20211222T004816Z~c7280c7e93~64bit
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, refer
Content-Type: application/sdp
Content-Disposition: session
Content-Length: 260
Remote-Party-ID: "10087" <sip:10087@dev.xswitch.cn>;party=calling;privacy=off;screen=no

200 OK消息:

当10087拿起电话接听后,回复200给freeswitch。

IP/2.0 200 OK
Via: SIP/2.0/UDP 172.18.0.14:17060;rport=17060;received=172.18.0.14;branch=z9hG4bK9FNpKQ6v9aSea
Record-Route: <sip:192.168.31.188:15060;transport=tcp;lr;r2=on;nat=yes>
Record-Route: <sip:192.168.31.188:15060;lr;r2=on;nat=yes>
Call-ID: 6e0d4d6e-1d00-4326-b82d-f2eb3bac236e
From: "10086USER" <sip:10086@172.18.0.14>;tag=6vSBy8BgceeDQ
To: <sip:10087@dev.xswitch.cn;dest=extension>;tag=B5e4EsqcqeTGk30gdo1X0way6hjX8t04
CSeq: 58044591 INVITE
Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
Contact: <sip:10087@172.18.0.1:57950;transport=TCP;ob;alias=172.18.0.1~57950~2>
Supported: replaces, 100rel, norefersub
Content-Type: application/sdp
Content-Length:   311

ACK消息:

freeswitch收到200之后,回复10087一个ack,表明已经收到,然后会给10086回200。

ACK sip:10087@172.18.0.1:57950;transport=TCP;ob;alias=172.18.0.1~57950~2 SIP/2.0
Via: SIP/2.0/UDP 172.18.0.14:17060;rport;branch=z9hG4bKaSeFNjQ06KF1N
Route: <sip:192.168.31.188:15060;lr;r2=on;nat=yes>
Route: <sip:192.168.31.188:15060;transport=tcp;lr;r2=on;nat=yes>
Max-Forwards: 70
From: "10086USER" <sip:10086@172.18.0.14>;tag=6vSBy8BgceeDQ
To: <sip:10087@dev.xswitch.cn;dest=extension>;tag=B5e4EsqcqeTGk30gdo1X0way6hjX8t04
Call-ID: 6e0d4d6e-1d00-4326-b82d-f2eb3bac236e
CSeq: 58044591 ACK
Contact: <sip:mod_sofia@172.18.0.14:17060>
Content-Length: 0

回送给客户端的200 ok消息:

SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.31.188:15060;branch=z9hG4bK986d.1c537238ae43750e62a423ddf7fe078c.0;received=172.18.0.188
Via: SIP/2.0/UDP 172.18.0.1:61789;received=172.18.0.1;rport=61789;branch=z9hG4bKPjTu0TroBVkc2BuxTbvQ4ODaYdk83-ljf9
Record-Route: <sip:192.168.31.188:15060;lr=on;nat=yes>
From: "10086USER" <sip:10086@dev.xswitch.cn>;tag=xav30sssdGzvtGLUJV7uwjtvKVZra6nl
To: <sip:10087@dev.xswitch.cn>;tag=5K0jvDUcF5QtB
Call-ID: 01YPOzp4pT.DDQs5VapOAu9EEy7kss3I
CSeq: 10584 INVITE
Contact: <sip:10087@172.18.0.14:17060;transport=udp>
User-Agent: FreeSWITCH-mod_sofia/1.10.8-dev+git~20211222T004816Z~c7280c7e93~64bit
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, refer
Session-Expires: 120;refresher=uas
Content-Type: application/sdp
Content-Disposition: session
Content-Length: 260
Remote-Party-ID: "Outbound Call" <sip:10087@dev.xswitch.cn>;party=calling;privacy=off;screen=no

客户端再回一个ack消息给freeswitch:

ACK sip:10087@172.18.0.14:17060;transport=udp SIP/2.0
Via: SIP/2.0/UDP 192.168.31.188:15060;branch=z9hG4bK986d.10b2bc120531367a8df6e82cbba0ef11.0
Via: SIP/2.0/UDP 172.18.0.1:61789;received=172.18.0.1;rport=61789;branch=z9hG4bKPjqRtG0BNHXz3lieovgGbagVMf1bgveYpB
Max-Forwards: 69
From: "10086USER" <sip:10086@dev.xswitch.cn>;tag=xav30sssdGzvtGLUJV7uwjtvKVZra6nl
To: sip:10087@dev.xswitch.cn;tag=5K0jvDUcF5QtB
Call-ID: 01YPOzp4pT.DDQs5VapOAu9EEy7kss3I
CSeq: 10584 ACK
Content-Length:  0

BYE消息:

此时的from是10087,可见是10087这个被叫主动发出的挂机请求给freeswitch。

BYE sip:mod_sofia@172.18.0.14:17060 SIP/2.0
Via: SIP/2.0/UDP 192.168.31.188:15060;branch=z9hG4bK71b.ab931f7decc319df14337c8822b5278b.0;i=3
Via: SIP/2.0/TCP 172.18.0.1:57950;received=172.18.0.1;rport=57950;branch=z9hG4bKPje2pt4x0eBwbYGx1ki8iKkZiCUhRD8oCD;alias
Max-Forwards: 69
From: <sip:10087@dev.xswitch.cn;dest=extension>;tag=B5e4EsqcqeTGk30gdo1X0way6hjX8t04
To: "10086USER" <sip:10086@172.18.0.14>;tag=6vSBy8BgceeDQ
Call-ID: 6e0d4d6e-1d00-4326-b82d-f2eb3bac236e
CSeq: 16442 BYE
User-Agent: Telephone 1.5.2
Content-Length:  0

freeswitch收到bye消息之后,回复200,删除被叫这个channel。

SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.31.188:15060;branch=z9hG4bK71b.ab931f7decc319df14337c8822b5278b.0;i=3;received=172.18.0.188
Via: SIP/2.0/TCP 172.18.0.1:57950;received=172.18.0.1;rport=57950;branch=z9hG4bKPje2pt4x0eBwbYGx1ki8iKkZiCUhRD8oCD;alias
From: <sip:10087@dev.xswitch.cn;dest=extension>;tag=B5e4EsqcqeTGk30gdo1X0way6hjX8t04
To: "10086USER" <sip:10086@172.18.0.14>;tag=6vSBy8BgceeDQ
Call-ID: 6e0d4d6e-1d00-4326-b82d-f2eb3bac236e
CSeq: 16442 BYE
User-Agent: FreeSWITCH-mod_sofia/1.10.8-dev+git~20211222T004816Z~c7280c7e93~64bit
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
Supported: timer, path, replaces
Content-Length: 0

同时,freeswitch也会给原叫回bye,同时会携带挂机原因Reason:Q.850;cause=16;text="NORMAL_CLEARING"

BYE sip:10086@172.18.0.1:61789;ob;alias=172.18.0.1~61789~1 SIP/2.0
Via: SIP/2.0/UDP 172.18.0.14:17060;rport;branch=z9hG4bKB277pD833v5KH
Route: <sip:192.168.31.188:15060;lr=on;nat=yes>
Max-Forwards: 70
From: <sip:10087@dev.xswitch.cn>;tag=5K0jvDUcF5QtB
To: "10086USER" <sip:10086@dev.xswitch.cn>;tag=xav30sssdGzvtGLUJV7uwjtvKVZra6nl
Call-ID: 01YPOzp4pT.DDQs5VapOAu9EEy7kss3I
CSeq: 58044593 BYE
User-Agent: FreeSWITCH-mod_sofia/1.10.8-dev+git~20211222T004816Z~c7280c7e93~64bit
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
Supported: timer, path, replaces
Reason: Q.850;cause=16;text="NORMAL_CLEARING"
Content-Length: 0

客户端收到bye之后回复200给freeswitch,freeswitch挂断原叫这个channel。

至此,整个SIP协议流程完毕。

下面,通过一个简单的图整理一下整个流程: