Skip to main content

14. 修改现有会话 (Modifying an Existing Session)

成功的INVITE请求 (参见第13节) 使用提供/应答模型在两个用户代理之间建立对话和会话。第12节解释了如何使用目标刷新请求修改现有对话 (例如, 更改对话的远程目标URI)。本节描述如何修改实际会话。此修改可能涉及更改地址或端口、添加媒体流、删除媒体流等。这是通过在建立会话的同一对话内发送新的INVITE请求来完成的。在现有对话内发送的INVITE请求称为re-INVITE (重新INVITE)。

请注意, 单个re-INVITE可以同时修改对话和会话的参数。

呼叫方或被叫方都可以修改现有会话。

UA在检测到媒体失败时的行为是本地策略的问题。但是, 不建议自动生成re-INVITE或BYE以避免在网络拥塞时用流量淹没网络。在任何情况下, 如果自动发送这些消息, 应该在某个随机间隔后发送。

请注意, 上面的段落指的是自动生成的BYE和re-INVITE。如果用户在媒体失败时挂断, UA将照常发送BYE请求。


14.1 UAC行为 (UAC Behavior)

适用于INVITE中会话描述的相同提供/应答模型 (第13.2.1节) 也适用于re-INVITE。因此, 例如, 想要添加媒体流的UAC将创建包含此媒体流的新提供, 并在INVITE请求中将其发送给对等方。重要的是要注意, 发送的是会话的完整描述, 而不仅仅是更改。这支持各种元素中的无状态会话处理, 并支持故障转移和恢复功能。当然, UAC可以发送不带会话描述的re-INVITE, 在这种情况下, 对re-INVITE的第一个可靠的非失败响应将包含提供 (在本规范中, 那是2xx响应)。

如果会话描述格式具有版本号的功能, 提供者应该指示会话描述的版本已更改。

re-INVITE的ToFromCall-IDCSeqRequest-URI的设置遵循与现有对话内常规请求相同的规则, 如第12节所述。

UAC可以选择不向re-INVITE添加Alert-Info头字段或Content-Disposition为"alert"的消息体, 因为UAS通常不会在接收到re-INVITE时向用户发出警报。

与可以分叉的INVITE不同, re-INVITE永远不会分叉, 因此只会生成单个最终响应。re-INVITE永远不会分叉的原因是Request-URI将目标标识为与之建立对话的UA实例, 而不是标识用户的记录地址。

重要约束

请注意, 当另一个INVITE事务在任一方向进行时, UAC不得在对话内发起新的INVITE事务

  1. 如果存在正在进行的INVITE客户端事务, TU必须等待事务达到完成或终止状态后才能发起新的INVITE。

  2. 如果存在正在进行的INVITE服务器事务, TU必须等待事务达到已确认或终止状态后才能发起新的INVITE。

但是, UA可以在INVITE事务进行时发起常规事务。UA也可以在常规事务进行时发起INVITE事务。

处理响应

如果UA收到对re-INVITE的非2xx最终响应, 会话参数必须保持不变, 就像没有发出re-INVITE一样。请注意, 如第12.2.1.2节所述, 如果非2xx最终响应是481 (Call/Transaction Does Not Exist) 或408 (Request Timeout), 或者根本没有收到re-INVITE的响应 (即, INVITE客户端事务返回超时), UAC将终止对话。

处理491响应

如果UAC收到对re-INVITE的491响应, 它应该启动一个计时器, 值T选择如下:

  1. 如果UAC是对话ID的Call-ID的所有者 (意味着它生成了该值), T的值在2.1到4秒之间随机选择, 单位为10毫秒。

  2. 如果UAC不是对话ID的Call-ID的所有者, T的值在0到2秒之间随机选择, 单位为10毫秒。

当计时器触发时, 如果仍然希望进行该会话修改, UAC应该再次尝试re-INVITE。例如, 如果呼叫已经用BYE挂断, 则不会进行re-INVITE。

传输re-INVITE和为re-INVITE的2xx响应生成ACK的规则与初始INVITE相同 (第13.2.1节)。


14.2 UAS行为 (UAS Behavior)

第13.3.1节描述了区分传入的re-INVITE和传入的初始INVITE以及处理现有对话的re-INVITE的程序。

处理竞争条件

如果UAS在为具有较低CSeq序列号的第一个INVITE发送最终响应之前在同一对话上收到第二个INVITE, 它必须对第二个INVITE返回500 (Server Internal Error) 响应, 并且必须包含Retry-After头字段, 其值在0到10秒之间随机选择。

如果UAS在对话上收到INVITE, 而它在该对话上发送的INVITE正在进行中, 它必须对收到的INVITE返回491 (Request Pending) 响应。

检查会话描述

如果UA收到现有对话的re-INVITE, 它必须检查会话描述中的任何版本标识符, 或者如果没有版本标识符, 则检查会话描述的内容以查看是否已更改。如果会话描述已更改, UAS必须相应地调整会话参数, 可能在征求用户确认后。

