会话初始协议ISP技术要求-中国通信行业标准(3)

时间:2008-10-19 来源: 作者: 点击:
P2 检查不负责u1.example.com ,所以它根据Route 头字段值的解析结果将请求消息发往P1。 P1 注意到自己被列在最顶端的Route 头字段值中,因而它将该值删除,消息变为: BYE sip:caller@u1.example.com SIP/2.0 既然
  

P2 检查不负责u1.example.com ,所以它根据Route 头字段值的解析结果将请求消息发往P1。
P1 注意到自己被列在最顶端的Route 头字段值中,因而它将该值删除,消息变为:
BYE sip:caller@u1.example.com SIP/2.0
既然P1 不负责u1.example.com ,并且消息中也没有Route 头字段,P1 根据Request-URI 将请求消息转发到u1.example.com 。
13 SIP 事务层
13.1 概述
SIP 是事务型的协议, 一个SIP 事务是由请求和其响应,包括临时响应和最终响应组成的。在请求是INVITE 而响应是非2xx 的响应时,对应的事务也包括ACK 消息。如果其响应是2xx,则相应的事务中不包括ACK 消息。
事务可分为客户端事务和服务器端事务。客户端事务发送请求, 而服务器端事务发送响应。客户端和服务器端事务都是一种逻辑功能,包含在任何实现此功能的实体中。
一个无状态的代理服务器没有客户端或服务器端事务功能。客户端事务负责从上层实体(称为事务用户 TU,可以是UA 或者有状态的代理服务器)接收请求,并将请求可靠的发送到服务器端事务;它也负责接收响应并将响应传送给TU, 同时过滤重复的响应和一些非法的响应,如对ACK 的响应。另外,对于INVITE 请求的非2xx 的最终响应,客户端事务还负责产生相应的ACK 响应。
服务器端事务负责从传输层接收请求并发送给上层TU, 同时滤掉从网络上收到的重复的请求。它也负责从TU 接收响应并将其发送给传输层。在INVITE 请求事务中,服务器端事务负责吸收对非2xx 的最终响应的ACK 。
2xx 的响应的重传和和对应的ACK 请求的产生是由UA Core 完成的,由UAS 重传2xx 响应, UAC 负责产生对应的ACK 。这种端到端的处理使呼叫者能够了解接受呼叫的所有用户的完整列表。所以在路径上的每个代理服务器都仅仅是转发INVITE 的2xx 响应以及对应的ACK 。
1. 13.2 客户端事务
2. 13.2.1 简述

客户端事务通过维护一个状态机来实现相应的功能。上层TU 与客户端事务通过一个简单的接口进行通信。当TU 初始化一个新的事务时,它产生一个新的客户端事务实例,要发送的SIP 请求传送给实例,并带上要发往目的地的IP 地址,端口号,和传输协议等参数。客户端事务实例开始执行状态机,同时将有效的响应上传给TU。
根据TU 发送的请求的方法类型, 有两种客户端事务实例的状态机。一种是处理INVITE 请求的客户端事务实例,称为INVITE 客户端事务;另一种是处理除INVITE 和ACK 之外的所有请求的客户端事务实例,称为非INVITE 客户端事务。没有对应于ACK 的客户端事务存在。如果TU 要发送一个ACK, 它将直接将对应的请求发送给传输层。
1. 13.2.2 INVITE 客户端事务
2. 13.2.2.1 INVITE 事务简述

INVITE 事务由三次握手组成: 客户端事务发送INVITE 请求,服务器端事务发送响应,然后客户端事务发送ACK 消息。对于UDP 等不可靠传输, 客户端事务开始以T1 的间隔重传请求,并在每次重传后将定时间隔加倍。T1 是往返时间(RTT) 的估计值,缺省为500ms 。本规范所涉及的大部分事务定时器都是以T1 为度量标准的,可以通过更改T1 的值来更改其它定时器的值。对于可靠传输,请求不进行重传。在收到1xx 的临时响应后,停止重传, 客户端事务等待进一步的响应。对于不可靠传输服务端事务可以发送另外的1xx 响应, 最后发送最终响应。对于不可靠传输, 响应周期性的进行重传, 而对于可靠传输,响应只传输一次。对于每个收到的最终响应,客户端事务都发送ACK 消息,以便使对端停止重传响应。
13.2.2.2 状态机模型
INVITE 客户端事务的状态机如图1 所示。在TU 用INVITE 请求来生成新事务时, 客户端事务首先进入Calling 状态,同时客户端事务将请求传送给传输层进行网络传输。如果使用不可靠传输协议,客户端事务必须用T1 启动定时器A;如果使用可靠传输协议,客户端事务不必启动定时器A。无论何种情况,事务都必须用64*T1 启动定时器B( 定时器B 控制整个事务的超时)。
如果定时器A 超时, 则客户端事务必须将请求进行重传, 然后必须将定时器的间隔设为2*T1 进行更新并重新启动。若A 在2*T1 秒后超时,则继续重传请求,同时A 的间隔时间继续加倍, 如此反复。上述重传只在“Calling” 状态下进行。T1 的值可根据具体的网络性质进行一定的调整,但上述的重传过程必须遵循。
如果在事务处于“Calling” 状态的情况下,定时器B 超时, 则事务应该通知TU 超时的发生。事务层不能产生ACK 。定时器B 的值在不可靠传输的情况下刚好等于重传7 次请求的时间。
|INVITE from TU Timer A fires |INVITE sent Reset A, V Timer B fires INVITE sent +-----------+ or Transport Err.
+---------| |---------------+inform TU
| | Calling | |
+-------->| |-------------->|
+-----------+ 2xx |
| | 2xx to TU |
| |1xx |
300-699 +---------------+ |1xx to TU |
ACK sent | | |
resp. to TU | 1xx V |
| 1xx to TU -----------+ |
| +---------| | |
| | |Proceeding |-------------->|
| +-------->| | 2xx |
| +-----------+ 2xx to TU |
| 300-699 | |
| ACK sent, | |
| resp. to TU| |
| | | NOTE:
| 300-699 V |
| ACK sent +-----------+Transport Err. | transitions
| +---------| |Inform TU | labeled with
| | | Completed |-------------->| the event
| +-------->| | | over the action
| +-----------+ | to take
| ^ | |
| | | Timer D fires |
+--------------+ | - |
| |
V |
+-----------+ |
| | |
| Terminated|<--------------+
| |
+-----------+
图1:INVITE 客户端事务

如果事务在“Calling ”状态收到了临时响应,则状态迁到“Proceeding” 状态。在此状态,事务不应该重传请求。同时临时响应必须上传给TU。在此状态,每个收到的临时响应都要上传给TU。
无论在“Calling ”还是“Proceeding ”状态,在收到状态码为300-699 的响应时,事务的状态都迁到“Completed ”状态,并且将响应上传到TU,同时必须生成相应的ACK 并发送到传输层进行传输。ACK 发往的地址必须和请求发往的地址具有同样的IP 地址, 端口号和传输协议。在进入“Completed” 状态后,客户端事务应该启动定时器D,对于不可靠传输定时时间至少为32 秒,而对可靠传输时间为0 秒。
在“Completed” 状态, 任何收到的重传的最终响应都必须使本端事务重传ACK, 但这些收到的重传响应不再上传给TU。如果在此状态定时器D 超时,则事务必须立刻迁到“Terminated ”状态,并将超时事件上报给TU。
在“Calling ”或“Proceeding ”状态,如果收到2xx 的响应,则事务立刻迁到“Terminated ”状态,同时将响应上传给TU。这个响应的处理方法取决于TU 是Proxy Core 还是UAC Core ,对于UAC Core 将产生相应的ACK ,而Proxy Core 则仅仅前转200(OK) 即可。这种处理的不同就是200(OK)的处理不放在事务层的原因。
事务一旦进入“Terminated ”状态,就必须将实例销毁。如果传输层收到一个找不到对应事务的响应,则直接将响应发送给TU。
13.2.2.3 ACK请求的生成
事务层生成的ACK 请求必须与原发送的请求具有同样的Calll-ID,From ,和Request-URI 头字段。ACK 的To 头字段必须与对应的响应的To 头字段具有同样的值,一般情况下因为多了Tag 参数而与原请求的To 头部不同。ACK 请求必须具有单个的Via 头字段,而且是与原请求的Top Via 头字段具有同样的值。Cseq 头字段必须具有与原请求同样的序列号,且方法必须是“ACK”。
如果原INVITE 请求具有Route 头字段,则这些字段也必须出现在ACK 请求中,这是为了保证ACK 能被接下来的无状态的代理服务器正确的路由。
本规范建议, 在对应非2xx 最终响应的ACK 请求中不应包含消息体。如果有消息体的话则分两种情况:对应响应不是415,ACK 中的消息体类型要严格限制在INVITE 中包含的消息体类型范围内;如果响应是415 ,则ACK 中包含的消息体的类型可以是在响应的Accept 头字段中所列的消息体类型。
例如对以下的请求::
INVITE sip:bob@biloxi.com SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKkjshdyff
To: Bob <sip:bob@biloxi.com>
From: Alice <sip:alice@atlanta.com>;tag=88sja8x
Max-Forwards: 70
Call-ID: 987asjd97y7atg
CSeq: 986759 INVITE

