sip
SIP协议
一.绪论
SIP协议即为会话初始协议。
针对我们的Subcentrex2.0系统,对SIP协议的需要进行重点学习的是设备的注册以及呼叫在系统中的流程,其中包括消息的发起,转发,处理以及对消息的回应。
二.SIP消息
SIP消息主要分为请求和响应两个大分类,invite和response!
请求消息为客户机发给服务器端,响应消息为服务器发给客户端,他们都是以RFC2822定义的基本格式进行编码的。
请求和响应消息格式如下:
SIP 消息=起始行R
*消息头部(1 个或多个头部)
CRLF (空行)
[消息体]
起始行=请求行/状态行
2.1请求消息
请求消息的起始行为请求行(Request-Line)。请求行的格式如下所示,由方法名、请求URL 和协议版本组成,各部分之间均用一个空格字符进行分隔。除此之外,请求行必须用回车换行(CRLF)字符表示行终结。
Request-Line = Method[ ] Request-URI [] SIP-Version CRLF
1)Method:本规范共定义了6 个方法,INVITE、ACK、CANCEL、OPTIONS、BYE 和REGISTER。REGISTER 消息用于发送注册请求信息,INVITE、ACK、CANCEL 用于建立会话连接,BYE 用于终结会话连接,OPTIONS 用于查询服务器能力。本协议规定方法名必须使用大写字母。除以上6 类主要消息外,SIP 协议在其他文档中还定有若干方法实现协议扩展。
2)Request-URL:指示被邀请用户的当前地址,本协议规定Request-URL 中不允许出现空格或其他控制字符且不能包含于“<>”符号之内。除使用“sip”和“sips”之外,Request-URI 还可以使用“tel”的URI 定义机制,有关“tel”的URI定义机制参见RFC2806。SIP 实体可使用任何可选方法将非SIP URL 翻译成SIP URI、SIPS URI 或其他URI 定义。
3)SIP-Version:用于定义协议的当前版本号,本协议的版本号为SIP/2.0
请求示例:INVITE sip:665@218.80.220.50:5060 SIP/2.0
Via:SIP/2.0/UDP 172.16.195.156:5060;branch=z9hG4bk80f97d7468ee9e
From:NULL<sip:664@218.80.220.50;user=phone>;tag=AB93CCC237BEBA71D1A
To:<sip:665@218.80.220.50;user=phone>
Call-ID:30057-BD21-D4AD-F0E0-4A468FCF59D9@172.16.195.156
CSeq:1 INVITE
Supported: replaces,timer
Allow: INVITE,OPTIONS,BYE,CANCEL,ACK,SUBSCRIBE,NOTIFY,INFO,REFER
Contact: <sip:664@172.16.195.156:5060;transport=udp>
Max-Forwards: 70
User-Agent: HP180-S VOIP IPPhone
Content-Type: application/sdp
Content-Length: 229
v=0
o=TelogyUnknown0000 1049699 1049699 IN IP4 172.16.195.156
s=RTP Audio
c=IN IP4 172.16.195.156
t=0 0
m=audio 2070 RTP/AVP 18 4 0 8
a=rtpmap:18 G729/8000
a=rtpmap:4 G723/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
2.2响应:
响应消息的起始行为状态行(Status-Line),状态行由协议版本、状态码和与状态码相关的文本描述组成,各个部分之间用一个空格字符进行分隔。状态行的格式如下所示:
Status-Line = SIP-Version [ ]Status-Code [ ] Reason-Phrase CRLF
除状态行的尾部可使用回车换行CRLF 字符之外,状态行内不允许出现CRLF 字符。
1) Status-Code(状态码):该参数为一个3 位的十进制整数,用于指示请求消息的执行响应结果。
2) Reason-Phrase(原因):该参数用于对Status-Code 参数进行简单的文本描述。客户机不必检查或显示Reason-Phrase 参数。尽管本规范建议使用特定字符表示Reason-Phrase,具体实现过程中Reason-Phrase 仍可使用其他的文本字符。本协议共定义6 类状态码,其中状态码的第1 位数字用于指示响应类型,后两位数字表示具体响应。本协议规定状态码为“100—199”之间的响应用“1XX”进行标识,“200—299”之间的响应用
“2XX”进行标识,依此类推。
1) 1XX:临时响应,表示请求消息正在被处理。
2) 2XX:成功响应,表示请求已被成功接收,完全理解并被接受。
3) 3XX:重定向响应,表示需采取进一步以完成该请求。
4) 4XX:客户机错误,表示请求消息中包含语法错误信息或服务器无法完成客户机请求。
5) 5XX:服务器错误,表示服务器无法完成合法请求。
6) 6XX:全局故障,表示任何服务器无法完成该请求。
响应示例:
SIP/2.0 200 OK
From: NULL<sip:664@218.80.220.50;user=phone>;tag=AB93CCC237BEBA71D1A
To: <sip:665@218.80.220.50;user=phone>;tag=32dc50da-13c4-4092d0eb-ac971-788041e3
Call-ID: 30057-BD21-D4AD-F0E0-4A468FCF59D9@172.16.195.156
CSeq: 1 CANCEL
Via: SIP/2.0/UDP 172.16.195.156:5060;received=218.1.121.106;rport=59573;branch=z9hG4bk80f97d7468ee9e
Content-Length: 0
2.3 头字段
SIP 头字段的语法和语义定义与HTTP 头字段定义基本相同,有关HTTP 头字段的定义和SIP 头字段多行扩展的定义规则参见RFC 2616。RFC 2616 中定义的多行扩展可使用隐含的空格和折叠字符(folding),而本规范定义的多行扩展规则只能使用显式空格和折叠字符(folding),且空格和折叠字符(folding) 作为消息的组成部分。
同样,RFC 2616 也定义了将具有多个参数值的同一字段扩展为具有相同字段名称的多个字段行的规则。该规则同样适用于本协议,但具体应用时规则会有所不同。SIP 协议定义的头字段语法规则如下:header = "header-name" HCOLON header-value *(COMMA header-value)
如上所示,SIP 头字段允许一个头字段可以定义多个参数值,且多个参数值之间用“,”字符进行分隔。当属性值不为“*”时,Contact 头字段允许属性值之间用“,”字符进行分隔。
2.4 消息实体
本协议规定SIP 请求消息可包含消息实体部分,消息实体部分的解释应与消息请求方法相一致。对于SIP 响应消息,请求方法和响应状态码可以识别消息实体的类型。本协议规定所有SIP 响应消息应包含一个消息实体部分。
2.5 SIP 消息帧
SIP 协议可以使用UDP 或者其他不可靠的报文协议进行承载传送,且每一个报文携带一个请求或响应消息。关于SIP 协议以不可靠协议传送有关要求参见本规范第18 章。
具体实现时,如果SIP 消息采用面向流的方式进行传送,则SIP 消息起始行前的任何CRLF 字符应忽略。“Content-Length ”头字段值用于定义一个SIP 消息在流中的结束位置。当SIP 消息采用面向流的方式进行传送时,该头字段不能被省略。
三.设备的注册
设备在注册的时候会向SERVER发送Registration消息,服务器接受到请求以后会对注册设备进行相应的鉴权,如果成功将会给设备会200 OK的响应;如果失败将会给出4XX错误响应。
针对我们的Subcentrex系统,设备注册的流程是,设备向AS发送Registration请求消息,AS会想DBPROXY发送设备鉴权请求,然后DBPROXY向RDBMS发送消息,对设备的DEVICE ID等信息进行比对,如果正确AS将收到鉴权成功的消息,并向设备发送200 OK 的响应;既而设备成功注册。下面将给出一个设备成功注册的示例:
注册请求:
REGISTER sip:218.80.220.50:5060 SIP/2.0
Via:SIP/2.0/UDP 172.16.195.18:5060;branch=z9hG4bke712404c90e866
From:<sip:663@218.80.220.50;user=phone>;tag=E08D85B12D3AE9BECBA
To:<sip:663@218.80.220.50;user=phone>
Call-ID:4098-BD21-D423-BF4E-FFFFC1878259@172.16.195.18
CSeq:72 REGISTER
User-Agent: WLAN600-S VOIP IPPhone
Contact: <sip:663@172.16.195.18:5060;transport=udp>
Expires: 360
Content-Length: 0
注册响应:
SIP/2.0 200 OK
From: <sip:663@218.80.220.50;user=phone>;tag=E08D85B12D3AE9BECBA
To: <sip:663@218.80.220.50;user=phone>;tag=32dc50da-13c4-4092d0ee-ad4ae-2785220c
Call-ID: 4098-BD21-D423-BF4E-FFFFC1878259@172.16.195.18
CSeq: 72 REGISTER
Date: Fri, 30 Apr 2004 14:19:26 GMT
Contact: <sip:663@172.16.195.18:5060>;expires=360
Expires: 50
Via: SIP/2.0/UDP 172.16.195.18:5060;received=218.1.121.106;rport=44619;branch=z9hG4bke712404c90e866
Content-Length: 0
四.对话(Dialog)
对话是两个UA 之间持续一段时间的点对点的SIP 连接,它使UA 之间的消息变得有序,同时给出请求消息的正确的路由。对话包括一个解释SIP 消息的上下文。有关对话外独立UA 处理请求和响应的方法参见本规范第8 章。本章将规定如何使用那些请求和响应去建立一个对话,以及在对话过程中如何发送后续的请求和响应。任何UA 上的对话都是由对话ID 来标识的,这个对话ID 包含一个Call-ID,一个本地标签和一个远端标签。对话中的每个UA 的对话ID 是不同的。另外,一个UA 的本地标识符与对端UA 的远端标识符相等。标签(tags)在唯一的对话ID 的生成过程中是不透明的。
对话ID 与其To 头字段中包含一个标签(tag)的所有响应和请有关。某个消息中的对话ID 的计算规则取决于SIP 实体是UAC 还是UAS。对于UAC,对话ID 中的Call-ID 由消息的Call-ID 头字段设置,远端标签(tag)由To 头字段的tag 设置,本地标签由于From 头字段的tag 设置。对于UAS,对话ID中的Call-ID 由消息中的Call-ID 头字段设置,远端标签由消息From 头字段的tag 设置,消息To 头字段的tag 设置;对话中包括一些对话中的后续消息所需的状态,包括:对话ID、本地序列号、远URI、远端URI、远端目的、布尔型标记“secure”和路由集,其中路由集是一个顺序发送一个请求到对端所需遍历的服务器地址。临时的响应被创建时,对话处于“初始状态”,当一个2xx 的最终响应到达时转如果是其他响应或无响应到达,“初始状态”终止。
4.1会话发起的过程
UA通过向服务器发送INVITE 消息开始会话发起过程,该请求可能通过网络中间的服务器设备的转发,最终到达UAS。如果UAS 同意建立本次会话,则返回2XX 响应,如果不同意,则返回3XX、4X、5XX、6XX 响应。在收到最终响应之前,UAS 也可以发送临时响应(1XX)来通知UAC 当前的处理进展情况。由于该INVITE 请求可能被分支(Forking),UAC 可能会收到一个或多个2XX 响应或者一个非2XX响应。UAC 收到最终响应消息之后需要向UAS 侧发送ACK 消息。每一个2XX 响应都会创建一个Dialog,因此如果UAC 收到多个2XX 响应,那么每个2XX 都创建一个Dialog,这些Dialog 都属于同一个呼叫。
4.1.1UAC的处理过程
a.初始INVITE 消息
由于初始的INVIT 消息是Dialog 之外的请求,因此它的构造过程需要遵循通用的Dialog 外请求消息构造过程(参见:8.1.1 节)。下面针对INVITE 消息的特殊情况进行说明:
必须包含Allow 头域,用于表示本次会话过程中UAC 支持的请求方法。必须包含Supported 头域,用于表示UAC 支持的扩展功能。INVITE 消息中可以包含SDP 信息,这时Content-Type 头域应该是application/sdp。SIP 协议中规定关于媒体协商的过程是通过在消息中携带SDP 来完成的。关于SDP 协商的过程需要遵循如下规定:INVITE 消息中携带SDP 请求,200 消息中返回SDP 响应。200 消息中携带SDP 请求,ACK 消息中返回SDP 响应。
SDP 请求和响应这个协商过程,不能并行,只能当一次交互完成之后才能发起新的协商.
b. 处理对INVITE 消息的响应
1XX 响应:在收到最终响应之前,UAC 可能收到零个、一个或者多个临时响应。
3XX 响应:一个3XX 响应中可以包含一个或者多个Contact 头域,这些头域代表被呼叫方的新的地址。UAC 可以根据具体的响应类型以及本地的业务策略来选择是否向这些地址发起新的会话请求。4XX、5XX 和6XX 响应:UAC 只能收到一个非2XX 响应。其中可以包含一个Contact 头域用于提供关于会话建立失败信息的查询地址。UAC 收到非2XX 响应,即认为INVITE 事务已经完成,向UAS发送ACK。2XX 响应:由于INVITE 请求可能被分岔(Forking),因此UAC 可能收到多个2XX 响应。这些响应通过To 头域中的tag 参数相区别,每一个响应都代表一个独立的Dialog。UAC 必须对每个2XX 都返回ACK。
4.1.2UAS 的处理过程
a. 处理INVITE 消息
正在处理:如果UAS 不能马上作出应答,它可以发送相应的1XX 响应来通知UAC 当前的处理进展(例如:振铃,被前转等)。重定向:如果UAS 希望将该请求重定向,它可以发送3XX 响应,其中携带新的被叫地址。要求UAS 向新的地址发起呼叫。拒绝:如果UAS 由于某种原因不能接受这个呼叫请求,它可以根据具体的原因,发送相应的4XX,5XX,6XX 响应。接受:UAS 返回2XX 响应,表示接受本次呼叫请求。这个响应消息同时也建立了一个Dialog。2XX 响应中必须包含Allow 头域,用于表示UAS 支持的请求方法。2XX 中必须包含Supported 头域,用于表示UAS 支持的扩展能力。如果INVITE 请求中,包含SDP 请求,那么UAS 必须在2XX 返回一个SDP 应答。UAS 必须重发2XX 直到接收到ACK 确认消息。重发间隔为T1,每次重发间隔加倍,直到达到T2。如果这时仍未收到ACK,UAS 必须结束本次会话,向UAC 发送BYE 请求。
4.2会话结束过程
会话的中止可以通过对INVITE 请求返回拒绝响应,对已建立的会话发送BYE 请求等方式来完成。
4.2.1 通过BYE 请求结束会话
a. UAC 的处理过程
会话中的任意一方可以通过发送BYE 请求来结束已经建立的会话。BYE 请求的生成与通用的Dialog 中请求消息的生成规则相同(参见第12 章)。BYE 请求对应一个新的事务。UAC 发送BYE 请求之后即认为本次会话已经结束了。
b.UAS的处理过程
UAS 收到BYE 请求之后,需要查询匹配的会话。如果找不到则返回481 响应。如果找到对应的会话,UAS 必须结束该会话。然后对BYE 返回2XX 响应。对于正在处理的请求消息,UAS 返回487 响应。
针对我们的Subcentrex的呼叫处理过成可以参见LOG培训文档,该文档将针对成功和是失败的呼叫在系统中的整个流程进行的详细的解析。
下面将演示一个具体的呼叫流程,本呼叫是NAT后面的两个设备进行呼叫,其中包括信令的传输和相应的LOG信息:
218.1.121.106:59573 218.80.220.50:5060 218.1.121.106:44619 218.1.121.106:49380
| | | | <Call><PFrame><Time>
| | | |
|>F1 INVITE (sdp)------------->| | | 1 PF:1 06:19:8.0469
| | | |
|<-------------- Trying 100 F2<| | | 1 PF:2 06:19:8.0487
| | | |
| |>F3 INVITE (sdp)-------------------------------------------->| 2 PF:3 06:19:8.1303
| | | |
| |>F4 INVITE (sdp)-------------------------------------------->| 2 PF:4 06:19:8.6370
| | | |
| |<--------------------------------------------- Trying 100 F5<| 2 PF:5 06:19:8.8375
| | | |
| |<-------------------------------------------- Ringing 180 F6<| 2 PF:6 06:19:12.0371
| | | |
|<------------- Ringing 180 F7<| | | 1 PF:7 06:19:12.0435
|

