SIP协议是VoIP中最重要的信令控制协议。SIP中第一件事情就是主叫发送INVITE给被叫,被叫响铃。本文从多角度详细描述INVITE消息发送的全过程。
一、阅读RFC权威描述
关于INVITE消息发送,先查看RFC 3261中权威描述:
INVITE client transaction: https://tools.ietf.org/html/rfc3261#page-128
- 从TU收到发送INVITE的要求,通过transport层发出去,进入Calling状态
- 启动Timer A,Timer A触发时发送INVITE
- 启动Timer B,Timer B触发时通知TU
- 网络错误或收到1xx,2xx,300-699响应时处理逻辑各不相同
INVITE server transaction: https://tools.ietf.org/html/rfc3261#page-136
- 收到INVITE时,将INVITE传给TU,并进入Proceeding状态
- 从TU收到100-199响应,通过transport层发出去
- 在Proceeding状态收到INVITE,发送response
很容易产生几个疑问:
- Q1: TU是什么意思?实际中TU具体是什么?
- Q2: 为什么要启动Timer A和Timer B?
- Q3: 被叫收到INVITE是从哪里收到的?
- Q4: “send 100 if TU won't in 200ms” 是什么意思?实际中是怎样的?
二、理解基础细节
Q1: TU是什么意思?实际中TU具体是什么?
TU是Transaction User的缩写,表示的是使用Transaction层服务的上层模块。从RFC 3261的 5 Structure of the Protocol 小节可以知道:SIP协议是分层阐述的,总结如下图:
从上图可知,Transaction层上面是Core层,所以TU就是Core层。对于主叫端是UAC Core,对于被叫端是UAS Core,对于代理服务器就是Proxy Core。如下面两图所示:
Q3: 被叫收到INVITE是从哪里收到的?
从上面的分层描述总很容易看出:被叫收到INVITE是从Transport Sublayer收到的,而Transport Sublayer是从具体使用系统网络传输层如UDP或TCP层收到的。
小结:
将上面两个状态机和相关SIP消息综合在一起,可以得到下图:
三、理解关键设计
第一节阅读RFC时产生的疑问Q2和Q4都涉及到timer,为什么要引入这些timer呢?
这就涉及到SIP协议设计上对底层网络的假设。RFC 3261中明确表示:
SIP works with both IPv4 and IPv6.
即SIP是设计运行在IP网络协议之上的(SIP最初设计就是为VoIP服务的)。
SIP协议对网络传输层没有可靠性的要求,在不可靠的传输层如UDP上可以良好地工作。
所以SIP就要自己保证信令消息的可靠性传输,这也是SIP Transaction层的主要职责:消息丢失重传、消息去重。自然地,SIP Transaction层的状态机就要通过timer来实现重传,通过状态迁移实现去重。具体解释如下:
Q2: 为什么要启动Timer A和Timer B?
Timer A的工作逻辑:发出第一次INVITE请求,在超时时间(第一次是0.5秒)内未收到任何响应,则Timer A触发,此时发出第二次INVITE请求,将超时时间加倍后(0.5x2=1秒)重新计时,超时未收到任何响应,则Timer A再次触发INVITE的发送,依此类推,每次Timer A超时时间加倍。
这样Timer A就实现了以经典的指数型延迟重试策略来确保INVITE的发送和响应接收
- 如果INVITE发送失败,如下图F01,则Timer A会触发INVITE请求重发
- 如果INVITE发送成功,但响应返回途中丢失,如下图F05,则Timer A也会触发INVITE请求重发,UAS收到重复的INVITE请求后,保持状态为Proceeding不变,重新发送响应给UAC
上面解释了Timer A的作用:确保INVITE成功送达且成功收到响应。
那么Timer B呢,很简单,在无网或者网络很差的情况下,INVITE不应无限重发,这就是Timer B的作用,当Timer B超时(RFC建议为32秒)触发时,则停止发送,给TU报告发送失败。
Q4: “send 100 if TU won't in 200ms” 是什么意思?实际中是怎样的?
在RFC 17.2.1 INVITE Server Transaction 中有明确说明:
When a server transaction is constructed for a request, it enters the
"Proceeding" state. The server transaction MUST generate a 100
(Trying) response unless it knows that the TU will generate a
provisional or final response within 200 ms, in which case it MAY
generate a 100 (Trying) response. This provisional response is
needed to quench request retransmissions rapidly in order to avoid
network congestion.
简单来说,如果transaction知道TU不会在200毫秒内发送一个响应,那么transaction应立刻回一个100 Trying响应,以便告知发送方自己已经接收到INVITE请求了,请不要重传INVITE了。这样可以降低网络拥堵。
要回答实际中UAS是否会发100 Trying响应,要看端到端的消息发送过程了。我们看常见的 “客户端 - 服务端 - 客户端” 的网络拓扑下的情况:
从上图可以看到:从主叫客户端UAC到服务端,服务端要转发给被叫客户端,服务端无法确定多久能转发完成,于是在F02步骤立刻回复主叫客户端UAC一个100 Trying响应,告诉主叫:
我收到你的INVITE了,我在努力发送给被叫,请不要重发INVITE了
然后我们看被叫客户端UAS在F04步骤收到INVITE请求,被叫的transaction知道其TU即UAS Core会立即响应一个180 Ringing,所以被叫客户端UAS不会回复服务端100 Trying响应。
总结一下整个INVITE发送到响铃的过程如下图:
要点如下:
- 通过Timer A和B来保障消息可靠送达
- 通过状态机来实现消息去重