会话描述的版本控制可用于适应会议新到达者的能力、添加或删除媒体, 或从单播更改为多播会议。

如果新的会话描述不可接受, UAS可以通过为re-INVITE返回488 (Not Acceptable Here) 响应来拒绝它。此响应应该包含Warning头字段。

如果UAS生成2xx响应但从未收到ACK, 它应该生成BYE以终止对话。

临时响应和警报

UAS可以选择不为re-INVITE生成180 (Ringing) 响应, 因为UAC通常不会向用户呈现此信息。出于同样的原因, UAS可以选择不在re-INVITE的响应中使用Alert-Info头字段或Content-Disposition为"alert"的消息体。

构造提供

在2xx中提供提供的UAS (因为INVITE不包含提供) 应该构造提供, 就像UAS正在发起全新呼叫一样, 但受到发送更新现有会话的提供的约束, 如 [13] 中针对SDP的描述。具体来说, 这意味着它应该包含UA愿意支持的尽可能多的媒体格式和媒体类型。UAS必须确保会话描述在媒体格式、传输或需要对等方支持的其他参数方面与其先前的会话描述重叠。这是为了避免对等方需要拒绝会话描述。但是, 如果UAC不可接受, UAC应该生成带有有效会话描述的应答, 然后发送BYE以终止会话。


re-INVITE使用场景

1. 添加媒体流

场景: 通话中添加视频
UAC UAS
| |
|<=========音频会话===================>|
| |
|---re-INVITE (音频+视频)------------>|
|<--200 OK (音频+视频)----------------|
|---ACK----------------------------->|
| |
|<=========音频+视频会话===============>|

2. 删除媒体流

场景: 关闭视频, 仅保留音频
UAC UAS
| |
|<=========音频+视频会话===============>|
| |
|---re-INVITE (仅音频)--------------->|
|<--200 OK (仅音频)-------------------|
|---ACK----------------------------->|
| |
|<=========音频会话===================>|

3. 更改媒体参数

场景: 切换编解码器或更改端口
- 发送包含新编解码器列表的re-INVITE
- 或更改接收媒体的端口

4. 保持会话活跃

场景: 发送re-INVITE作为保活机制
- 某些实现使用re-INVITE检测对等方是否仍然响应

re-INVITE vs 初始INVITE的关键区别

特性初始INVITEre-INVITE
分叉可以分叉永不分叉
Request-URI记录地址UA实例的联系地址
对话创建新对话在现有对话内
180响应通常发送通常不发送
Alert-Info可能使用通常不使用
并发限制不能与另一个INVITE重叠

处理491 (Request Pending) 的重试机制

Call-ID所有者:
等待时间 = random(2.1秒 到 4秒)

非Call-ID所有者:
等待时间 = random(0秒 到 2秒)

目的: 避免双方同时重试导致的冲突

重要注意事项

  1. 会话描述必须完整: re-INVITE必须包含完整的会话描述, 而不仅仅是更改的部分。

  2. 版本控制: 如果会话描述格式支持, 应该更新版本号。

  3. 不能重叠: 在同一对话中, 同一时间只能有一个INVITE事务进行。

  4. 失败后保持不变: 如果re-INVITE失败 (非2xx), 会话参数保持原样。

  5. 491响应处理: 使用随机退避重试, Call-ID所有者等待更长时间。

  6. 自动重试要谨慎: 不建议在媒体失败时自动发送re-INVITE, 以避免网络拥塞。

  7. UAS行为: UAS必须检查会话描述是否更改, 并相应调整参数。


典型re-INVITE流程

1. UAC决定修改会话

2. 检查是否有正在进行的INVITE事务
├─ 有 → 等待完成
└─ 无 → 继续

3. 构造re-INVITE
├─ 完整的会话描述
├─ 更新版本号
└─ 正确的对话标识符

4. 发送re-INVITE

5. UAS处理
├─ 检查会话描述变化
├─ 可能征求用户确认
└─ 调整会话参数

6. 返回响应
├─ 2xx → 应用新参数
├─ 488 → 拒绝提议
├─ 491 → 请求挂起, 稍后重试
└─ 500 → 服务器错误, 稍后重试

7. UAC发送ACK (如果是2xx)

8. 会话使用新参数继续

本章小结:

第14章描述了如何使用re-INVITE修改现有SIP会话。re-INVITE是在已建立的对话内发送的INVITE请求, 用于修改会话参数, 如添加/删除媒体流、更改编解码器、更新端口等。关键特点是re-INVITE永不分叉、必须包含完整的会话描述、不能与另一个INVITE事务重叠, 以及需要特殊处理491响应以避免竞争条件。re-INVITE是SIP会话灵活性的重要体现, 允许在会话进行中动态调整参数。