本文主要记录阅读 SIP rfc3261 文档的一些所思所考,不会对其进行整理分类,并且存在跳跃性
生成 SIP 响应
- 8.2.6
- 除了 invite 外需要生成临时响应,其它响应应该立即响应
- 生成的临时响应,请求中的时间戳应该直接复制到响应中。如果响应慢就需要将延迟时间以 s 为单位,将时间生成在响应中
- 响应的 Call-ID、CSeq、VIA的顺序必须相同。除了 100,其它响应的 uri 内容必须相同,并且需要添加一个 tag,用于 dialog。
事务的解读
事务的分为客户端事务与服务器事务,客户端事务发送请求,服务器事务发送响应。
无状态代理不包含客户端事务或服务器事务。
- 200(Ok)的ack作用:主要为了确保 200ok 能够正常发送到 UAC。如果后续不发送 ACK,那么服务端会不断发送,并且在三分钟后断开连接
- 疑问:为啥 200 ok 的 ack 作为自己单独的事务?
- 解答:这样设计的原因是保证送达到UAC,并且如果没有回复 ACK,那么 UAS 将会重传
- 客户端事务:客户端事务的主要负责将接收到的响应传递给 TU, 并过滤重传与不允许的传递。对于 invite 的请求,用于生成 ACK
- 疑问:TU 与客户端事务有什么区别吗
- 解答:客户端是TU 与 传输层的中间层
- 服务器事务:服务器事务的目的是接收来自传输层的请求并将其传递给TU,服务器事务过滤来自网络的任何请求重传。
服务器事务接受来自TU的响应,并将它们传递到传输层,以便通过网络进行传输。在INVITE事务的情况下,它会吸收除2xx响应之外的任何最终响应的ACK请求。 - 200ok与ack的生成: 都由 UA 核心来处理
- 疑问:前面说客户端事务生成ack,现在又说 UA 核心来处理,不明白
- 解释:这里的由核心来处理指的是重传由核心处理。
- on-INVITE client transaction:这是没有 ack 的事务。如果需要 ack 的话,需要 tu 直接生成一个 ack?
客户端事务
- 客户端事务状态机: invite 客户端事务与非 invite 客户端事务
- 特点:invite 客户端事务发送延迟长,需要三方握手;非 invite 事务需要立即响应
- 注意:如果 TU 希望发送 ACK,它将一个 ACK 直接传递给传输层进行传输
invite 客户端事务
invite 事务由发送 invite、服务器事务响应、客户端事务响应ack组成。
其中 invite 发出后在 t1(默认值:500ms) 重发,除非接受到 1xx 响应,否则就增加两倍的 t1 进行重传。
最终,服务器事务发出最终响应,并有客户端事务发送 ack 用于终止重传
- 形式描述
- invite 的客户端事务初始状态为 “Calling”
- 不可靠传输启动定时器 A(t1),可靠传输不需要启动。事务启动定时器 B(64*t1) 控制事务超时
- 超时后重传必须在 “calling” 状态下进行,并且传输时间是 2*t1
- 如果定时器 B 触发后任然处于 “calling”, 则通知 TU 超时,并不生成 ack,然后进入 “Terminated” 状态
- 当接收到临时响应是,状态改为 “Proceeding”。后续的临时响应需要传递给 TU
- 当处于 “Calling” 或 “Proceeding” 状态下,接收到 300-699 响应必须转换为 “Completed”
- 接收到服务器事务的响应后,生成 ack 并传输到原始请求发送到的相同的地址、端口和 transport
- 当进入 “Completed” 时,启动定时器 D, 对于不可靠传输值至少为 32 秒,可靠传输置为 0。这个值等于服务器事务定时器 H(64*T1)
- 新接收到的重新响应不能传递给 TU
- 定时器 D 在客户端事务处于 “Completed” 状态时触发,客户端事务必须移动到 “Terminated”
- 当处于 “Calling” 或 “Proceeding” 状态下,接收 2xx 响应必须导致客户端事务进入 “Terminated” 状态,并且必须将响应传递到TU
- Proxy 响应 200 为传递给下一跳,客户端事务生成 ack
- 客户端事务必须在进入 “Terminated” 状态的瞬间被销毁。
- 注意:如何没匹配到合适的客户端事务,则传递到 core
- invite 的客户端事务初始状态为 “Calling”
- ack 的构造
- Call-ID、From 和 Request-URI 必须和原始请求相同
- To 必须等于被确定的响应中的 To 字段
- ACK 必须包含单一的 Via 报头字段,这个字段必须等于原始的顶部 Via 报头字段
- 如果 2xx 中有 Route 字段,则这些也要出现在 ACK 报头中
- 注意:invite 响应 415,则可以在 ACK 中放置 body 内容
非 INVITE 客户端事务
非 INVITE 客户端事务超时 t1 后重传,但是在接受到临时或最终响应后,以 t2 为间隔继续传输消息。
疑问:按照标准文档,按照 t2 继续传输消息,是为了确保交付最后响应。服务器发送了一个请求后,传输在终止?
非 INVITE 客户端事务的 200ok 不会响应 ACK。
- 形式描述:
- 发起事务请求,进入 “Trying” 状态
- 启动定时器 F(64T1) 。如果是不可靠传输,客户端事务必须设置定时器 E(T1),以MIN(2T1,T2),T2 默认为 4s
- 如果定时器 F 触发,仍处于 “Trying”,通知 TU 超时,然后进入 “Terminated” 状态
- 如果在 “Trying” 状态下收到最终响应(200-699),则传递给 TU,事务转换为 “Completed” 状态
- 当在 “Trying” 状态下收到临时响应,则转为 “Proceeding” 状态
- 如果定时器 E 在 “Proceeding” 状态下被触发,请求需要被重传,定时器 E 重置为 T2 秒
- 如果定时器 F 在 “Proceeding” 状态下被触发,通知 TU 超时,然后进入 “Terminated” 状态
- 如果在 “Proceeding” 状态下收到最终响应(200-699),则传递给 TU,事务转换为 “Completed” 状态
- 当进入 “Completed” 时,启动定时器 K, 对于不可靠传输值 T4 秒,可靠传输置为 0。
- T4表示网络清除客户机和服务器事务之间的消息所需的时间。缺省值为5s
- 如果定时器 K 在此状态下触发,客户端事务必须转换到 “Terminated” 状态。
- 发起事务请求,进入 “Trying” 状态
- 匹配响应给对应客户端事务
- 响应消息的 Via 头字段的 Branch 参数相同,则匹配
- CSeq报头字段中的方法参数与创建事务的请求的方法匹配。用于 CANCEL,CANCEL 会新生成一个事务
- 异常处理
- 当传输发送错误时,立即想 TU 响应错误,并直接切换到 “Terminated” 状态
服务器事务
服务器事务是在接收到请求时由核心创建。
INVITE 服务器事务
形式描述:
Proceeding 收到重传请求,那么需要获取 TU 给的最新的 trying 进行重传
- Proceeding 状态下 TU 向服务器事务传递 2xx 响应,服务器事务必须传出去,当然重传由 TU 负责,服务器事务状态转为 Terminated
- Proceeding 状态下 TU 向服务器事务传递 300-699,必须传出去,服务器事务状态转为 Completed。不可靠传输定时器 G(T1) 触发,可靠传输,定时器不触发。
Completed 进入后,定时器 H(64*T1) 必须启动,此定时器决定了重传超时时间。
- 如果定时器 G 触发,则将继续重传,定时器 G 时间为 MIN(2*T1, T2)
- Completed 状态下,接收到重传请求应该进行重传
- Completed 状态下,收到了 ACK,则转为 Confirmed。并且定时器 G 被忽略,任何重传都会停止
- Completed 状态下,定时器 H 被激活,则服务器事务转为 Terminated 状态,并通知 TU 事务失败。
Confirmed 主要用于吸收多余的 ACK。
- 当进入该状态时,定时器 I 在 T4 秒内触发,对于不可靠的传输,定时器 I 为 0 秒。
- 一旦定时器触发,则转为 Terminated 状态
一旦事务处于“终止”状态,它必须立即销毁。与客户端事务一样,这需要确保对INVITE的2xx响应的可靠性。
非 INVITE 服务器事务
- 形式描述:
- Trying 状态下,初始化走这个状态并且任何重传都将丢弃
- TU 向服务器事务传输响应,则转为 Proceeding 状态
- Proceeding 状态下,所有 TU 传输过来的内容,都需要全部通过传输层传输出去
- Proceeding 接收到请求的重传,则必须将最新发送临时响应重传出去
- Proceeding 状态下,TU 向服务器事务传递最终响应(200-699), 则事务必须进入 Completed 状态
- Completed 状态必须启动定时器 J(64*T1),不可靠为 0 秒
- TU 传递给服务器事务的任何其他最终响应必须在处于 Completed 状态时丢弃
- 服务器事务保持这个状态,直到定时器 J 触发,转为 Terminated 状态
- 服务器事务必须在进入 Terminated 状态的瞬间被销毁。
- Trying 状态下,初始化走这个状态并且任何重传都将丢弃
事务的的匹配
在 VIA 中有 z9hG4bK 字符,通过魔法字符进行匹配。没有就采用 Request-URI, To tag, From tag, Call-ID, CSeq, and top Via header
匹配对应的 事务。