顯示具有 SIP 標籤的文章。 顯示所有文章
顯示具有 SIP 標籤的文章。 顯示所有文章

2023年6月2日 星期五

SIP Match Transactions

在 RFC3261,必須有 Via branch,對特定 UA 發請求時必須產生在時空上是唯一的 Via branch,且開頭是「z9hG4bK」。

RFC2543 沒有唯一的規定,且不會以「z9hG4bK」開頭。

CANCEL 和失敗的 ACK 則是沿用要取消或 ACK 請求的 Via branch。

回應比對 Client Transaction,需符合:

  1. Via branch
  2. CSeq method (因為 CANCEL 沿用 Via branch,但不同 Transaction)

有可能收到來自不同 server 的多個回應 (基本上 To tag 會不同),第一個收到的回應會被採用,其它視為重送,這樣並不是錯誤,multicast SIP provides only a rudimentary "single-hop-discovery-like" service that is limited to processing a single response.

請求比對 Server Transaction

  • 來自 RFC3261 client,需符合:
    1. Via branch
    2. Via sent-by (不同 client 可能產生相同 branch。)
    3. Method 符合,ACK 是符合 INVITE。
  • 來自 RFC2543 client (無 Via branch 或不是),需符合:
  • 項目INVITEACK 比對 INVITE
    其它
    Request-URIvvv
    To tagvresponsev
    From tagvvv
    Call-IDvvv
    CSeqvnumberv
    top Viavv?

CANCEL 和失敗的 ACK 會有 Inclusion of the tag in the To header field in the ACK matching process helps disambiguate ACK for 2xx from ACK for other responses at a proxy, which may have forwarded both responses (This can occur in unusual conditions. Specifically, when a proxy forked a request, and then crashes, the responses may be delivered to another proxy, which might end up forwarding multiple responses upstream). An ACK request that matches an INVITE transaction matched by a previous ACK is considered a retransmission of that previous ACK.

Via branch 格式參考:...

Proxy 收到請求可選擇檢查 Loop Detection

2022年2月19日 星期六

SIP dialog

INVITESUBSCRIBE... 可建立 dialg。

使用 tag 作為 dialog 識別在 RFC 3261 是強制的,但在 RFC 2543 是 optional。(有一端是 RFC 3261 的話,至少 From Tag 或 To Tag 中會有一個,RFC 2543v會保留嘛?)

...

12.2 Requests within a Dialog

兩個 UA 建立 dialog 後,任一端需要時可發起新 transaction。請求可 (還是有 Route Set 時必須) 包含 Record-Route 和 Contact。這些請求不能改變 dialog 的 route set (為什麼?)。這些中,屬於 target refresh request 才可以改變 remote target URI (什麼是 target?什麼是 remote target URI?依建立 dialog 的 method 而有不同?),並不能更新 route set。更新 route set 和 RFC2543 系統會有嚴重相容問題 (什麼問題?)。INVITE 建立的 dialog,唯一的 target refresh request 是 re-INVITE。ACK 並不是 target refresh request。

12.2.1 UAC Behavior

12.2.1.1 Generating the Request

...

target refresh request 應該要有 Contact,且除非有改變的需要,應該和 dialog 內之前的請求一致。如果 "secure" flag 是 true,必須是 SIPS URI。如同 Section 12.2.2 所討論,target refresh request 的 Contact 更新 remote target URI,不是 target refresh request 不更新 remote target URI。

請求剩下部份照 Section 8.1.1 描述形成。compute the address of the server,照 Section 8.1.2 送請求,一般送給 topmost Route 或沒有時送給 Request-URI。Subject to certain restrictions,允許送給不在 route set 的其它位址,例如, default outbound proxy。

12.2.1.2 Processing the Responses

如果 client transaction timeout,視同收到 408 Request Timeout。

收到 3xx,行為描述在 Section 8.1.3.4.

target refresh request 收到 2xx,如果有 Contact,必須取代為 dialog 的新的 remote target URI。

481 Call/Transaction Does Not Exist 或 408 Request Timeout,應該結束 dialog。INVITE 的 dialog 結束,包含送 BYE。

12.2.2 UAS Behavior

如果收到請求有 To tag,UAS core 比對 dialog 符合,先如同 Section 8.2 處理。如果不符合,可能是 UAS 有重啟、或收到要給其它 UAS 的請求 (possibly failed) UAS (the UASs can construct the To tags so that a UAS can identify that the tag was for a UAS for which it is providing recovery)、或者純粹跑錯。UAS 可以基於 To tag 決定是否接受來提供 robustness,讓 dialog 即使重啟仍可以維持。提供此功能需考慮維持 CSeq 序號增加、重建 route set、和接受 out-of-range RTP timestamps and sequence numbers。如果要 reject,回 481 Call/Transaction Does Not Exist。

如果 remote sequence number 是空的,設為 CSeq 序號。如果 remote sequence number 大於 CSeq 序號,the request is out of order and MUST 回 500 Server Internal Error。如果 remote sequence number 小於 CSeq 序號 (包括差 1 以上),request is in order 並更新為 CSeq 序號。如果請求 proxy challenges,並不會送到 UAS。UAC 需要序號增加重送請求 with credentials,所以序號可能會有 gap。

當收到 target refresh request,如果有 Contact,必須用來取代 dialog 的 remote target URI。

12.3 Termination of a Dialog

建立 dialog 失敗,同時也結束 early dialog。結束 dialog 的機制是 method specific,例如 BYE 結束一個 INVITE 建立的 session 以及 associated dialog。

Call-ID 分大小寫,tag 不分大小寫

tag-param = "tag" EQUAL token

tag 值是 token,包含英文字母、數字和其他符號共 72 字元,不分大小寫的話 46 (會有設備去改大小寫嗎?)。

參考

  1. RFC 3261

2021年12月11日 星期六

tel URI

RFC3966 說明 tel URI

telephone-subscriber = global-number / local-number

telephone-subscriber 可以看成是 user 是電話號碼的特例,看開頭有無「+」分成全球號碼 (global-number) 和區域號碼 (local-number) 兩種。

