本文主要记录阅读 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
  • 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” 状态。
  • 匹配响应给对应客户端事务
    • 响应消息的 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 状态的瞬间被销毁。

事务的的匹配

在 VIA 中有 z9hG4bK 字符,通过魔法字符进行匹配。没有就采用 Request-URI, To tag, From tag, Call-ID, CSeq, and top Via header
匹配对应的 事务。