SIP 是文本協定,使用 UTF-8 字元集 和 CRLF換行,用一般的文字的使用者界面就可以看, 通用的訊息格式用 ABNF 描述是按呢:
generic-message = start-line ;開始的一行標明請求方法或回應碼。
*message-header ;批頭。每個結束是換行。每個可能多行。
CRLF ;空白行,表示 message-header 結束。
[ message-body ] ;選擇性的訊息體。
訊息內容用換行區隔,第 1 行就是 start-line,可以看出是請求還是回應。回應一開始是「SIP/2.0」,擱來是 3 個數字的回應碼。請求一開始是 Method。
擱來是足多 message-header,簡稱 header、批頭。每一個生著「名:值」,嗎是用換行結束。猶毋過一個 header 也可以分成多行,多的行開頭有空白。每個批頭 可以用 CRLF 緊接著 White Space 分成多行。
header 的結束是用一個空白行表示。最尾有時陣有 message-body,譬如放 SDP。message-body 有可能是二進位資料。
內容大部分無分大小寫,比較時大寫和小寫是同款,除了 (case-sensitive or case-insensitive?)
- Method 和 CSeq 內的 Method。
- SIP 和 SIPS URI 的 userinfo 部份當作是分大小寫的字串,簡化比較,包含 password 或 telephone-subscriber 格式。所以,原本在 telephone-subscriber 轉換成 userinfo,不分大小寫的部份須轉為小寫,參數順序除了 isdn-subaddress 和 post-dial 先放按照順序,其它按照名稱 lexically 排。
- SIP-Version 字串不分大小寫,但實做必須送大寫(為什麼?)。
- Call-ID 值。
- value 用 quoted string,除非特別指明。
- Date 放 RFC 1123 date。
- 其它特別定義的地方。
在 RFC 2543,換行可以是 CR、LF、或 CRLF,RFC 3261 只能是 CRLF。
start-line
開始行就是一行,欄位用單一空白 (SP) 區隔,訊息只有請求和回應兩種,辨別符合 Request-Line 是請求、符合 Status-Line 是回應。
start-line = Request-Line / Status-Line Request-Line = Method SP Request-URI SP SIP-Version CRLF Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF
請求和回應都有協定版本 SIP-Version,開頭必須是「SIP/」,不分大小寫,但實作必須用大寫送。接著兩個數字以「.」隔開,在 RFC 3261 是「2.0」。Status-Line 開頭是 SIP-Version,和 Request-Line 的 Method 不會相同而區別。
SIP-Version = "SIP" "/" 1*DIGIT "." 1*DIGITMethod 可以是 REGISTER、INVITE、ACK、CANCEL、BYE 等,不會有「/」,可以跟 SIP-Version 區別。
Method = INVITEm / ACKm / OPTIONSm / BYEm / CANCELm / REGISTERm / extension-method extension-method = token token = 1*(alphanum / "-" / "." / "!" / "%" / "*" / "_" / "+" / "`" / "'" / "~" )
請求對象的 URI (用戶或服務),描述在 RFC 3261 Section 19.1 的 sip: 或 sips: 或 RFC 2396 的通用 URI,不能有 unescaped spaces 或控制字元,也不能用 "<>" 包起來。SIP 元件可以支援如 RFC 2806 的 "tel" URI 方案,可以用任何機制轉換成 SIP URI、SIPS URI、或其它 scheme。
Request-URI = SIP-URI / SIPS-URI / absoluteURI
Status-Code (回應碼) 是 3 碼數字表示請求的回應狀態,方便機器判讀。
Status-Code = 3DIGIT
Reason-Phrase 是回應碼的簡易描述,讓人方便理解。每個回應碼有預設內容,但可以修改,例如依據請求 Accept-Language 的語言。不能使用的可顯示 ASCII 碼有 "、#、%、<、>、[、\、]、^、{、|、},其中「%」作為 escaped 使用,可用來顯示這些排除的碼。其它為什麼要排除呢?
Reason-Phrase = *(reserved / unreserved / escaped / UTF8-NONASCII / UTF8-CONT / SP / HTAB)
message-header
每個訊息至少會有多個基本的 header。每個 header 可能跨多行。因為有少數例外,實際批頭格式是依每種批頭名列舉,通用格式 依循 RFC 2822 Section 2.2:
header = header-name HCOLON header-value *(COMMA header-value) CRLF header-name = token ;至少一個字元 HCOLON = *( WSP ) ":" SWS ;冒號,和名稱在同一行,前可有 WSP,後可有 LWS。 header-value = *(TEXT-UTF8char / UTF8-CONT / LWS) ;使用 UTF8 編碼,可有 WSP,WSP 前可換行。 COMMA = SWS "," SWS ;逗號,前後可有 LWS,讓每個值可獨立一行。
名稱 (header-name) 和值 (header-value) 用冒號區隔,如有多個值則用逗號分隔。冒號必須和名稱同行,中間可以有空白(sp 或 tab)。值可以在同一行或換行,換行開頭是 WSP。值內容中的 WS 處,可變成 LWS 換行,在接收或轉送時可取代回 SP。
不同名 header 的相對順序不重要,但需要 proxy 處理的 header (譬如 Via、Route、Record-Route、Proxy-Require、Max-Forwards、和 Proxy-Authorization) 建議放頭前,較快解析到。
有的 header 可以出現多次,相對順序就重要了。欄位允許有多個逗號分隔的值,可以分成多個同款 header,意思相同。另外 WWW-Authenticate、Authorization、Proxy-Authenticate、和 Proxy-Authorization 也可以出現多次,但不能合併成一個 header。
欄位值的格式定義是跟著每個欄位名稱,不是 TEXT-UTF8 octets 的 opaque 系列, 就是 whitespace、tokens、separators、和 quoted strings 的組合。大部分值遵循通用格式,後面可以有一系列分號分隔的成對 parameter-name 和 parameter-value:
field-name: field-value *(;parameter-name=parameter-value)
雖然可以有任意數目的參數,相同參數名稱不能出現超過 1 次。
當比較 header,header 名稱是不分大小寫的。除非額外特別說明,欄位值、參數名稱、和參數值是不分大小寫的。token 總是不分大小寫的。除非額外特別說明,值用 quoted strings 表示是分大小寫的。
https://lirobo.blogspot.com/2018/11/sip-header-fields.html
message-body
請求和回應的 message-body 使用、類型和解釋取決於請求的 Method。message-body 的媒體類型必須由 Content-Type 決定,也可以說明字元集。Content-Encoding 必須省略,除非有任何編碼 (例如壓縮) 才使用。
也可以使用定義在 RFC 2046 的 "multipart" MIME 類型。如果要送包含 multipart 的 message-body,但請求的 Accept 不含 multipart,必須送一個 session 描述為非 multipart 的 message-body。
message-body 可由二進位資料組成。
當 sender 沒有提供明確字元集參數,媒體子類型 "text" 預設使用 UTF-8。
詳細用法見 RFC 5621。
message-body 長度見 Content-Length。
不能使用 HTTP/1.1 的 "chunked" transfer 編碼。
註:chunk 編碼改變訊息內容傳送為一系列每個有自己大小的 chunk。
transport
一個 SIP 訊息可用一個 UDP 或其它不可靠 transport 協定的 datagram 攜帶,限制請見 RFC 3261 Section 18。在 stream 導向 transport 之上使用 SIP 訊息,必須忽略 start-line 之前的 CRLF
[參見 RFC 2616 Section 4.1],而且 header 欄位 Content-Length 是必要的,訂出在 stream 中每個 SIP 訊息的結束。
延伸閱讀
- SIP 訊息雖然語法在字元集和規範和 RFC 2822 有所不同,但基本格式是一樣的。
- 除了字元集和 HTTP/1.1 不同,SIP 訊息和 header 欄位語法大部分相同,但 SIP 不是 HTTP 的擴充。此外 HTTP 只用可靠的 transport 協定傳送。
- SIP-Version 依循 HTTP Version (HTTP 取代為 SIP,HTTP/1.1 取代為 SIP/2.0) 關於版本順序、合規要求、和版號更新。 不像 HTTP/1.1,SIP-Version 視為文字字串,但實際上應該沒有什麼不同。
- SIP header 欄位依循 HTTP header 欄位的語法定義,以及延伸到多行的規則。但 HTTP 是用 implicit whitespace and folding,而 RFC 3261 符合 RFC 2234 使用 explicit whitespace and folding 作為文法整體的一部分。多個名稱相同的 header 欄位,其值是逗號分隔的列表,可以結合成一個 header 欄位也應用在 SIP,但文法不同而特定規則不同。
沒有留言:
張貼留言