则其对应非2xx 最终响应的ACK 请求将如下所示:
ACK sip:bob@biloxi.com SIP/2.0
Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKkjshdyff
To: Bob <sip:bob@biloxi.com>;tag=99sa0xk
From: Alice <sip:alice@atlanta.com>;tag=88sja8x
Max-Forwards: 70
Call-ID: 987asjd97y7atg
CSeq: 986759 ACK

1. 13.2.3 非INVITE 客户端事务
2. 13.2.3.1 非INVITE 事务的简述

非INVITE 事务不使用ACK, 是简单的请求-响应的模式。对于不可靠数据传输,请求将首先以T1
的时间间隔进行重传,并且每次超时将T1 加倍,直到与T2 相等。如果收到了临时响应,请求的重传将继续,但重传的时间间隔为T2。服务器端事务只有在收到重传请求的情况下才将最后发送的临时或最终的响应进行重传。因此客户端事务在收到临时响应的情况下仍然重传请求是为了能使最终响应得到可靠的传输。
非INVITE 事务对2xx 响应无特殊处理。
13.2.3.2 状态机模型
非INVITE 客户端事务的状态机与INVITE 客户端事务的状态机非常相似。在TU 生成新事务时事务实例进入“Trying ”状态,此时应该设置定时器F(值为64*T1 秒),同时将请求发送到传输层进行传输。如果使用不可靠传输协议,则必须设置定时器E, 时间为T1,如果仍在该状态且E 已到期,则复位定时器E,但时间设置为min(2*T1,T2)。如果定时器再次到期,则复位min(4*T1,T2),依此类推,直到达到T2,然后将定时器时间设为T2。T2 的缺省取值为4 秒。所以对于T1 和T2 的取值,这个间隔为:500ms,1s,2s,4s,4s,4s,等等。
如果事务在“Trying ”状态定时器F 到期,则事务实例应该通知TU 该超时事件,同时状态迁到“Terminated ”状态。若在此状态期间收到临时响应,则事务实例将临时响应发送给上层TU,然后将实例状态迁到“Proceeding ”状态; 若在此状态期间收到最终响应(状态码为200-699),则事务实例必须将响应发送给上层TU, 然后将实例状态迁到“Completed ”状态。
如果事务在“Proceeding” 状态定时器E 到期, 则必须将请求再次发送给传输层进行重传, 同时定时器E 复位,值为T2 秒。若在此状态定时器F 到期,则事务实例必须通知TU 超时事件,并将状态迁到“Terminated ”状态;若在此状态收到最终响应( 状态码为200-699), 则事务实例必须将响应发送给上层TU,然后将实例状态迁到“Completed ”状态。
一旦客户端事务实例进入“Completed ”状态,事务必须启动定时器K,对于不可靠传输定时时间为T4 秒,而对可靠传输时间为0 秒。“Completed”状态的存在是为了在不可靠传输时吸收重传的响应。而T4 则代表了等待的时间,T4 的缺省值为5 秒。若在此状态定时器K 到期,则事务实例必须立刻迁到“Terminated ”状态。
一旦客户端事务实例进入“Terminated ”状态,实例必须立刻销毁。
|Request from TU
|send request Timer E V send request +-----------+
+---------| |-------------------+ | | Trying | Timer F | +-------->| | or Transport Err.| +-----------+ inform TU | 200-699 | | | resp. to TU | |1xx | +---------------+ |resp. to TU | | | | | Timer E V Timer F | | send req +-----------+ or Transport Err. | | +---------| | inform TU | | | |Proceeding |------------------>| | +-------->| |-----+ | | +-----------+ |1xx | | | ^ |resp to TU |
YD ××××—××××
| 200-699 | +--------+ |
| resp. to TU | |
| | |
| V |
| +-----------+ |
| | | |
| | Completed | |
| | | |
| +-----------+ |
| ^ | |
| | | Timer K |
+--------------+ | - |
| |
V |
NOTE: +-----------+ |
| | |
transitions | Terminated|<------------------+
labeled with | |
the event +-----------+
over the action
to take

图2:Non-INVITE 客户端事务
13.2.4 响应与客户端事务的匹配
当客户端传输层收到一个响应的时候,它必须决定由某个事务来遵循上述过程处理这个响应。在以下两种情况同时满足时,响应和一个客户端事务相匹配:
1. 1. 响应中Top Via 头字段中的branch 参数与产生此事务的原请求中Via 顶端头字段中branch 参数是相同的;
2. 2. 响应中Cseq 头字段中的方法参数与产生此事务的原请求中Cseq 头字段中的方法参数是相同的。此处需要方法匹配是因为CANCEL 请求与原请求虽属不同的事务,却具有相同的branch 参数值。