全球號碼 (global-number, E.164):tel: +十進位數字

global-number        = global-number-digits *par
global-number-digits = "+" *phonedigit DIGIT *phonedigit

全球號碼是「+」開頭十進位數字,至少一碼。可用 visual-separator「-」「.」「(」「)」隔開便於閱讀,比較或撥號時都忽略。後面可有參數,每個「;」表示有一個。依照 E.123E.164,數字必須包含國碼 (CC) 和受話國國內有效號碼 (National Significant Number, NSN),是全球唯一的。

範例

tel:+1-201-555-0123

一個美國門號,國碼 1、區碼 ...、、、。

有些號碼無法用全球號碼表示,需要用區域號碼,例如私人號碼、緊急電話 119/110、查號台 104、服務電話等。號碼含有 有 A ~ D、* 或 # 也不行。

區域號碼:tel: 十六進位數字;phone-context=網址

local-number         = local-number-digits *par context *par
local-number-digits  = *phonedigit-hex (HEXDIG / "*" / "#")*phonedigit-hex

區域號碼用十六進位數字和「*」「#」,一樣可以隔開便於閱讀,後面一樣可以有參數。

參考

  1. RFC3966 The tel URI for Telephone Numbers obsolete RFC2806 URLs for Telephone Calls
  • http://tools.ietf.org/html/rfc3261#section-19.1.6 說明跟 sip: 的轉換。
  • cpc (Calling Party's Category)
    • https://itectec.com/spec/c-1-interworking-sip-to-isup/
    • https://www.etsi.org/deliver/etsi_TS/129100_129199/129163/11.07.00_60/ts_129163v110700p.pdf
  • Numbering Plan
    • ISDN 和 PSTN 使用 E.164 (I.330),PSPDN (Packet Switched Public Data Networks) 一般使用 X.121。不同 numbering plan 轉換需要 numbering plan interworking,有 Escape Code、NPI 等方式。
    • National ISDN number = Nataional destination code + ISDN subscriber number
    • Internation ISDN number = Country code + National ISDN number
    • prefix
    • E.164 Escape Code

SIP URI

SIP 最基本的 URI scheme 是 sip:,TLS 加密用 sips:,像 email 格式,用在 SIP 請求行及批頭值等,整個會使拆著 4 個部份:

格式sip:user:password@host:port;uri-parameter?header
4 個部份
帳號主機URI 參數URI 批頭
ABNF
userinfohostporturi-parametersheaders

其中只有主機的 host 是必要的。URI 可作為 addr-spec,但有 URI 參數時,需要整個用 <> 包起來成為 name-addr,才能區別「批頭參數」。

ABNF 格式:

SIP-URI    = "sip:" [ userinfo ] hostport uri-parameters [ headers ]
SIPS-URI   = "sips:" [ userinfo ] hostport uri-parameters [ headers ]

有「@」表示在主機有帳號,「@」之前就是帳號部份,分大小寫,可用 user 或 telephone-subscriber。帳號內如果有「:」表示含有密碼 password,毋過有安全問題不建議用。

userinfo   = ( user / telephone-subscriber ) [ ":" password ] "@"

user 大多字元都可以使用,即使「,」「;」「?」也可以。「@」區別帳號不能使用,「:」表示有密碼也不行,可用「% 跳脫」。

user            =  1*( unreserved / escaped / user-unreserved )
user-unreserved =  "&" / "=" / "+" / "$" / "," / ";" / "?" / "/"

telephone-subscriber 是電話號碼,由 tel URI 來,可視為 user 的特例,可用 URI 參數 user=phone 明確表示用電話號碼。電話號碼本身可能包括「;」開頭的參數,這是出現在「@」之前,和主機之後的 URI 參數是不同的。電話號碼參數在 tel URI 是不分大小寫的,且不同順序是相同的。轉遮 SIP/SIPS URI 愛換遮小寫,isub 排頭前,賰的照字母順序排,這樣比較才會一致。例如:

tel:+358-555-1234567;tsp=a.b;phone-context=5

變成

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

密碼也大多字元都可以使用,只比 user 少了「;」「?」和「/」。(為什麼需要少這 3 個?)

password        =  *( unreserved / escaped /
                   "&" / "=" / "+" / "$" / "," )

主機可以是網域名稱或 IP 網址,如果有「:」表示含有 port。

hostport       = host [ ":" port ]
host           = hostname / IPv4address / IPv6reference
hostname       = *( domainlabel "." ) toplabel [ "." ]
domainlabel    = alphanum / alphanum *( alphanum / "-" ) alphanum
toplabel       = ALPHA / ALPHA *( alphanum / "-" ) alphanum
IPv4address    = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
IPv6reference  = "[" IPv6address "]"
IPv6address    = hexpart [ ":" IPv4address ]
hexpart        = hexseq / hexseq "::" [ hexseq ] / "::" [ hexseq ]
hexseq         = hex4 *( ":" hex4)
hex4           = 1*4HEXDIG
port           = 1*DIGIT

URI 參數可有多個,每個以「;」開始,格式是 名稱=值,名稱不能重複,有 transport、maddr、ttl、user、method、lr 等。和批頭參數是不同的東西。整個 URI 可作為 addr-spec,可用到「,」、「?」、和「;」,但為了跟信頭參數的「;」區別,整個 URI 需要用 <> 包起來成為 name-addr

uri-parameters = *( ";" uri-parameter)
uri-parameter     = transport-param / user-param / method-param
                    / ttl-param / maddr-param / lr-param / other-param
transport-param   = "transport="
                    ( "udp" / "tcp" / "sctp" / "tls"
                    / other-transport)
other-transport   = token
user-param        = "user=" ( "phone" / "ip" / other-user)
other-user        = token
method-param      = "method=" Method
ttl-param         = "ttl=" ttl
maddr-param       = "maddr=" host
lr-param          = "lr"
other-param       = pname [ "=" pvalue ]
pname             = 1*paramchar
pvalue            = 1*paramchar
paramchar         = param-unreserved / unreserved / escaped
param-unreserved  = "[" / "]" / "/" / ":" / "&" / "+" / "$"

說明

  • user=phone:特別表示帳號是電話號碼。

「?」表示有 header,每個用「&」格開。

headers        = "?" header *( "&" header )
header          =  hname "=" hvalue
hname           =  1*( hnv-unreserved / unreserved / escaped )
hvalue          =  *( hnv-unreserved / unreserved / escaped )
hnv-unreserved  =  "[" / "]" / "/" / "?" / ":" / "+" / "$"

其它 scheme URI,可以是網路路徑、絕對路徑等。

absoluteURI    =  scheme ":" ( hier-part / opaque-part )
scheme         =  ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
hier-part      =  ( net-path / abs-path ) [ "?" query ]
net-path       =  "//" authority [ abs-path ]
authority      =  srvr / reg-name
srvr           =  [ [ userinfo "@" ] hostport ]
reg-name       =  1*( unreserved / escaped / "$" / ","
                  / ";" / ":" / "@" / "&" / "=" / "+" )
query          =  *uric
abs-path       =  "/" path-segments
opaque-part    =  uric-no-slash *uric
uric           =  reserved / unreserved / escaped
uric-no-slash  =  unreserved / escaped / ";" / "?" / ":" / "@"
                  / "&" / "=" / "+" / "$" / ","
path-segments  =  segment *( "/" segment )
segment        =  *pchar *( ";" *pchar )
pchar          =  unreserved / escaped /
                  ":" / "@" / "&" / "=" / "+" / "$" / ","

參考

  1. RFC3261 §19.1
  • SIP/SIPS URL follow RFC3986 guideline

2021年6月8日 星期二

SIP P-Header

SIP 的 Private Header (P-Header) 擴充

3GPP [RFC7315] [RFC7976]

  • P-Associated-URI:在 SIP REGISTER 成功回應時告知所有相關 URI。可有多個。UA 可用這些 URI 身份,但並不表示這些 URI 已註冊。
    P-Associated-URI       = "P-Associated-URI" HCOLON
                             [p-aso-uri-spec]
                             *(COMMA p-aso-uri-spec)
    p-aso-uri-spec         = name-addr *(SEMI ai-param)
    ai-param               = generic-param
    範例 [https://community.cisco.com/t5/ip-telephony-and-phones/cisco-2811-itsp-sip-configuration-was-good-from-a-long-time-but/m-p/4163078]
    P-Associated-URI: <sip:+97440006999@vodafone.qa>
    P-Associated-URI: <tel:+97440006999>
    P-Associated-URI: <tel:+97440006900;wcard-range=+974400069![0-9][0-9]!>
    P-Associated-URI: <sip:+974400069![0-9][0-9]!@vodafone.qa>
    name-addr 的 URI 是 <> 包起來的,其中 user 或 telephone-subscriber 的 wildcard 支援
    • 有沒有標準?一般 wildcard 部份前後用 ! 包起來,放正規表示式語法,但可能不是全部支援。
    • IMS PSI 
    • Alcatel-Lucent 5060 IP Call Server (ICS) 的 wildcard PUID。PrID, pbxPUID, pbxPrID, iDN (individual Directory Number)
  • P-Called-Party-ID
  • P-Visited-Network-ID
  • P-Access-Network-Info [https://datatracker.ietf.org/doc/html/rfc7913]
  • P-Charging-Function-Addresses
  • P-Charging-Vector

Early Media 授權 [https://datatracker.ietf.org/doc/html/rfc5009]

2021年5月22日 星期六

Issabel IP PBX

Elastix 2.5 是 GPL 自由軟體,而 Elastix 5.0 是 3CX 私有軟體。Issabel 分支 Elastix 5.0 之前的開源軟體維護。

VirtualBox Linux RetHat 64-bit, 2048M Memroy, 20G HD, Bridged Adaptor

https://www.youtube.com/watch?v=qZE1Tx-fy90&list=PLtWLDPhfY-igBjqrTY5dCpneHEAAXMLdT 

基於 Asterisk、...

參考

https://en.wikipedia.org/wiki/Elastix

2021年4月3日 星期六

SIP Session Timers

RFC4028 提供 SIP session expiration 機制,週期送 re-INVITE 或 UPDATE 作為 session 持續的請求。雖然 UA 可以知道,但 Proxy 不知道 session 是否還活著,例如 BYE 沒收到。 session timer,週期經過協調,如在週期內沒收到 refresh,視為 session 已經結束,Proxy 或 UA 可以清除狀態,結束 NAT session。

新增

  • Option Tag:timer
    • 支援的 UAC 必須放 Supported: timer,即使目前 session 不使用,或者 Required 或 Proxy-Required 已經有了。
    • UAC 並不建議放 Required 或 Proxy-Required,因為只要 UAC 支援就能運作。
  • Session-Expires (x): session 逾時的秒數,不能低於 Min-SE。只放在 INVITE 和 UPDATE,或者其 200 回應。建議 1800 秒 (30 分),95% 的通話低於此值。
    • UAC 一開始可以加 refresher=uac,但就不能協調決定。
  • Min-SE:session 逾時最短的秒數,沒有的話預設 90 秒,SIP transaction 逾時兩倍時間多一點。讓 UA 在一半時間嘗試 refresh 前,能夠結束 transaction。只用在 INVITE 和 UPDATE,或其 422 回應則必須要有。
  • 422 Session Interval Too Small:當 proxy 或 UAS 收到請求的 Session-Expires 時間太短時回應,必須包含 Min-SE

一開始 UAC 送 INVITE 含 Supported: timer,可放 Session-Expires 或 Min-SE。之後 Proxy 或 UAS 可減小 Session-Expires 或加大 Min-SE,沒有的話可插入。如果要求的 Session-Expires 小於自己允許的週期,回 422 含 Min-SE 說明最小允許的週期。最後協調成功決定的週期,放在 200 OK 回應的 Session-Expires,並含 'refresher' 參數表示目前的 uac 或 uas 那邊進行 refreshing。

在過期前,refresher 產生 re-INVITE 或 UPDATE session refresh request。如果 refresher 沒收到回應,送 BYE 結束 session。另一邊到過期一直沒收到 refresh 請求,同樣送 BYE。

有一種較複雜的情況,只有一端 UA 支援,一個 Proxy may need to insert the Session-Expires header field into the response, in the event that the UAS doesn't support the extension. The negotiation of the role of refresher is also affected by this capability; it takes into consideration which participants support the extension.

 

Session-Expires  = ("Session-Expires" / "x") HCOLON delta-seconds
                     *(SEMI se-params)
se-params        = refresher-param / generic-param
refresher-param  = "refresher" EQUAL  ("uas" / "uac")
 Min-SE  =  "Min-SE" HCOLON delta-seconds *(SEMI generic-param)

待整理

RFC4028 Section 7.2 以後

2021年3月20日 星期六

SIP P-Early-Media header

RFC5009: Private Header (P-Header) Extension to the Session Initiation Protocol (SIP) for Authorization of Early Media

P-Early-Media 是 ETSI TISPAN 為了在 3GPP IMS authorizing early media flows 所採用的 private SIP P-header,也用在其它 SIP 網路。

ETSI
European Telecommunications Standards Institute
TISPAN
Telecommunications Internet-converged Services and Protocols for Advanced Networks
3GPP
Third Generation Partnership Project
IMS
IP Multimedia Subsystems
Early Media
應答前的 media,目的是協助用戶完成呼叫,通常不是兩端用戶間直接交換資訊,包括彩鈴、或告訴主叫端「您撥的號碼通話中」等聲音訊息。
Unfortunately, a SIP network interconnected with another SIP network may have no means of assuring that the interconnected network is implementing a compatible early media policy, thus allowing the exchange of user data within early media under some circumstances. For example, if a network "A" allows all early media with user equipment as UAC and an interconnected network "B" allows all early media with user equipment as UAS, any session established between user equipment as UAC in "A" and user equipment as UAS in "B" will allow bidirectional user data exchange as early media. Other combinations of early media policies may also produce similar undesirable results. The purpose of the extension is to allow a SIP network interconnected to other SIP networks with different early media policies to correctly identify and enable authorized early media according to its policies.
Backward Early Media
由 terminating switch 往主叫端方向,例如提供回鈴音。
Forward Early Media
由主叫端往 terminating switch 方向,例如二次撥號的 DTMF digit collection。

authorize the cut-through of backward and/or forward early media when permitted by the early media policies of the networks involved. 用在有下列特性的 SIP 網路:兩端用戶間透過其它 SIP 網路連接,兩端用戶間無法直接交換 early media,但可以 "gate" (enable/disable) the flow of early media to/from user equipment.

在一個 isolated SIP 網路,可以自己決定是否開啟內部兩個用戶間的 early media。但如果兩個用戶間需要透過其它 SIP 網路連接,只有連到外部 SIP 網路的 boundary node 可以決定 which early media policy。The P-Early-Media header field provides a means for this boundary node to communicate this early media policy decision to other nodes within the network.

P-Early-Media 只應用 inside 定義在 RFC 3325 的 "Trust Domain". Nodes in such a Trust Domain are explicitly trusted by its users and end-systems to authorize early media requests only when allowed by early media policy within the Trust Domain.

This document does NOT offer a general early media authorization model suitable for inter-domain use or use in the Internet at large. Furthermore, since the early media requests are not cryptographically certified, they are subject to forgery, replay, and falsification in any architecture that does not meet the requirements of the Trust Domain.

An early media request also lacks an indication of who specifically is making or modifying the request, and so it must be assumed that the Trust Domain is making the request. Therefore, the information is only meaningful when securely received from a node known to be a member of the Trust Domain.

Although this extension can be used with parallel forking, it does not improve on the known problems with early media and parallel forking, as described in RFC 3960, unless one can assume the use of symmetric RTP.


待整理

Section 4.1 以後

P-Access-Network-Info[RFC7315]
P-Answer-State [RFC4964]
P-Asserted-Identity [RFC3325]
P-Asserted-Service [RFC6050]
P-Called-Party-ID [RFC7315]
P-Charge-Info [RFC8496]
P-Charging-Function-Addresses [RFC7315]
P-Charging-Vector [RFC7315]
P-DCS-Trace-Party-ID [RFC5503]
P-DCS-OSPS [RFC5503]
P-DCS-Billing-Info [RFC5503]
P-DCS-LAES [RFC5503]
P-DCS-Redirect [RFC5503]
P-Media-Authorization [RFC3313]
P-Preferred-Identity [RFC3325]
P-Preferred-Service [RFC6050]
P-Private-Network-Indication [RFC7316]
P-Profile-Key [RFC5002]
P-Refused-URI-List [RFC5318]
P-Served-User [RFC5502] [RFC8498]
P-User-Database [RFC4457]
P-Visited-Network-ID[RFC7315]

 

2021年3月13日 星期六

SIP PRACK

PRACK (Provisional Response ACKnowledgement)  是 SIP 用來確認暫時回應 (Provisional Response) 有順利送達,定義在 RFC3262

INVITE 的最後回應會間隔重送直到收到 ACK,其中成功回應和 ACK 的可靠機制是端對端的。但 180 Ringing 等暫時回應,在 RFC3261 並沒有重送機制,沒送到對方就不知道有振鈴。PRACK 模仿 ACK,暫時回應會主動間隔重送直到收到 PRACK。不同的是,PRACK 和一般 SIP Method (如 BYE) 同款,是獨立的 Transaction 而有自己的回應確認收到。

使用 PRACK 機制,每個暫時回應帶 RSeq 封頭放序號。PRACK 帶 RAck 封頭放要確認暫時回應對應的 RSeq 序號。PRACK 確認並不是 cumulative,為了 congestion control 建議暫時回應 PRACK 後才送下一個。

是否支援或啟用 PRACK 依照 Option Tag 機制,Tag 名稱是 100rel,步驟如下:

  1. UAC 發一開始的 INVITE:Require 或 Supported 放 100rel 表示強制或選用 PRACK。
  2. UAS:
    • 如果強制使用 PRACK 但不支援,回 420 Bad Extension (Unsupported 放 100rel) 後結束。
    • 如果要啟用 PRACK,送非 100 的暫時回應時,放 Require: 100rel 和 RSeq。(exponential backoff?) 重送暫時回應直到收到 PRACK。最後沒收到 PRACK 則回 5xx 拒絕原始請求。重送回應
  3. UAC 收到有啟用 PRACK 的暫時回應:一樣建立 dialog,並送 PRACK 含 RAck,內容是要 acknowledge 的 RSeq 和 CSeq。照一般 Transaction 重送 PRACK。
  4. UAS 收到 PRACK:回 200 OK 並停止重送暫時回應。
新增兩個封頭:RSeq 和 RAck
  • RSeq:只用在可靠的暫時回應,值是 1 ~ 232 - 1 數字。
    Example: RSeq: 988789
  • RAck:只用在 PRACK 請求,內容包括要 acknowladge 的暫時回應的 RSeq 和 CSeq。
    Example: RAck: 776656 1 INVITE
說明
  • PRACK 像一般 SIP 訊息 hop-by-hop 傳送和自己的 response。
  • 100 Trying 是 hop-by-hop,PRACK 是 end-to-end 的機制。
  • 如果有 INVITE 以外需要 100 以外暫時回應的 SIP Method,PRACK 應該也適用。
  • UAS 送 18x 時啟用 PRACK,如果最後成功接聽,除非暫時回應有 SDP 外,可以收到 PRACK 前送最後回應。最後回應後才收到 PRACK 該回 481 還是 200?
  • 重送 ACK 由收到 2xx 驅動,但重送 PRACK 獨立於收到暫時回應,所以暫時回應重送的 exponential backup 毋限 T2。

BNF

PRACKm       = %x50.52.41.43.4B ; PRACK in caps
Method       = INVITEm / ACKm / OPTIONSm / BYEm
               / CANCELm / REGISTERm / PRACKm
               / extension-method
RAck         = "RAck" HCOLON response-num LWS CSeq-num LWS Method
response-num = 1*DIGIT
CSeq-num     = 1*DIGIT
RSeq         = "RSeq" HCOLON response-num

參考

  • 能和 Transaction 整合?
  • exponential backoff (指數型退讓)

2021年3月6日 星期六

SIP Authentication

 SIP 認證

--> INVITE/REGISTER

<-- 401 Unauthorized 或 407 Proxy Authentication Required 含 WWW-Authenticate 或 Proxy-Authenticate

--> 請求含  Authorization 或 Proxy-Authorization

RFC 3261 Section 22.2 概述 Authorization 的使用,Section 22.4 說明和 HTTP 認證一起使用時的語法和語意。 Authorization (和 Proxy-Authorization) 多個信頭欄位值不能合併成逗號分隔的列表,要分成多個信頭欄位行。

Authentication-InfoAuthorizationProxy-Authenticate

2020年12月19日 星期六

SIP NOTIFY

SIP Method NOTIFY 讓遠端有事件時提供 notification 。

RFC6665 向前相容並 obsolete RFC3265,並稍微更新 RFC4660

能夠 request asynchronous notification of events 提供用處 in many types of SIP services for which cooperation between end-nodes is required. Note, however, that event packages based on this framework may define arbitrarily elaborate rules that govern the subscription and notification for the events or classes of events they describe. "event packages" in Section 5.

應用

  • automatic callback services (based on terminal state events)
  • buddy lists (based on user presence events)
  • 留言通知 (MWI,message waiting indications)
  • PSTN and Internet Internetworking (PINT) [RFC2848] status (based on call state events).
  • 搭配 REFER
  • 告知特業設定,例如註冊後告知是否有設勿干擾或轉接

典型流程是先透過 SIP SUBSCRIBE 訂閱 Event 後建立 dialog,Event 包括 resource or call state for various resources or calls。之後收到 SIP NOTIFY 並更新 dialog 狀態。

   Subscriber          Notifier
       |-----SUBSCRIBE---->|     Request state subscription
       |<-------200--------|     Acknowledge subscription
       |<------NOTIFY----- |     Return current state information
       |--------200------->|
       |<------NOTIFY----- |     Return current state information
       |--------200------->|

訂閱有逾時,由後續 SUBSCRIBE 請求續訂。

...

3.1.2. Identification of Subscribed Events and Event Classes

Event 由 Request URI、Event Type、和 (optionally) 信體識別。The Request URI of a SUBSCRIBE request contains enough information to route the request to the appropriate entity per the request routing procedures outlined in [RFC3261]. It also contains enough information to identify the resource for which event notification is desired, but not necessarily enough information to uniquely identify the nature of the event (e.g., "sip:adam@example.com" would be an appropriate URI to subscribe to for my presence state; it would also be an appropriate URI to subscribe to the state of my voice mailbox).

SUBSCRIBE 必須含有單一 Event,表示要訂閱哪個 event 或 class of events。The "Event" header field will contain a token that indicates the type of state for which a subscription is being requested. This token will be registered with the IANA and will correspond to an event package that further describes the semantics of the event or event class. If the event package to which the event token corresponds defines behavior associated with the body of its SUBSCRIBE requests, those semantics apply. Event packages may also define parameters for the "Event" header field; if they do so, they must define the semantics for such parameters.

3.1.3. Additional SUBSCRIBE Header Field Values

Because SUBSCRIBE 建立 dialog,可包含 Accept 表示後續 NOTIFY 允許的信體格式。Event packages MUST define the behavior for SUBSCRIBE requests without "Accept" header fields; usually, this will connote a single, default body type.

3.2. NOTIFY

NOTIFY 通知 subscribers 有訂閱的狀態改變。訂閱透過 SUBSCRIBE 建立,過去也透過 REFER [RFC3515] 或其它方式建立。NOTIFY 是 target refresh request。

3.2.1. Identification of Reported Events, Event Classes, and Current State

Identification of events being reported in a notification is very similar to that described for subscription to events (see Section 3.1.2). NOTIFY request "Event" MUST 包含單一 event package name for which a notification is being generated. The package name in the "Event" header field MUST match the "Event" header field in the corresponding SUBSCRIBE request. Event packages may define semantics associated with the body of their NOTIFY requests; if they do so, those semantics apply. NOTIFY request bodies are expected to provide additional details about the nature of the event that has occurred and the resultant resource state. When present, the body of the NOTIFY request MUST be formatted into one of the body formats specified in the "Accept" header field of the corresponding SUBSCRIBE request (or the default type according to the event package description, if no "Accept" header field was specified). This body will contain either the state of the subscribed resource or a pointer to such state in the form of a URI (see Section 5.4.13).

4. Node Behavior

...

8.4. Augmented BNF Definitions

   SUBSCRIBEm        = %x53.55.42.53.43.52.49.42.45 ; SUBSCRIBE in caps
   NOTIFYm           = %x4E.4F.54.49.46.59 ; NOTIFY in caps
   extension-method  = SUBSCRIBEm / NOTIFYm / token

   Event             =  ( "Event" / "o" ) HCOLON event-type
                        *( SEMI event-param )
   event-type        =  event-package *( "." event-template )
   event-package     =  token-nodot
   event-template    =  token-nodot
   token-nodot       =  1*( alphanum / "-"  / "!" / "%" / "*"
                            / "_" / "+" / "`" / "'" / "~" )

   ; The use of the "id" parameter is deprecated; it is included
   ; for backwards-compatibility purposes only.

   event-param       =  generic-param / ( "id" EQUAL token )

   Allow-Events      =  ( "Allow-Events" / "u" ) HCOLON event-type
                        *(COMMA event-type)

   Subscription-State   = "Subscription-State" HCOLON substate-value
                          *( SEMI subexp-params )
   substate-value       = "active" / "pending" / "terminated"
                          / extension-substate
   extension-substate   = token
   subexp-params        =   ("reason" EQUAL event-reason-value)
                          / ("expires" EQUAL delta-seconds)
                          / ("retry-after" EQUAL delta-seconds)
                          / generic-param
   event-reason-value   =   "deactivated"
                          / "probation"
                          / "rejected"
                          / "timeout"
                          / "giveup"
                          / "noresource"
                          / "invariant"
                          / event-reason-extension
   event-reason-extension = token

參考

2020年10月30日 星期五

SIP REFER

SIP Method REFER 透過 Refer-To 提供第三方資訊給對方去聯繫,並隱含訂閱 refer Event 回報是否聯繫成功 (Event subscriptions 定義在 RFC3265)。在 INVITE Dialog 外也可使用,會建立一個 Dialog。

應用

Call Transfer。例如 A 和 B 通話中,判斷需要和 C 談,所以送 REFER 給 B 提供 C 的 Contact 資訊。B 允許下嘗試用來呼叫 C。B 將會回報是否聯繫成功給 A。

Refer-To (r) 信頭欄位

REFER 請求必須要 Refer-To,Refer-To 只用在 REFER 請求,提供參照的 URL,可加密。由於 Contact 是 Route/Record-Route 機制的重要部份,不能用來表示參照的 URL。

格式

( name-addr / addr-spec ) * (SEMI generic-param)

範例

Refer-To: sip:alice@atlanta.example.com

Refer-To: <sip:bob@biloxi.example.net?Accept-Contact=sip:bobsdesk.
       biloxi.example.net&Call-ID%3D55432%40alicepc.atlanta.example.com>

Refer-To: <sip:dave@denver.example.org?Replaces=12345%40192.168.118.3%3B
          to-tag%3D12345%3Bfrom-tag%3D5FFE-3994>

Refer-To: <sip:carol@cleveland.example.org;method=SUBSCRIBE>

Refer-To: http://www.ietf.org

REFER 請求處理

  • 回 400 Bad Request 如果沒有 Refer-To 或多於一個 Refer-To。
  • Proxy 或 UA 可回 100 Trying 或適當的 4xx ~ 6xx。
  • 接受回 202 Accepted,並訂閱 refer,馬上 NOTIFY 回報。
    • 聯繫 Refer-To 提供的 URL,例如有參數 method=INVITE 用 INVITE。
    • NOTIFY 回報使用和 REFER 相同的 Dialog。Event 是 refer,可能有 id 參數放 REFER CSeq 序號區別多個 REFER。含信體 message/sipfrag (RFC3240)。一開始 Subscription-State expires 參數告知 duration,也可能告知停刊。後續發 REFER 者可停訂或續訂 refer。
    • 信體基本要有 SIP 回應狀態行,可包含其它 SIP 信頭欄位。
      • SIP/2.0 100 Trying (聯繫進行中)
      • SIP/2.0 200 OK (聯繫成功)
      • SIP/2.0 503 Service Unavailable (聯繫失敗)
      • SIP/2.0 603 Declined (參照失敗)

其它

只有 REFER 能訂閱 refer

refer event package

RFC3515 2.4.7 以後未看

參考

  1. RFC3515 The SIP Refer Method

2020年10月24日 星期六

SIP OPTIONS

SIP Method,可用在 Dialog 內或 Dialog 外。RFC3261 §11

UA 註冊成功後,約每分鐘送 SIP OPTIONS 確認 UA 是否還在,不在一直確認到註冊逾時。

2020年9月26日 星期六

SIP CANCEL 取消請求

SIP CANCEL 取消請求:

  • 要取消的那個關聯請求,稱為原始請求。
  • 只是嘗試針對原始請求的 Transaction 進行取消,沿用原始請求的 Via branch 找原始請求的 Transaction:
    • 找不到 Transaction 回 481 Call Leg/Transaction Does Not Exist。
      • 已送成功回應算找不到 Transaction?
      • 已送失敗回應算找不到 Transaction?(也就是 Transaction 狀態不是 Proceeding)
    • 否則回 200 OK。
  • 原始請求:
  • 可能一下子還不會有最後回應的請求才需要,通常會先有暫時回應。馬上 (200ms 以內) 就最後回應的請求不需要暫時回應,送 CANCEL 到對方收到可能已經發出最後回應而造成 race condition。
  • CANCEL 不是 INVITE 專用,但目前只有 RFC3261 的 INVITE 符合,Client 只對 INVITE 發 CANCEL。Server 設計應當對所有請求通用 (除了 CANCEL 和 ACK 以外),以後或許有別的請求可 CANCEL。
  • CANEL 不屬於 Regular Transaction

CANCEL INVITE 讓 UAS 停止處理 (如「停止振鈴」)。re-INVITE 可以 CANCEL 嗎?

註:RFC3261 限制 CANCEL 收到任何回應之後才能發,確保 Server 收到 CANCEL 前收到原始請求。RFC2543 沒此規定,所以 CANCEL 有可能比原始請求先到。

CANCEL 可由 UAC 或 Proxy 產生。CANCEL 屬於「點對點」請求,Stateful Proxy 不是只是轉送,需回應 CANCEL,並對所有關聯 branch 進行 CANCEL。另外,也不能加上 Authorization 要求重送來盤問取得適當的憑證。

 在 RFC2543,CANCEL 和 INVITE 的 Transaction 是混在一起的,UAS 收到 CANCEL 後就不回應原始請求,不會回 487。

Client 行為

建立 CANCEL 請求:
  • 沿用原始請求的 Request-URI、Call-ID、CSeq 的序號、From (含 tag)、和 To (含 tag)。CSeq 的 Method 是 CANCEL。
    • 註:To tag 未必有,含 To tag 也似乎不必要。
  • 只有一個 Via,和原始請求的頂頭 Via 一致,好讓 Server 比對出要取消的 Transaction。
  • 須包含原始請求的 Route,讓 Stateless Proxy 能夠適當地繞 CANCEL。(在 RFC2543 沒清楚定義)
  • 不能有 Require 或 Proxy-Require。(應該被忽略。都要取消了,額外要求也就沒意義。)
傳送 CANCEL
  • 已收到最後回應,送了也沒用,所以不該送。
  • 等到收到任何暫時回應才能送,否則 Server 有可能比原始請求還早收到 CANCEL。但 RFC2543 不用等到收到任何暫時回應。此時可能有 To tag,也可能沒有。
  • 如同一般 Transaction 建立 Client Transaction 附上和原始請求仝款的目的位址、port 和 transport 傳送請求。

處理 CANCEL 回應 (不用理會結果如何)

  • 481 Call Leg/Transaction Does Not Exist:要取消的 Transaction 不存在。(不用取消了?)
  • 200 OK:要取消的 Transaction 存在,但未必表示取消成功。
  • 逾時:
收原始請求的回應 (就跟原本的處置一樣,都會移除原始請求的 Client Transaction)
  • 200 OK:原始請求成功,取消失敗。
  • 487 Request Terminated:取消成功。(註:RFC2543 UAS 不會送 487,只能等逾時)
  • 其它錯誤:原始請求失敗也就不用取消了。
  • 逾時 ( 64*T1 秒):視為已經取消。

註:就 INVITE 而言,UAC 發出 CANCEL 後 dialog 仍 confirmed,只能先 ACK 再 BYE 結束 dialog。early dialog 可嘗試用 CANCEL 結束,也可以用 BYE 結束。被叫端只能收到 ACK 後 BYE

Proxy 轉送最後回應時,必須取消進行中的所有相關 Client Transaction。這之前或當下,原始請求仍可能收到其它 branch 產生的 200 OK。

如果 Proxy 的 Client Transaction (Timer C) 逾時,此時可基於目前狀況 (如使用率) 重設 Timer 動態延長 Transaction 生存時間。或者結束 Client Transaction,此時如果有收到暫時回應,Proxy 必須產生 Transaction 的 CANCEL (等多久?)。
如果沒收到暫時回應,則視為收到 408 Request Timeout。

Server 行為

CANCEL 要求 Server 端 TU,取消符合的 Transaction。註:CANCEL 和 ACK 不能取消。

不同 Server 類型有不同 CANCEL 處理方式:
  • UAS:
    • 如同通用 UAS 方式處理,但由於 CANCEL 是 hop-by-hop 請求,不能加上 Authorization 要求重送來盤問取得適當的憑證。
    • 找不到參照的 Transaction,回  481 Call Leg/Transaction Does Not Exist。
    • 回 200 OK。
  • Stateless UAS:忽略 CANCEL。因為沒紀錄 Transaction,無法針對 Transaction 取消。
  • Stateless Proxy:轉送。
  • Stateful Proxy:
    • 找不到參照的 Transaction,轉送。
    • 回 200 OK,並對所有進行中 branch 產生 CANCEL。
    • INVITE Expire 逾時
  • Redirect Server:回 2xx 並結束參照的 Transaction,自己不產生任何請求。

參考

  1. RFC3261 §9 Canceling a Request§16 Proxy Behavior§8.2.7 Stateless UAS Behavior§8.3 Redirect Servers、。

2020年8月13日 星期四

SIP Proxy

Proxy 或 Proxy Server 是 Server 和 Client 的合體。首先它是 Server,能接收 SIP 請求。然後又是 Client,轉送 Server 收到的請求或產生請求。

2020年3月15日 星期日

SIP Transactions

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 完成。流程如下:
  1. [Client] TU 發出請求,Transaction 層建立一個新 Client Transaction,透過傳輸層確保可靠地送出。
  2. [Server] 收到請求時上傳給 TU 處理,依需要建立 Server Transaction。
  3. [Server] TU 的任何回應,都經過 Server Transaction 給傳輸層確保可靠地傳送。如果收到重傳的請求,不再送給 TU,只重傳回應。
  4. [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請求CallingTimer ATimer B
收到暫時回應Proceeding
收到失敗回應送 ACK
CompletedTimer D
逾時 或 無法送 或 收到 2xx
TerminatedNA
事件狀態主動重送逾時
送一般請求TryingTimer ETimer F
收到暫時回應ProceedingTimer ETimer F
收到最後回應CompletedTimer K
逾時 或 無法送
TerminatedNA

Server Transaction

事件狀態再次收到請求主動重送逾時
收到請求Trying忽略
送暫時回應Proceeding重送回應無 (PRACK)
一般送最後回應CompletedTimer J
INV送失敗回應Timer G64*T1
INV送成功回應
收到 ACK (相同 Via branch)Confirmed忽略Timer I
收到 ACK (在 TU 有 Dialog)
逾時 或
無法送 (通知 TU)
TerminatedNA
送成功回應在 TU 有 DialogTU 處理TU 處理
收到 ACK (不同 Via branch)TU 處理

INV 成功回應的重傳本來是在 TU 處理的,可整合到 Completed 狀態,採用 INV 失敗回應相同的 Timer G 重送和 Timer H 結束,變成 INV 最後回應都採用相同的處理方式。此時收到 ACK 也要進到 Confirmed 狀態。

註:transaction 源自 HTTP

參考

  1. RFC3261 §17

2019年7月20日 星期六

SIP Timers

Timer適用說明
T1預設 0.5s 17.1.1.1預估的來回時間 (RTT)
T24snon-INVITE 請求
INVITE 回應
最大重送間隔
T45snon-INVITE Client Transaction訊息停留在網路的最大時間
AT1, 2*T1, ...
INV 請求UDP 請求重送間隔
ET1, 2*T1, ... (最大 T2)
non-INV 請求
G17.2.1INVITE 回應的重送間隔
B64*T1Client Transaction等候回應逾時
F
H64*T117.2.1等候 ACK
DUDP: > 32s
TCP/SCTP:0
INVITE Client Transaction等候重送的回應
KUDP: T4
TCP/SCTP:0
Non-INVITE Client Transaction等候重送的回應
IUDP: T4
TCP/SCTP:0
17.2.1等候重送的 ACK
JUDP: 64*T1
TCP/SCTP:0
17.2.2等候重送的非 INVITE 請求
C> 3min16.6 bullet 11Proxy INVITE transaction 逾時

參考:RFC3261 Table of Timer Values

2019年7月19日 星期五

SIP Option Tags

option-tag 是 SIP擴充選項,例如 100rel 等,本身是不超過 20 字元的 alphanum 字串 (在 SIP ABNF 定義 option-tag = token),用在信頭欄位 RequireProxy-RequireSupportedUnsupported 來表示是否支援及採用。

擴充選項的支援及採用

UAC 在 Supported 放可支援的 option-tag、或在 Require 放 UAS 必須支援的 option-tag、或在 Proxy-Require 放 Proxy 必須支援的 option-tag。Proxy 如果不支援 Proxy-Require 的 option-tag,回 420。UAS 如果不支援 Require 的 option-tag,回 420。UAS 需要的 option-tag 沒列在 Supported,回 421。UAS 採用的 option-tag,列在回應的 Require。

UAC
  • 發請求表示可支援的或必須支援的 option-tag。
  • CANCEL 和失敗 INVITE 的 ACK 不用 Require 和 Proxy-Require。
  • 成功 INVITE 的 ACK 只能包含 INVITE Require 和 Proxy-Require 有的 option-tag。
  • UAC 如果收到 420 Bad Extension,應該嘗試再次請求,但這次略過列在回應 Unsupported 的 option-tag。
Proxy UAS
  • 檢查 Require,如有不支援回 420 Bad Extension
  • 需要某 option-tag 才能進行,但 Supported 沒列,回 421 Extension Required
  • 忽略 CANCEL 和失敗 INVITE 的 ACK 的 Require。
  • 成功 INVITE 的 ACK 只能包含 INVITE Require 有的 option-tag。
  • 採用時,回應含 Require 列啟用的 option-tag。
Client 和 Server 間的 negotiation option-tag 的機制不會因都支援而有所延遲。

相關信頭欄位

Proxy-Require

告訴 Proxy 必須支援哪些 option-tag 才能處理請求。proxy 可新增、不能加密。

Proxy-Require  =  "Proxy-Require" HCOLON option-tag *(COMMA option-tag)

範例:
Proxy-Require: foo

Require

必須支援的 option-tag,用在請求、421 Extension Required、或在其它回應表示採用。Proxy 可新增、不能加密。

Require       =  "Require" HCOLON option-tag *(COMMA option-tag)
範例:
Require: 100rel

Supported (k)

在請求是 UAC 告訴 UAS 支援哪些 option-tag。在 SIP OPTIONS 回應是 UAS 告訴 UAC 支援哪些 option-tag。空白表示所有都不支援。在 RFC2543 沒有。INVITE 及其 2xx 回應應該要有。

Supported  =  ( "Supported" / "k" ) HCOLON [option-tag *(COMMA option-tag)]
範例:
Supported: 100rel

Unsupported

用在 420 Bad Extension,告訴 UAC 不支援的 option-tag。

Unsupported  =  "Unsupported" HCOLON option-tag *(COMMA option-tag)
範例:
Unsupported: foo

相關回應碼

420 Bad Extension

不當擴充。

Proxy 不認得 Proxy-Require 或 UAS 不認得 Require 列的某些 option-tag。回應必須含有 Unsupported 表示不支援的 option-tag 有哪些。UAC 應該再次嘗試請求,但這次略過列在回應 Unsupported 的 option-tag。

例如:
      UAC->UAS:   INVITE sip:watson@bell-telephone.com SIP/2.0
                  Require: 100rel

      UAS->UAC:   SIP/2.0 420 Bad Extension
                  Unsupported: 100rel

421 Extension Required

需要擴充。

UAS 需要特定 option-tag 處理請求,但沒列在請求的 Supported。421 回應含 Require 表示需要的 option-tag。罕用。

擴充選項

全部註冊的擴充選項及相關 RFC 參見 IANA

參考

RFC 3261

SIP header Via

所有 SIP 訊息 都要有 Via,縮寫 v。一開始的 UAC 和後續途經的每個 proxy 都會疊加一個 Via 放傳送的位址,依序作為回應的路徑。 格式 sent-protocol sent-by [ ;branch= branch ][ ; 參數 ...] s...