SIP 是靠 Transaction (譯作「交易」?) 完成的協定,用 Method 表示
啥款功能,動作是發出請求 (request),然後等候回應 (response)。回應會使先有一寡
暫時回應 (provisional responses),最尾攏有一個
最後回應 (final responses)。INVITE Transaction 較複雜,除了上述回應外,最尾還要送 ACK 請求來確定最後回應。
以 SIP 分層功能來看,Transaction 服務 Transaction User (TU),透過 SIP Transport 層藉由 UDP/TCP/? 傳收封包。Transaction 層又可分成在 Client 端的 Client Transaction,對應到 Server 端的 Server Transaction。Transaction 層找出訊息的相關 Transaction,處理逾時及重傳。任何 UAC 的工作都透過一系列 transaction 完成。流程如下:
- [Client] TU 發出請求,Transaction 層建立一個新 Client Transaction,透過傳輸層確保可靠地送出。
- [Server] 收到請求時上傳給 TU 處理,依需要建立 Server Transaction。
- [Server] TU 的任何回應,都經過 Server Transaction 給傳輸層確保可靠地傳送。如果收到重傳的請求,不再送給 TU,只重傳回應。
- [Client] 收到回應找到對應的 Client Transaction,過濾掉重傳的最後回應或不允許的回應 (例如 ACK 的回應),然後地交給 TU。
此外,如果是
INVITE 請求,Client Transaction 還負責產生失敗回應的 ACK。Server Transaction 吸收失敗回應的 ACK。
INVITE 2xx 回應和其 ACK 特別處理。INVITE 2xx 回應只由 UAS 重傳,ACK 只由 UAC 重傳,確保主叫端得知所有接受呼叫的用戶。因此,INVITE 2xx 回應重傳和 ACK 產生由 UA core 處理,不是 Transaction 層。沿路上的每個 Proxy 只是轉送每個 INVITE 的 2xx 回應和 ACK。
UA 和 stateful proxy 都有 transaction 層功能,stateless proxy 則不需要 transaction 層功能。
找出訊息的相關
Transaction 比對:
Via branch
[待續]
以下說明分成一般 Transaction 和 INVITE Transaction (含 ACK)。
一般 Transaction
請求要在 64*T1 (T1 預設 0.5 秒,所以總共是 64*0.5 = 32 秒) 前要收到最後回應,不然就逾時而結束。
如果使用 UDP,由 Transaction 層提供重傳機制,Client Transaction 重送請求直到收到最後回應,間隔是 T1, 2*T1, 4*T1, ..., T2, T2, T2, ...。一開始是 T1,然後每次加倍直到 T2 或收到暫時回應後,改為 T2。
Server Transaction 收到重傳的請求,不往 TU 送,有回應過會重送回應。傳送最後回應後,有可能對方沒收到而收到重傳的請求,需使用 Timer J 等候 64*T1 才把 Transaction 結束。
T2
表示 server transaction 不馬上回應時應該的回應時間。
一般請求重送間隔照 T1 指數型退讓最大 T2,總共最長 64*T1。預設 T1 0.5 秒、T2 4 秒,間隔會是 0.5 秒、1 秒、2 秒、4 秒、4 秒、4 秒、4 秒、4 秒、4 秒、4 秒 (共 7 次 4 秒)。
Client Transaction 收到最後回應後,可能還會有重傳的回應在半路,等候 T4 才把 Transaction 結束,預設是 5
秒。
一般 Client Transaction 狀態流程 (修改自 RFC3261)
|Request from TU:
|send request
Timer E: V
send request +-----------+
+---------| |-------------------+
| | Trying | Timer F |
+-------->| | or Transport Err.:|
+-----------+ inform TU |
200-699: | |1xx: |
resp. to TU | |resp. to TU |
+---------------+ | |
| | |
| Timer E: V Timer F |
| send req +-----------+ or Transport Err.:|
| +---------| | inform TU |
| | |Proceeding |------------------>|
| +-------->| |-----+ |
| +-----------+ |1xx: |
| 200-699: | ^ |resp to TU |
| resp. to TU | +--------+ |
| V |
| +-----------+ |
+----------->| Completed | |
+-----------+ |
| Timer K: |
V |
+-----------+ |
| Terminated|<------------------+
+-----------+
註:Timer F 計數 64*T1 逾時,Timer E 在 UDP 時計數重傳間隔,Timer K 在 UDP 時計數 T4 等候可能還在半路的重傳回應。
一般 Server Transaction 狀態流程 (修改自 RFC3261)
| 收到請求:
| 轉給 TU
TU 最後回應: V
送回應 +-----------+
+-------------| Trying |
| +-----------+
| | TU 暫時回應:
| | 送回應
| TU 新暫時回應或 V Trnsprt Err:
| 再次收到請求:+-----------+ Inform TU
| 送回應 +----| Proceeding|-------------->+
| | +-----------+ |
| | ^ | |
| +------+ |TU 最後回應: |
+------------------>|送回應 |
V Trnsprt Err: |
再次收到請求:+-----------+ Inform TU |
送回應 +----| Completed |-------------->+
| +-----------+ |
| ^ |Timer J 到期 |
+------+ V |
+-----------+ |
| Terminated|<--------------+
+-----------+
註:
- TU 回應都轉給傳輸層傳輸,不主動重傳,只有再次收到請求才重傳。
- 請求含重傳最久持續 64*T1,Timer J 等候可能的重傳。
INVITE Transaction
INVITE Transaction 比一般 Transaction 多了要對最後回應回送 ACK 作確認,形成三路交握 -- INVITE、回應、ACK。
如果使用 UDP,由 SIP Transaction 層提供重傳機制
- Client Transaction 重傳 INVITE 直到收到回應 (通常會有暫時回應)。Server Transaction 收到重傳的 INVITE,重送回應。
- Server Transaction 重傳失敗的最後回應直到收到 ACK。Client Transaction 收到重傳的最後回應,重送 ACK。
註:一般請求預期很快會完成 (應該不會超過 T2,預設 4 秒)。而 INVITE 預期會有長時間延遲,包括路由到被叫端、振鈴等到接聽後才有最後回應。過程中通常會有多個暫時回應,例如 100 Trying 和 180 Ringing。Proxy/UAS 收到 INVITE,預期 0.2 秒內不會有回應必須先回送 100 Trying,停止 INVITE 重送來避免網路擁塞。到達被叫端振鈴時回送 180 Ringing。
註:一般請求是重傳直到收到
最後回應,可確認有收到最後回應。而 INVITE 最後回應較久,所以收到
任何回應就停止重傳,並需要另外 ACK 確認最後回應。
註:除了 100 Trying 以外的暫時回應,如 180 Ringing,這些如果需要重傳機制,需要另
外支援
PRACK。
INVITE 重送間隔是 T1、2*T1、4*T1、8*T1、16*T1、32*T1 (exponential backoff)。一開始是 T1,然後每次加倍,逾時是 64*T1,所以總共最多傳 7 次。。
失敗回應重送間隔和一般請求相同,一樣是 T1, 2*T1, 4*T1, ..., T2, T2, T2, ...。
成功回應的重送間隔也是一樣,只是改由 UAC Core 重送。
失敗回應的 ACK 和 UAC core 產生給 2xx 的 ACK 不同 (Section 13)。
- 原始 INVITE 請求的 Call-ID、From、Request-URI、To、單一 Via。
- 回應的 To tag 和 Route
- CSeq 序號和原始請求一樣,method 為 ACK。
雖然任何請求都可以放信體,但避免讓 ACK 因信體不認得而 reject,並不建議放信體。如果要放,type 限制出現在 INVITE 的 type。如果是 415 的 ACK,ACK 信體可以是任何列在 415 Accept 信頭欄位的 type。
INVITE Client Transaction 狀態流程 (修改自
RFC3261)
|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 |
300-699: +---------------+ |1xx: |
ACK sent | |1xx to TU |
resp. to TU | 1xx: V |
| 1xx to TU -----------+ 2xx: |
| +---------| | 2xx to TU |
| | |Proceeding |-------------->|
| +-------->| | |
| +-----------+ |
| |300-699: |
+----------------->|ACK sent, |
|resp. to TU |
300-699: V |
ACK sent +-----------+Transport Err.:|
+---------| |Inform TU |
| | Completed |-------------->|
+-------->| | |
+-----------+ |
| Timer D fires: |
v |
+-----------+ |
| Terminated|<--------------+
+-----------+
註:Timer B 計數 64*T1 逾時,Timer A 在 UDP 時計數重傳間隔。
註:收到暫時回應進入 "Proceeding" 狀態。
註:最後回應是成功時 (2xx) 通知 TU 後結束,ACK 由 TU 負責。不同 TU 對 2xx 有不同處理,Proxy Core 會往上游轉送,UAC Core 會產生 ACK,並直送 UAS。重傳的 2xx 會沒有 Client Transaction 符合並上傳 TU 處理。
註:收到最後回應是失敗時進入 "Completed" 狀態,負責 ACK 事宜。在 UDP 時,再次收到重送,Timer D 計數 32 秒以上等候有可能還在半路上的最後回應。Timer D 相當於 INVITE Server Transaction 的 Timer H,預設是 64*T1。但由於 INVITE Client Transaction 並不知道對方 T1 值,所以使用 absolute minimum of 32s instead of basing Timer D on T1。
INVITE Server Transaction 狀態流程 (修改自 RFC3261)
收到請求:|
轉給 TU | 如果無法在 200ms 內回應:
+-------+ 送 100 Trying
| |
TU 回應失敗: V | TU 回應成功:
送回應 +---------+ | 送回應
+---------| Trying |--|----------------->+
| +---------+ | |
| TU 暫時回應:| | |
| 送回應 | | |
| TU 暫時回應或 V v TU 回應成功: |
| 再次收到請求:+-----------+ 送回應 |
| 送回應 +----| Proceeding|-------------->+
| | | | |
| +--->| | |
| +-----------+ Trnsprt Err: |
| TU 回應失敗:| | Inform TU |
| 送回應 | +---------------->|
+------------------>| Timer H 到期或 |
再次收到請求或 V Trnsprt Err: |
Timer G 到期:+-----------+ Inform TU |
送回應 +----| Completed |-------------->+
| +-----------+ |
| ^ | ACK |
+------+ V |
+-----------+ |
| Confirmed | |
+-----------+ |
|Timer I 到期 |
V |
+-----------+ |
| Terminated|<--------------+
+-----------+
和一般 Transaction 差別:
- 如果預期無法在 200ms 內回應,就送 100 Trying 直接進 Proceeding。100 Trying 依據 Section 8.2.6 建立,除了 To tag 不應該 (SHOULD NOT) 放 (當請求沒有時)。
- 成功就回 2xx 結束 Transaction,收到 ACK 是不同 Transaction 不建 Transaction 直接上傳 TU。TU 重傳 2xx 直到收到 ACK,然後做可能的後續處理,包括 SDP、可能進行 re-INVITE 等。
- 再次收到請求重傳失敗回應機制還是在,但因為對方收到暫時回應後就不會再次請求,所以多了 Timer G 主動重傳失敗回應,最多歷時 Timer H (64*T1),直到收到 ACK。再次請求也最多歷時 64*T1,加上回應失敗的延遲,可以有效覆蓋 Timer J 的角色。收到 ACK 後,路上可能還有,多了狀態 Confirmed 等候 Timer I (5 秒) 消化額外的 ACK。
Client Transaction
| 事件 | 狀態 | 主動重送 | 逾時 |
| 送INV請求 | Calling | Timer A | Timer B |
| 收到暫時回應 | Proceeding | 無 | 無 |
收到失敗回應送 ACK
| Completed | 無 | Timer D |
逾時 或 無法送 或 收到 2xx
| Terminated | NA |
| 事件 | 狀態 | 主動重送 | 逾時 |
| 送一般請求 | Trying | Timer E | Timer F |
| 收到暫時回應 | Proceeding | Timer E | Timer F |
| 收到最後回應 | Completed | 無 | Timer K |
逾時 或 無法送
| Terminated | NA |
Server Transaction
| 事件 | 狀態 | 再次收到請求 | 主動重送 | 逾時 |
| 收到請求 | Trying | 忽略 | 無 | 無 |
| 送暫時回應 | Proceeding | 重送回應 | 無 (PRACK) |
| 一般送最後回應 | Completed | 無 | Timer J |
| INV送失敗回應 | Timer G | 64*T1 |
| INV送成功回應 |
| 收到 ACK (相同 Via branch) | Confirmed | 忽略 | 無 | Timer I |
| 收到 ACK (在 TU 有 Dialog) |
逾時 或 無法送 (通知 TU) | Terminated | NA |
| 送成功回應 | 在 TU 有 Dialog | TU 處理 | TU 處理 |
| 收到 ACK (不同 Via branch) | TU 處理 |
INV 成功回應的重傳本來是在 TU 處理的,可整合到 Completed 狀態,採用 INV 失敗回應相同的 Timer G 重送和 Timer H 結束,變成 INV 最後回應都採用相同的處理方式。此時收到 ACK 也要進到 Confirmed 狀態。
註:transaction 源自 HTTP
參考
- RFC3261 §17