先后两个匹配同一个事务的的响应是重传的响应。
如果请求是经多播发送的, 那么它将从不同的服务端返回多个响应。所有的这些响应在Via 顶端头字段中都具有相同的brance 参数,但具有不同的To 标签值。根据上述的规则, 则第一个响应会被正常处理,而其它的响应则会视为重传。这并非错误,本规范规定, 在多播发送的情况下只处理一个响应消息。具体内容参见本规范第18.1.1 节。
13.2.5 传输错误处理
在客户端的事务实例将相应的请求发到传输层后,在传输层传输失败的情况下事务层实例应该将传输失败通知给上层TU,并将实例的状态迁为“Terminated”。
13.3 服务器端事务
服务器端事务负责将请求发送给上层TU, 并将相应的响应发送给传输层进行网络传输。服务器端事务同样通过状态机来实现相关的功能。在收到一个新的请求时, 生成一个新的服务器端事务。和客户端一样,状态机也根据请求是否为INVITE 而分为两种状态机模型。
13.3.1 INVITE 服务端事务
一个新的INVITE 请求到来时, 服务器端生成新的INVITE 事务实例, 并进入“Proceeding ”状态。如果不清楚TU 是否会在200ms 内产生临时响应或最终响应,事务实例必须生成100(Trying )临时响应。这个100 响应可以用来快速避免因请求的重传而造成的网络拥塞。关于100 响应的生成参见本规范
8.2.6。请求消息必须上传给TU。
TU 可以发送多个临时响应给服务器端事务实例。在“Proceeding ”状态下,事务实例将这些响应发送给传输层进行网络传输, 但不影响实例的状态。若在此状态收到重传的请求,则事务实例将最近一次的响应进行重传。重传请求的判断规则参见本规范17.3.3 。若在此状态收到TU 的2xx 响应,则事务实例将2xx 响应发送到传输层进行传输,但并不负责此响应的重传,2xx 响应的重传由TU 负责。然后
47
事务实例将状态迁到“Terminated ”状态。若在此状态收到TU 的300 到699 的响应,则事务实例将响应发送到传输层进行传输,并将状态迁到“Completed ”状态。对于不可靠的传输,启动定时器G,值为T1。
一旦进入“Completed ”状态,事务启动定时器H,值为64*T1 。定时器H 决定了何时放弃重传响应,它的取值与客户端事务定时器B 一致,而B 决定了客户端重传请求的时长。若定时器G 到期,则重传响应,同时将重新启动G,其取值为2*T1 和T2 的最小值,此后每次G 到期都重传响应,并将定时时长加倍,直到其值等于T2 后,将一直取T2 为时长。若在此状态收到重传的请求,则应该重传响应。
若在“Completed ”状态收到ACK 请求,则事务必须迁到“Confirmed ”状态。在此状态,忽略定时器G,所以重传将停止。
若在“Completed ”状态定时器H 到期,表示事务没收到ACK,则事务将状态迁到“Terminated” 状态,并通知上层TU 事务失败。
在“Confirmed” 状态, 事务实例可以吸收因重传响应而引起的重传的ACK 。进入“Confirmed ”状态后,事务启动定时器I,对于不可靠传输定时时间为T4 秒,而对可靠传输时间为0 秒。若在此状态定时器I 到期,则事务实例必须立刻迁到“Terminated ”状态。
一旦事务实例进入“Terminated ”状态,实例必须立刻销毁。
|INVITE
|pass INV to TU INVITE V send 100 if TU won't in 200ms send response+-----------+
+--------| |--------+101-199 from TU
| | Proceeding| |send response
+------->| |<-------+
| | Transport Err.
| | Inform TU
| |--------------->+ +-----------+ | 300-699 from TU | |2xx from TU | send response | |send response | | +------------------>+ | | INVITE V Timer G fires | send response+-----------+ send response | +--------| |--------+ | | | Completed | | | +------->| |<-------+ | +-----------+ | | | | ACK | | |
- | +------------------>+ | Timer H fires | V or Transport Err.|
+-----------+ Inform TU | | | | | Confirmed | | | | | +-----------+ |
| |
|Timer I fires |
|- |
| |
V |
+-----------+ |
| | |
| Terminated|<---------------+
| |
+-----------+

图3:INVITE 服务器端事务
13.3.2 非INVITE 服务器端事务
对于非INVITE 和ACK 的请求,生成非INVITE 服务器端事务实例,初始状态机为“Trying”状态,并将该请求发送给上层TU。一旦进入“Trying ”状态,任何收到的重传请求都将被丢弃。
在“Trying” 状态,若收到上层TU 的临时响应,服务器端事务实例进入“Proceeding” 状态,并将临时响应发送到传输层。在此状态从TU 接收到的任何临时响应都将发送到传输层进行网络传输。若在此状态收到重传的请求,则事务将最近的响应进行重传。若在此状态收到TU 的最终响应(状态码200-699),则事务迁到“Completed ”状态,同时将响应发送到传输层进行发送。
当事务进入到“Completed ”状态,必须启动定时器J,对于不可靠传输值为64*T1 秒,对于可靠传输则为0 秒。在“Completed ”状态,收到重传请求的情况下事务将最后的响应进行重传;并且在此状态,事务收到的任何TU 的最终响应都将丢弃。当定时器J 超时后,事务迁到“Terminated ”状态。
一旦事务实例进入“Terminated ”状态,实例必须立刻销毁。
|Request received |pass to TU V
+-----------+
| |
| Trying |-------------+
| | |
+-----------+ |200-699 from TU

| |send response |1xx from TU | |send response | | |
Request V 1xx from TU |
send response+-----------+send response| +--------| |--------+ | | | Proceeding| | | +------->| |<-------+ |
+<--------------| | |
|Trnsprt Err +-----------+ |
|Inform TU | |
| | |
| |200-699 from TU |
| |send response |
| Request V |
| send response+-----------+ |
| +--------| | |
| | | Completed |<------------+
| +------->| |
+<--------------| |
|Trnsprt Err +-----------+
|Inform TU |
| |Timer J fires
| |-
| |
| V
| +-----------+
| | |
+-------------->| Terminated|

| | +-----------+
图4:非INVITE 服务器端事务
13.3.3 请求与服务器端事务的匹配
在服务器收到网络上的一个请求后,它必须将请求与已有的事务进行匹配,匹配规则如下:首先检查请求的最顶端的 Via 字段中的branch 参数。如果branch 参数存在并且以“z9hG4bK ”开始,说明此参数是由与兼容的客户端事务产生的。所以此branch 参数在此客户端产生的事务中应该是
唯一的。需要满足下列条件,请求与事务相匹配:
1. 1. 请求中的branch 参数与产生事务的请求最顶端 Via 中的branch 参数相同
2. 2. 请求中的send-by 值与产生事务的请求相同,
3. 3. 除了ACK 请求,请求中的Method 要与产生事务的请求相同。匹配规则对于INVITE 以及非INVITE 事务都适用。其中send-by 参数用于匹配规则是因为有可能不同客户端事务所产生的branch 参数有可能相同。如果请求中不存在branch 参数或branch 参数不以“z9hG4bK ”开始,按照下面的规则进行匹配: 如果INVITE 请求的Request-URI,To 标签,From 标签,Call-ID,Cseq 和顶端Via 头字段与产生

事务的INVITE 请求相匹配,则该请求与事务相匹配。该情况下,INVITE 请求为原请求的重传请求。如果ACK 请求的Request-URI,From 标签,Call-ID,Cseq 中的数字(不包括方法)和顶端 Via 头字段与产生事务的INVITE 请求相匹配,并且该请求的To 标签与服务器端事务产生的To 标签相匹配,则该ACK 请求与事务相匹配。头字段对于所有其它的请求方法,如果Request-URI,To 标签,From 标签,Call-ID,Cseq 和顶端 Via 所有头字段与产生事务的请求相匹配,则匹配成功。如果一个非INVITE 请求与一个存在的事务相匹配的话,则认为它是产生这个事务的请求的重传。
因为以上匹配规则与Request-URI 有关,所以服务器端事务无法将一个响应与存在的事务匹配起来。当TU 传送一个响应给服务器端事务时,它必须被传送给响应所标明的指定的服务器端事务。
13.3.4 传输错误处理
在服务器端的事务实例将相应的响应发到传输层后,在传输层传输失败的情况下,可进行如下处理:首先,可以选择将响应发往另一个作为备份的实体。参见RFC 3263 。如果上述尝试都传输失败,事务层应该将失败通知给TU, 并将相应的事务实例的状态迁为
TERMINATED 。
13.4 相关说明
IETF draft-ietf-sip-rfc2543bis-09.txt
IETF rfc3261
14 传输
传输层负责通过网络传送请求和响应,当传输为面向连接时,还要确定请求或者响应可用的连接。
传输层可以管理永久连接,这些连接使用的传输协议有TCP 和SCTP, 或者基于TCP 和SCTP 的TLS,
包括那些开放的传输层的协议。这些连接还包括客户机或者服务器传输输层的开放连接,客户机和服务
器传输层可以共同使用该连接。可以通过该连接的远端地址、端口、传输协议所组成的三元组来检索该
连接。如果一个连接被传输层开放,该索引设成目的地IP 地址、端口和传输协议的三元组。如果一个
连接被传输层所接受,该索引设成源IP 地址、端口和传输协议的三元组。由于源端口通常是暂时的,
所以传输层所接受的连接一般不会重新使用。所以通常两个对等代理服务器在使用面向连接传输协议
时,会使用两个连接,用于各自方向发起的事务。
本规范建议, 在最后一个消息通过之后, 该连接仍需要开放一段时间。该时间段至少等于实体将一
个事务从实例进行到终止状态所用时间的最大值。这样,事务可以在其发起的连接完成(例如请求、响
应、INVITE 、用于非2xx 响应的ACK)。该时间段的值至少为64*T1 (T1 的值参见本规范17.1.1.1) 。然
而如果一个实体使用一个更大的定时器C( 参见本规范16.6 的值,这个持续时间将更长。
50
YD ××××—××××
所有的SIP 实体都必须能实现UDP 和TCP。SIP 实体也可以使用其它的协议。
与RFC2543 不同,本规范中强制UA 使用TCP 。这不是仅因为必须使用TCP 处理大块的消息的,即使一个实体从不发送大块消息,它也必须具备接收这样的消息并处理它的能力。
1. 14.1 客户端
2. 14.1.1 发送请求

传输层的客户端负责发送请求并接受响应。传输层的用户将请求、IP 地址、端口、传输协议以及用于组播目的地的TTL 传递到客户机传输层。
如果一个请求在小于200 字节或者大于1300 字节的路径 MTU 中,而该MTU 值未知,那么该请求必须使用RFC 2914 中规定的拥塞控制协议,例如TCP 协议。如果这与顶端Via 中所指定的传输协议不同, 那么顶端Via 的值需要修改。这有效的防止了使用UDP 会造成的消息碎片,并且为大块的消息提供了拥塞控制。对于UDP 来说能够处理的最大数据包就是65,535 字节并包括IP 和UDP 字头。
消息尺寸和MTU 之间的200 字节的“缓冲区”适应了SIP 中响应消息一般比请求大的情况。例如, 可以在INVITE 响应中附加了Record-Route 头字段值。有了这个额外的缓冲区,响应可以比请求大170 字节而在Ipv4 中不必被分块(假设没有IPSec 时,IP/UDP 消耗大约30 字节)。当路径MTU 未知时,基于以太网的MTU 是1500 字节来将MTU 设为1300 字节。
如果一个实体由于消息大小的缘故才需要通过TCP 发送某请求,否则该请求可以通过UDP 传输,如果建立该连接时引起下面两种情况:ICMP 协议不支持, 和重新建立TCP 连接,此时该实体就应该使用UDP 重新发送请求。这将兼容RFC2543 中不支持TCP 的要求。
向组播地址发送请求的客户机必须在Via 头字段值中附加"maddr" 参数指明目的地组播地址,对于Ipv4 来说应该增加一个值为1 的"ttl" 参数。Ipv6 的组播的内容不在本规范范围之内。这个规定对SIP 组播产生了限制。它的基本功能是"single-hop-discovery-like" 业务,也就是向一组同类的服务器发送请求, 但是只需要其中一个服务器处理该请求即可。注册时可以使用该功能。参见本规范 17.1.3 中事务处理的规定,客户机事务层应该接收第一个请求, 其余的因为包含同样的Via 分支标识符而被视为重发。
发送请求之前,客户端事务层必须在Via 头字段中插入一个"sent-by" 字段。该字段包括一个IP 地址或者是主机名和端口。本规范建议使用FQDN( 全资格域名)方式。该字段用于以下情况下发送请求。如果没有规定端口,根据传输协议不同而取不同的端口缺省值,UDP 取5060 而TCP 和SCTP 取5061 。
在进行可靠传输时, 应在收到请求的连接上发送响应。因此, 客户端传输层必须准备在同一个连接上接收响应。发生错误时,服务器可以建立一个新连接发送响应。在这种情况下,传输层也必须在源IP 地址上引入一个连接,从源IP 地址和"sent-by" 字段中所指的端口发送请求。它还必须准备在服务
51
器端按照的Section 5 中程序选择的地址和端口上引入一个连接。
在不可靠的单播传输时,客户端传输层必须准备在源IP 地址上接收响应,源IP 地址就是发送请求的地址,端口号为"sent-by" 字段中的值。另外,与可靠传输一样,某些特定情况下,响应也将被传输到别处。客户机还必须准备在服务器依照RFC 3263 的第5 章中程序选择的地址和端口上接收响应。
在组播的情况下,客户端传输层必须作为发送请求的组播群中的一员在与发送请求相同的组播群和端口上接收响应。
如果一个原有的连接对于某请求的目的IP 地址、端口和传输协议开放,则本规范建议这个连接用于发送请求而另外一个连接也可以开放并使用。
如果某请求使用组播发送, 它就会被送往一组用户所提供的地址、端口和TTL 。如果某请求使用不可靠的单播传输方式发送,它就会被送往传输用户所提供的IP 地址和端口。
14.1.2 接收响应
客户机传输层收到响应后需要检查顶端Via 的值。如果"sent-by" 参数中的值与客户端传输层插入到请求中的值不一样,该响应就必须被丢弃。
如果存在一些客户端事务,客户机传输层将在原有的事务中查找与该响应所匹配的事务,具体匹配程序参见本规范17.1.3 。如果找到匹配事务,就必须将该响应送到对应的事务中处理。反之该响应就必须被送到核心服务器(无论是无状态代理服务器还是有状态代理服务器还是UA) 做进一步处理。根据核心服务器的不同,对这些响应有不同的处理。
1. 14.2 服务器
2. 14.2.1 接收请求

服务器可以通过DNS 来搜索对方服务器,搜索结果以SIP 或者SIPS URI 形式给出,服务器应该通过搜索结果中的任何IP 地址、端口和传输协议来接收请求。另外,必须将一个URI 放到REGISTER 请求或者重定向响应中的Contact 字段,或者放在请求或者响应中的Record-Route 头字段中。URI 也可以用放到网页或名片上的形式给出。本规范建议,服务器在公共接口上接受请求是应使用默认的端口值(TCP 和UDP 是5060,而TCP 上的TLS 是5061), 私有网络或者同一个主机上运行多个服务器的情况除外。因为如果消息太大则必须使用TCP 而不能用UDP 传输,所以任何使用UDP 端口和接口的服务器必须能够在TCP 上使用同样的端口和接口。反之,服务器不必因为使用了TCP 的一个特定的端口和接口就要求在UDP 情况下使用同一特定端口和接口。服务器传输层通过任何传输协议收到请求后, 必须检查Via 头字段顶端的"sent-by" 参数的值。如果"sent-by" 参数的主机位置包含一个域名或者包含一个不同于数据包源地址的IP 地址,服务器必须在Via 头字段中添加一个"received" 参数。该参数必须包括所收数据包的源地址,这样,服务器传输层就可以将响应发送到发出请求的源IP 地址。
52
YD ××××—××××
服务器传输层收到的请求,部分如下:
INVITE sip:bob@Biloxi.com SIP/2.0
Via: SIP/2.0/UDP bobspc.biloxi.com:5060 在源IP 地址192.0.2.4 处收到该请求。在传输层继续传输请求之前必须添加一个"received" 参数,因此该请求部分如下:
INVITE sip:bob@Biloxi.com SIP/2.0 Via: SIP/2.0/UDP bobspc.biloxi.com:5060;received=192.0.2.4 然后,服务器传输层将在服务器端事务中寻找与请求相匹配的事务。匹配规则参见本规范 17.2.3 。
如果找到了对应的服务器事务, 就将请求送到这个事务来处理。如果没有找到相匹配的事务, 就将请求送到核心服务器,并建立一个新的服务器端事务来处理它。如果UAS 核心服务器对INVITE 请求发出2xx 响应,服务器事务即终结。这就意味着如果ACK 到达, 将没有相匹配的服务器事务,基于上述原则,ACK 就被送往UAS 核心进行处理。
14.2.2 发送响应
服务器传输层使用Via 字段的顶端值来决定将响应发送目的。具体过程如下:

。如果"sent-protocol" 为可靠的传输协议,如TCP 或者 SCTP, 或者基于TCP 或 SCTP 的TLS, 且现有的连接仍然可用,则必须使用该连接传输响应到建立该事务的初始请求的源地址。这就要求服务器传输层保持服务器端事务和传输连接的关联。如果该连接不可用,服务器应与"received" 参数中的IP 地址之间开放一个新连接,并使用"sent-by" 中的端口值,如果没有指定端口就使用该传输协议的缺省端口值。如果该连接失败,服务器应该根据RFC3263 中的程序确定所要开放的连接的IP 地址和端口并向其发送响应消息。
。否则,如果Via 字段包含"maddr" 参数, 就必须将响应转发到参数中所列的地址,所用端口为"sent-by" 中指定端口值,如果没有指定,端口值为5060 。如果地址为组播地址,就应该使用"ttl"参数中指定的TTL 值来发送响应,如果该参数不存在, TTL 的值为1。
。不可靠的单播传输的情况下,如果Via 含有"received" 参数,则响应就被送往"received" 中指定的地址,所用端口为 "sent-by" 中指定端口值, 如果没有指定,端口值就为5060 。如果传输失败,例如得到ICMP " 端口不可达"响应,就应该使用RFC3263 中的Section 5 的程序来确定响应发送的目的。
。否则, 如果没有接收者标签,就应该将响应送到"sent-by" 中指定的地址。
14.3 数据帧
面向消息传输的情况下( 例如UDP), 如果消息包含Content-Length 头字段, 则消息体则被应为该
YD ××××—××××
字段所指示的长度。超长的数据包必须被丢弃。如果传输的数据包在消息体结束之前结束,则产生错误。如果消息是一个响应,则它必须被丢弃。如果消息为一个请求,实体就应该产生一个400 (Bad Request) 响应。如果该消息没有Content-Length 头字段,那么消息体的长度就认为是所传输的数据包的长度。
面向流传输的情况下(例如TCP)
,Content-Length 头字段指示消息体的大小。面向流传输的情况下必须使用Content-Length 头字段。
14.4 错误处理
如果传输的用户通过不可靠传输协议传输消息,并产生ICMP 错误,则按照ICMP 错误的类型确定处理方法。如果为主机、网络、端口或者协议不可用的错误或者参数错误, 应由传输层通知用户。源终止和TTL 超时的ICMP 错误都将忽略。
如果传输的用户要求通过可靠传输协议传输消息且连接失败,那么传输层应该通知用户。
15 普通的消息成分
15.1 SIP 和SIPS URI
SIP 和SIPS URI 用于指示一个通信资源。像所有的URI 一样, SIP 或SIPS URI 也可以用于网页、电子邮件消息和出版物。其中包含了与该通信资源建立并维持会话所需要的信息。
通信资源的例子如下:
。在线业务的用户
。多方电话的情况
。消息系统的语音信箱
。网关业务的PSTN 号码
。某组织里的一个组( 例如“销售组”或者“技术支持”)
SIPS URI 所指示的为安全的资源, 即,UAC 与该URI 所属的域之间使用TLS 传输。该资源与某个用户间通信是安全的, 且所使用安全机制由该域的本地策略所决定。如果希望得到安全的通信, 任何由SIP URI 所指示的资源在改变其URI 方案之后可以升级至SIPS URI 。
15.1.1 SIP URI 的构成
"sip:"和“sips”的方案参见 RFC 2396 。格式类似于邮件 URL,分别规定SIP 头字段和SIP 消息体。这就可以在网页上或者电子邮件消息里使用URI 规定会话的主题、媒体类型和紧急程度等。SIP URI 的通用格式为:
sip:user:password@host:port;uri-parameters?headers
SIPS URI 的格式也是一样的,但方案是SIPS 而不是SIP。
以上符号定义如下:user: 指定被寻址的主机资源的标识符。"host" 通常用来指示一个域。URI 中"userinfo" 由user 和password 字段以及 @ 符号组成。如果目的主机没有用户或者主机本身就是被指定的资源, 则userinfo 部分为可选。如果有 @ 符号,那么user 字段就不可为空。如果被寻址的主机可以处理电话号码,例如,IP 电话网关,其telephone-subscriber 字段就可以用来作为user 字段,SIP URI 中telephone-subscriber 的编解码方式参见本规范 19.1.2 。Password:password 与user 相关。SIP 和SIPS URI 的语法中允许该字段存在。但是本规范中不建议使用该字段。因为鉴权信息以明码文本的形式通过,所以几乎在所有的情况下都不安全。password 只是user 部分的延伸,本规范不对其进行特殊的定义,可以把"user:password" 部分看作一个字符串。Host:指定SIP 资源。Host 部分包含一个FQDN 或者是一个数值表示的IPv4 或者IPv6 地址。本规范建议该字段使用FQDN 方式。Port:指定请求要被发送的端口。 URI parameter :包括transport, maddr, ttl, user, method 以及lr 参数。这些参数用于以URI 构建一个请求,它们附加在hostport 之后, 以分号隔开,其格式为: parameter-name "=" parameter-value 虽然一个URI 可以有若干个参数,但是一个参数名最多只能出现一次。 Transport :用来确定发送SIP 消息的传送机制, 见RFC 3263 的规定。SIP 可以使用任何网络传送协议。各种协议的参数名的定义参见UDP、 TCP 和SCTP 的相关规范。 Maddr: 用于指定用户所要联系的服务器地址,它优先于host 字段的地址。Maddr 存在时,URI 中的port 和 transport 字段都用于maddr 所指定的地址。为了发送请求,需要获得目的地的地址、端口以及传输协议。Maddr 字段是松散源路由的一个简单的形式。它允许URI 指定一个到达目的地时必须通过的代理服务器。本规范不建议在该路径上继续使用maddr 参数,而是应该使用文件中讲的另外一种路由机制来预先建立一个路径组,它含有一个描述所要通过的节点的完整URI。 Ttl:UDP 组播数据包的生存时间值,只能用于maddr 为组播地址并且传送协议是UDP 的情况下。例如确定对于 alice@atlanta.com 的呼叫,使用ttl 值为15,组播地址为239.255.255.1,URI 形式如下:sip:alice@atlanta.com;maddr=239.255.255.1;ttl=15
这组有效的telephone-subscriber 字符串是有效的user 字符串的一个子集。URI 中的
user 参数用来区分那些电话号码和user 名不同的URI 。如果user 字符串包含一个格式为
telephone-subscriber 的电话号码,则应该存在"phone" 这个值。即使没有这个参数, 如
果本地用户名的规定允许,SIP URI 也可以把 @ 之前的部分看做一个电话号码。Method: 规定由URI 构建SIP 请求的方法,由方法参数指定。
1r: 该参数存在的情况下,用来指示负责该资源的实体实施路由机制。该参数可以存在于URI
代理服务器中Record-Route 头字段,也可以存在于预先建立的路由组URI 中。一个基于
URI 发送的请求如果没有1r 参数, 则接收实体就被认为执行的严格路由机制并重定消息
格式来保存Request-URI 中原有信息。既然URI 参数机制是可扩展的,SIP 实体就必须忽
略其不理解的URI 参数。 Headers: 该字段位于由URI 构建的请求消息中。SIP 请求的Headers 字段可以在URI 中用"?"来指定。Header 的名字和值是由&分开的hname = hvalue 对。当hname 为"body" 时表明相关的hvalue 是SIP 请求的消息体。
dialog
reg./redir. Contact/
default Req.-URI To From Contact R-R/Route external user --o o o o o o password --o o o o o o host --m m m m m m port (1) o --o o o user-paramip o o o o o o method INVITE -----o maddr-param --o --o o o ttl-param 1 o --o -o transp.-param UDP o --o o o lr-param --o ---o o other-param --o o o o o o headers -----o -o
表1 SIP URI 中各成分的使用及其缺省值(1): 缺省的port 值与传送协议有关。sip: 使用 UDP, TCP, 或者 SCTP 时为5060。sip: 使用基于TCP 的TLS 是5061 。
表一总结了在URI 出现在不同的上下文中时SIP 和SIPS URI 各个组成部分的用法。External 这一列讲述了URI 位于SIP 消息体之外的情况,例如网页上或者商业名片上。标注"m"表示强制使用,标注"o"表示可选, 标注"-" 表示禁止。如果URI 中有禁止项存在,SIP 实体处理到它的时候应该忽略这些项。第二列指出如果一个可选项没有出现时的缺省值。"--" 指出这项或者不可选或者没有缺省值。
Contact 头字段中的URI 根据字段出现的上下文的不同而有不同的限制。一组适用于建立和维持对话的消息(INVITE 和200 响应), 另外一组适用于注册和重定向消息(REGISTER ,对它的200 (OK) 响应以及对于任何方法的3xx 响应)。
15.1.2 字符转义的要求
在SIP URI 中,定义一组需要转义的字符时,就要遵循RFC 2396 中的要求使用""%" HEX HEX" 机制进行转义。RFC 2396 规定:任何给定的URI 组成部分中所保留的字符集实际是由该组成部分所定义的。一般情况下,如果一个URI 的字符使用转义的US-ASCII 码所代替后语义被改变,这个字符就应该保留。US-ASCII 字符之外的字符, 例如空格、控制符还有URI 中的分隔符都必须被转义。URI 不可以包含未被转义的空格和控制符。
对于每个部分来说,有效的BNF 的扩展定义了可以不用转义的字符。除此以外的字符都要被转义。例如"@" 不是user 成分的字符,因此user 为j@s0n 时,至少 @ 符需要编码为"j%40s0n" 。扩展的hname 和 hvalue 符号表明所有的URI 头字段名和值中保留的字符必须被转义。
User 部分的telephone-subscriber 子集的转义有特殊的要求。如RFC 2806[9] 所述,telephone-subscriber 未保留的字符集中包含许多不同语法形式的字符,当使用SIP URI 时,这些字符需要被转义。任何telephone-subscriber 中出现的字符如果没有出现在BNF 的扩展定义中则必须被转义。
SIP 和SIPS URI 中的host 部分不允许字符转义(%字符在扩展中无效)。将来国际化域名定案之后这个规定可能会发生改变。现在的具体实现中,不可以通过将所收到的host 中的转义字符理解为其未转义时字面的意思来提高鲁棒性。但是如果要求满足IDN 的要求的话, 将来的情况可能就完全不同。
15.1.3 SIP URI 举例
sip:alice@atlanta.com
sip:alice:secretword@atlanta.com;transport=tcp
YD ××××—××××
sips:alice@atlanta.com?subject=project%20x&priority=urgent sip:+1-212-555-1212:1234@gateway.com;user=phone sip:alice@192.0.2.4 sip:atlanta.com;method=REGISTER?to=alice%40atlanta.com sip:alice;day=tuesday@atlanta.com 最后一个例子的user 字段值为"alice;day=tuesday" 。转义规则允许该字段中分号保留未转义。本
协议的目的就是要求该字段不透明,所以这个值如何构成也仅仅在负责该资源的SIP 实体中有意义。
15.1.4 URI 比较
本规范中定义的某些操作要求确定两个SIP 或SIPS URI 是否等价。本规范规定,注册服务器需要
比较REGISTER 请求中的Contact URI 的绑定,并根据下列规则判定SIP 或SIPS URI 是否等价: . SIP 和SIPS URI 永远不等价. 比较SIP 和SIPS URI 的userinfo (含密码的userinfo 或者telephone-subscriber 格式)时
需要区分大小写,除非特殊要求,比较URI 的其余成分都不区分大小写。. 比较SIP 和 SIPS URI 时,参数和头字段的顺序与等价性无关。. 除了“保留”组(参见RFC 2396) 以外, 所有的字符都等价于它们对应的""%" HEX HEX" 编码。. DNS 搜索主机名得到的IP 地址与该主机名不一致。. 两个URI 等价,要求用户、密码、主机、端口都必须一致。省略用户部分的URI 与包含用户部分的URI 不一致。省略密码的URI 与包含密码的URI 也不一致。省略任何含有缺省值部分的URI 与包含该部分并且指定值等于缺省值的URI 不一致。例如,省略
掉可选的端口的URI 与指定端口为5060 的URI 不一致,transport-parameter, ttl-parameter, user-parameter, 以及 method 都是同样道理。(规定sip:user@host 与sip:user@host:5060 不等价与RFC 2543 规定完全不同。)从相同的URI 中得到的地址等价。sip:user@host:5060 的端口总是5060 而sip:user@host 可以通过[4] 的DNS SRV 机制解析为另外的端口。
. URI 的参数比较规则如下: 具体的每个字段的规定参见Section 20 。
- 两个URI 中出现的参数必须一致。
- user, ttl, 或method 参数只在其中一个URI 中出现,即使它们包含有缺省值,也一定不
能与另外的URI 一致。
- 包含maddr 参数的URI 与不包含maddr 的URI 不一致。
- 其余的参数如果只在其中一个URI 中出现时, 比较的时候,忽略不计。
- URI 的header 成分一定不能忽略。两个一致的URI 中必须同时包含成分一致的header 。

下列每组URI 都是等价的:sip:%61lice@atlanta.com;transport=TCP sip:alice@AtLanTa.CoM;Transport=tcp
sip:carol@chicago.com
sip:carol@chicago.com;newparam=5
sip:carol@chicago.com;security=on

sip:biloxi.com;transport=tcp;method=REGISTER?to=sip:bob%40biloxi.com sip:biloxi.com;method=REGISTER;transport=tcp?to=sip:bob%40biloxi.com
sip:alice@atlanta.com?subject=project%20x&priority=urgent
sip:alice@atlanta.com?priority=urgent&subject=project%20x

以下每组URI 不等价: SIP:ALICE@AtLanTa.CoM;Transport=udp (用户名不同) sip:alice@AtLanTa.CoM;Transport=UDP
sip:bob@biloxi.com (可以解析为不同的端口)
sip:bob@biloxi.com:5060

sip:bob@biloxi.com (可以解析为不同的传送协议)
sip:bob@biloxi.com;transport=udp

sip:bob@biloxi.com (可解析为不同的端口和传送协议)
sip:bob@biloxi.com:6000;transport=tcp

sip:carol@chicago.com (header 成分不同)
sip:carol@chicago.com?Subject=next%20meeting

sip:bob@phone21.boxesbybob.com (即使192.0.2.4 就是phone21.boxesbybob.
sip:bob@192.0.2.4 com 的解析结果也不能等价)
注意等价性不可以传递:

. o sip:carol@chicago.com 和sip:carol@chicago.com;security=on 等价
.o sip:carol@chicago.com 和sip:carol@chicago.com;security=off 等价
. o sip:carol@chicago.com;security=on 和
sip:carol@chicago.com;security=off 不等价


15.1.5 由URI 构成请求
直接由URI 构成请求的时,商业名片、网页以至协议内部资源(如已注册地址)的URI 的头字段或者消息体可能包含一些不合适部分。
构成请求中必须包括Request-URI 中的transport, maddr, ttl, user 参数。如果URI 包含一个method 参数,它的值必须作为请求的方法。Request-URI 中不可以有method 参数。未知的URI 参数必须放在消息的Request-URI 中。
出现在URI 中的头字段或者消息体都应当包含在消息里,基于请求中每个组成部分明显标记该请求。
具体实现中,不应明显标记那些容易受到威胁的头字段From, Call-ID, CSeq, Via, 和Record-Route 。
具体实现中,为了在恶意攻击的情况下不被作为不知情的代理利用,不可以明显标记那些请求的Route 字段的值。
有些头字段可能会引起位置或能力的错误判断,所以不应该明显标记它们。包括Accept, Accept-Encoding, Accept-Language, Allow, Contact, Organization, Supported, User-Agent 。
具体实现中, 应当校验描述性头字段的准确性, 包括:Content-Disposition, Content-Encoding, Content-Language, Content-Length, Content-Type, Date, Mime-Version, 和 Timestamp 。
如果从给定的URI 构建的请求不是有效的SIP 请求,那么该URI 也是无效的。该请求不应被传输, 并应寻找出现无效URI 的原因。构建请求无效的原因有很多,包括头字段语法错误,URI 参数组合无效, 消息体描述错误等。
发送一个由给定的URI 构成的请求中所要求的能力可能难以达到。例如,URI 可能指定一种不可实现的传送协议或者扩展。这种情况下应该拒绝发送这个请求而不是修改它来适应它的能力。不可以发送需要某个它不支持的扩展协议的请求。
YD ××××—××××
例如, 这种请求可以通过现有的Require 头参数来构造, 也可以通过或方法URI 参数来构造,该参数带有未知的值或明确不支持的值。
15.1.6 SIP URI 和tel URL 的关联
如果一个tel URL 要被转换为SIP URI 时,tel URL 中的整个telephone-subscriber 部分和一些
参数都被放在SIP URI 的userinfo 中。例如: tel:+358-555-1234567;postd=pp22 变成sip:+358-555-1234567;postd=pp22@foo.com;user=phone 而不是sip:+358-555-1234567@foo.com;postd=pp22;user=phone 通常,以这种方式,等价的"tel" URL 转变成的SIP 或SIPS URI 可能不等价。SIP URI 中的userinfo
比较的时候区分大小写。tel URL 中大小写不区分的部分和tel URL 参数重新排序虽然不影响tel URL
的等价性,但是转变成SIP 或SIPS URI 就不等价了。例如: tel:+358-555-1234567;postd=pp22 tel:+358-555-1234567;POSTD=PP22 等价
但是sip:+358-555-1234567;postd=pp22@foo.com;user=phone sip:+358-555-1234567;POSTD=PP22@foo.com;user=phone 不等价。同理tel:+358-555-1234567;postd=pp22;isub=1411 tel:+358-555-1234567;isub=1411;postd=pp22 等价但是sip:+358-555-1234567;postd=pp22;isub=1411@foo.com;user=phone sip:+358-555-1234567;isub=1411;postd=pp22@foo.com;user=phone 不等价。
为减轻这个问题,将放到userinfo 部分的telephone-subscriber 中大小写不区分的部分统一改为小写(tel URL 所有的成分除将来扩展的参数以外都是大小写不区分的),telephone-subscriber 参数按照名字排序(isdn-subaddress 和post-dial 这种参数除外,它们总是排在前面)。根据上面的规定,
tel:+358-555-1234567;postd=pp22
tel:+358-555-1234567;POSTD=PP22 都变为
sip:+358-555-1234567;postd=pp22@foo.com;user=phone

tel:+358-555-1234567;tsp=a.b;phone-context=5
tel:+358-555-1234567;phone-context=5;tsp=a.b 都变成
sip:+358-555-1234567;phone-context=5;tsp=a.b@foo.com;user=phone

15.2 选项标签
选项标签是用来指定SIP 中扩展选项的识别符且为唯一的。这些标签用于Require, Proxy-Require, Supported 以及Unsupported 这些头字段中。这些选项以“选项参数=符号” 的形式作为参数出现在这些头字段中。选项标签在RFC 的相关标准中定义。为了可以保证厂商互通性,可参考IANA 注册的选项标签。
15.3 标签
"tag"参数用于SIP 消息中的To 和From 头字段。它通常用来识别一个对话,由Call-ID 和对话的双方各一个的标签组成。当UA 在对话之外发送请求的时候, 它只包含一个From 标签,提供“一半”对话ID。对话由收到响应结束, 双方在To 标签里提供另一半ID。分叉代理的SIP 请求即可以由一个请求建立多个对话。因此, 对话双方都必须要有标识符: 没有接收者确认, 发件人不能确认这个对话是由一个请求建立的多个对话的哪一个。
UA 生成一个标签插入到请求或者响应中,这个标签必须是全局唯一的并且至少是32 比特的随机编码。当UA 要将自己加入一个会话中去,它需要在INVITE 请求的From 头字段中插入一个标签,在其响应的To 头字段中插入一个不同的标签。同样,两个对于不同呼叫的INVITE 有不同的From 标签,对于两个不同的呼叫的响应也有不同的To 标签。
除了要求全局唯一,根据具体实践不同对建立标签的规则也有不同的要求。系统在允许的范围之内出错,标签有助于将对话倒换到备用的服务器上。在出错的服务器上通过备份可以识别出这个对话的部分请求,UAS 可以选择标签来恢复该对话以及其它的相关状态。
16 头字段
本章完整的列举了头字段的语法、语义、用法。头字段与各种方法和代理服务器的的关系总结于表2 和表3。Header field where proxy ACK BYE CAN INV OPT REG
Accept R
Accept 2xx
Accept 415
Accept-Encoding R
Accept-Encoding 2xx
Accept-Encoding 415
Accept-Language R

-o -o m* o ---o m* o -c -c c c -o -o o o ---o m* o
-c -c c c -o -o o o
Accept-Language 2xx
Accept-Language 415
Alert-Info R
Alert-Info 180
Allow R
Allow 2xx
Allow r
Allow 405
Authentication-Info 2xx
Authorization R
Call-ID c
Call-Info
Contact R
Contact 1xx
Contact 2xx
Contact 3xx
Contact 485
Content-Disposition
Content-Encoding
Content-Language
Content-Length
Content-Type
CSeq c
Date
Error-Info 300-699
Expires
From c
In-Reply-To R
Max-Forwards R

ar ar
r ar
d
ar
r a a
r
amr
- - - o m* o
- c - c c c
- - - o -
- - - o -
- o - o o o
- o - m* m* o
- o - o o o
- m - m m m
- o - o o o
o o o o o o
m m m m m m
- - - o o o
o - - m o o
- - - o -
- - - m o o
- o - o o o
- o - o o o
o o - o o o
o o - o o o
o o - o o o
t t t t t t
* * - * * *
m m m m m m
o o o o o o
- o o o o o
- - - o o
m m m m m m
- - - o -
m m m m m m

Min-Expires 423
MIME-Version
Organization

-----m o o -o o o ar ---o o o
Table 2: 头字段摘要, A—O
Header field where proxy ACK BYE CAN INV OPT REG ___________________________________________________________________ Priority R ar ---o - Proxy-Authenticate 407 ar -m -m m m Proxy-Authenticate 401 ar -o o o o o Proxy-Authorization R dr o o -o o o Proxy-Require R ar -o -o o o Record-Route R ar o o o o o Record-Route 2xx,18x mr -o o o o Reply-To ---o - Require ar -c -c c c Retry-After 404,413,480,486 -o o o o o
500,503 -o o o o o
600,603 -o o o o o Route R adr c c c c c c Server r -o o o o o Subject R ---o - Supported R -o o m* o o Supported 2xx -o o m* m* o Timestamp o o o o o o To c(1) r m m m m m m Unsupported 420 -m -m m m User-Agent o o o o o o Via R amr m m m m m m Via rc dr m m m m m m
Warning r
WWW-Authenticate 401
WWW-Authenticate 407

-o o o o o ar -m -m m m ar -o -o o o
(1): 附加标签的复本Table 3: 头字段摘要, P—Z; "where" 列是可以使用该头字段的请求和响应的类型。每个值的含义如下:
. R:该头字段只能用于请求;
. r:该头字段只能用于响应;
2xx, 4xx 等等:该头字段可以用于的响应代码;


. c:该头字段从请求中复制到响应中。
"proxy" 列讲述的是代理服务器可以在该头字段上进行的操作:

. a:如果没有该字段,代理服务器可以增加或者连接该字段;
. m:可以修改头字段原有的值;
. d:可以删除一个头字端的值;
. r:代理服务器可以读该字段,因此该字段一定不能加密。
剩下的六列涉及的是某方法中可以存在的头字段:

. c: Conditional ,即该头字端的要求依赖于消息的上下文;

. m: mandatory, 即该头字段是强制使用的;
m*: 该头字段应该被发送, 但是客户机/服务器可以接收没有该字端的消息;

. o: optional, 即该头字段是可选的;

. t:该头字段应该被发送,但是客户机/服务器可以接收没有该字端的消息。如果使用基于流的传送协议(例如TCP), 必须含有该头字段。

*:消息体不为空时,该头字段是必需的。
-:不可使用该字段。

"可选的"意味着在请求中或者响应中可以包含该头字段,但是 UA 也可以忽略它,Require 字段例外。"强制的"要求请求中或者响应中必须含有该头字段,收到该请求的UAS 或者UAC 必须能够理解该字段。"不可使用"要求请求消息不可以含有该头字段,UAS 必须忽略含有这些字段的请求消息; 同样,对于响应,标注了"不可使用"的头字段意味着UAS 不可以将该字段放于响应中,并且UAC 必须忽略响应中的该字段。
YD ××××—××××
UA 应该忽略它所不理解的扩展的头字段参数。当整个消息太大时,某些普通的头字段可以使用缩略形式。Contact, From, 以及To 字段都包含一个URI 。如果该URI 包含逗号、问号或者分号, 该URI 必须用三角括号括起来。任何URI 参数也都包括在这些三角括号内。如果某URI 没有在三角括号内并且参数使用分号分隔,那么这些参数就认为是头字段参数,而不是URI 参数。
16.1 Accept 头字段
Accept 头字段参照HTTP 的语法规定,语义也基本相同,唯一不同的是如果Accept 头字段不存在, 服务器应该默认其值为application/sdp 。如果Accept 字段为空,意味着没有可接受的媒体类型。举例如下:
Accept: application/sdp;level=1, application/x-private, text/html
16.2 Accept-Encoding 头字段
Accept-Encoding 字段类似于Accept, 限制响应中可接受的内容编码Accept-Encoding 字段允许为空。它等价于Accept-Encoding: identity ,也就是说只有identity 时允许没有编码。如果没有Accept-Encoding 字段,服务器应该假设缺省值是identity 。
16.3 Accept-Language 头字段
Accept-Language 头字段用来在请求中指定响应中首选使用的语言,用于响应中作为消息体的原因
描述、对话描述或者状态响应。若无该字段服务器应该假定客户机接受任何一种语言。 Accept-Language 的语法遵照HTTP ,基于"q"参数排序的规定也适用于SIP。举例如下:Accept-Language: da, en-gb;q=0.8, en;q=0.7
16.4 Alert-Info 头字段
Alert-Info 位于INVITE 请求时,该字段对UAS 定义了另外一个可用的铃音。当Alert-Info 头字段位于180(Ringing) 响应中时, 该字段对UAC 定义了另外一个可以使用的回铃音。代理服务器插入该字段是可以提供一种独特的铃声。
但是Alert-Info 字段引入了安全隐患,具体内容参见本规范 20.9 。另外,用户应该也可以修改铃声能够使铃声可用。这有助于防止由于不信任的实体使用了该字段而导致通信中断。举例如下:
Alert-Info: <http://www.example.com/sounds/moo.wav>
16.5 Allow头字段
该字段列出请求发起UA 所支持的方法。UA 能理解的所有方法就必须列于该头字段中。消息中若无该头字段,则意味UA 未提供任何关于它所支持的方法的信息,并不意味着UA 不支持任何方法。响应消息中的Allow 头字段包含OPTIONS 头字段以外其它的方法的, 因此可以减少所需消息数量。例如:
YD ××××—××××
Allow: INVITE, ACK, OPTIONS, CANCEL, BYE
16.6 Authentication-Info 头字段
Authentication-Info 头字段为通信双方提供HTTP 分类鉴权信息。如果某请求已经基于Authorization 头字段完成了鉴权,那么UAS 可以在该请求的2XX 的响应中包含一个Authentication-Info 字段。语法和语义的规定见RFC 2617 。例如:
Authentication-Info: nextnonce="47364c23432d2e131a5fb210812c"
16.7 Authorization 头字段
Authorization 头字段中含有一个UA 的鉴权证书。关于该头字段的用法参见本规范 22.2 。关于
HTTP 鉴权的语法和语义参见本规范22.4 。
Authorization 和Proxy-Authorization 头字段不遵循多头字段值的一般规则。虽然多个数值之间没有逗号分隔,该头字段名仍可以出现多次。并且不可以按照7.3 中的规则将其合并未一个头字段行。下例中的Digest 参数没有引号:
Authorization: Digest username="Alice", realm="atlanta.com",
nonce="84a4cc6f3082121f32b42a2187831a9e",
response="7587245234b3434cc3412213e5f113a5432"

16.8 Call-ID 头字段
Call-ID 头字段唯一的标识某个客户端的某个特定的邀请或所有的注册请求。一个多媒体会议可以发起几个Call-ID 不同的呼叫, 例如,某用户可以多次邀请某人参与同一个会议。Call-ID 区分大小写并逐字节比较。缩写形式为i。例如:
Call-ID: f81d4fae-7dec-11d0-a765-00a0c91e6bf6@biloxi.com
i:f81d4fae-7dec-11d0-a765-00a0c91e6bf6@192.0.2.4
16.9 Call-Info 头字段
Call-Info 头字段若在请求中则提供主叫的附加信息,若在响应中来则提供被叫附加信息。"purpose" 参数描述了URI 的用途;"icon" 参数指定主叫或者是被叫的表示图像;"info" 参数则为主叫或者被叫的一般描述;"card" 参数用于提供一个商务名片。其余的参数可以通过IANA 注册,具体参见本规范27 章。
但是,使用Call-Info 字段可能引起安全隐患。如果某被叫收到一个恶意主叫提供的URI,那么该被叫可能会显现一些不恰当或者攻击性的内容,或者一些危险的或者非法的内容。因此本规范建议, 仅当UA 能够证明发出Call-Info 字段的实体是真实并可信的,该UA 才能使用Call-Info 的信息。这并一定要求是对等的UA, 代理服务器也可以在请求中插入该字段。例如:
Call-Info: <http://wwww.example.com/alice/photo.jpg> ;purpose=icon, <http://www.example.com/alice/> ;purpose=info
16.10 Contact 头字段
Contact 字段的值含有一个URI,其含义取决于该字段所在的请求或者响应的类型。
Contact 头字段值中还可以包含一个显示名称、含有URI 参数的URI 和头字段参数。本规范定义了Contact 参数"q" 和 "expires" 。这些参数只用于REGISTER 请求及其响应以及3xx 响应。
当Contact 头字段包含一个显示名称的时候,带有所有的URI 参数的URI 应放于三角括号<>中,否则,URI 后面的参数都认为是头字段参数而不是URI 参数。
即使"display-name" 为空,只要"addr-spec" 包含逗号、分号或者问号,也必须使用"name-addr" 中的格式。名字和"<" 之间LWS 可有可无。
解析显示名称、URI、URI 参数以及头字段参数的规则同样适用于To 和From 头字段。
Contact 头字段的作用类似于HTTP 中的Location 头字段。但是HTTP 的Location 头字段只允许一个不用引号标注的地址。由于URI 中可以包括逗号和分号,它们可能被误认为头字段或者参数的分隔符。
------分隔线----------------------------
顶一下
(2)
100%
踩一下
(0)
0%
------分隔线----------------------------
最新评论 查看所有评论
发表评论 查看所有评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
推荐内容
  • VoIP的配置选择

    前面,我们已经围绕Vo I P 讨论了一些问题。现在,让我们讨论几种Vo I P 的配置和拓扑...

  • SIP协议介绍

    介绍 通信提供商及其合作伙伴和用户越来越渴求新一代基于 IP 的服务。现在有了 SIP协...

  • IP电话协议H.323协议 MGCP协议 SIP协议比较

    随着IP电话应用的普及,建立终端设备和网关的可扩展网络已成为业界面临的一大技术挑战...