SIP 規範
RFC 3261 §25 提到
SIP 訊息格式用 ABNF 描述。ABNF (Augmented Backus–Naur Form, 擴充巴科斯範式,
RFC 2234 →
RFC 4234 →
RFC 5234) 改良自 BNF (Backus–Naur Form),是一種用來描述通訊協定中一系列數值格式的語言。
ABNF 規範是一些如下推導規則的集合,以 crlf 換行結束
rule = definition ;comment crlf
- rule:規則名稱,不分大小寫,以字母開始
- definition:規則定義,可能包含一個或多個規則名稱、或數值的組合。
- comment:需要的話,「;」開始為註解。
為了便於觀看,每條規則靠左對齊。當一個規則需要多行時,第二行開始縮排。
規則最後解析成一串值,值可用「%」表示法,二進位前置「%b」、十進位前置「%d」、十六進位前置「%x」。多個值串接可用一個前置,後面好幾個數字用「.」連接。一串值也可以用類似 C 語言字串前後加「"」表示,但在 ABNF 的字串是
不分大小寫的。如果要分大小寫需要使用「%」表示法。
定義中使用的 Operator,依照 Precedence 高低
- Value Range Alternatives (範圍):%c##-##
- Repetition (重複)
- *Rule:Rule 重複 0 次以上,* 前後可分別加上數字表示最少及最多的重複次數。
- nRule:n 是數字,重複 n 次
- Sequence Group (群組):(Rule1 Rule2)
- Optional Sequence (選擇性的):[RULE]
- Concatenation (串接):Rule1 Rule2
- Alternatives (或者):Rule1 / Rule2
- Incremental Alternatives (新增或者):Rule1 =/ Rule2
基本規則
US ASCII coded 字元集定義在 ANSI X3.4-1986,等同於國際標準 ISO 646。
DIGIT | = | %x30-39 | ; 0-9,數字 |
ALPHA | = | %x41-5A / %x61-7A | ; A-Z / a-z,英文字母 |
alphanum | = | ALPHA / DIGIT | ; 英文字母和數字 |
| 一些規則採自 RFC 2396 但更新為 RFC 2234 相容,包括: |
reserved | = | ";" / "/" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / "," | ;
|
unreserved | = | alphanum / mark |
|
mark | = | "-" / "_" / "." / "!" / "~" / "*" / "'" / "(" / ")" | ;mark 意思? |
escaped | = | "%" HEXDIG HEXDIG |
|
HEXDIG | = | DIGIT / "A" / "B" / "C" / "D" / "E" / "F" | ;十六進位數字不分大小寫 |
LHEX | = | DIGIT / %x61-66 | ;十六進位數字限制小寫。 |
| ASCII 中的可列印字元,除了 reserved (10 字元)、unreserved (71 字元)、%、和 SP 外,剩下 "#[\]^`{|}<> 12 字元。 |
| SWS 是選擇性的 LWS,一般用在 token 和 separators 間。 |
LF = %x0A ;linefeed
CR = %x0D ;carriage return
CRLF = CR LF ;換行
HTAB = %x09 ;horizontal tab
SP = %x20
WSP = SP / HTAB ;white space
LWS = [*WSP CRLF] 1*WSP ;linear whitespace
;方便拆行顯示,語意和一個 SP 一樣。
;一個或連續 WSP,前面可有一個換行,換行前可有連續 WSP。
;接收或轉送可取代為 SP (和 HTTP/1.1 行為一致)。
SWS = [LWS] ;sep whitespace,選擇性的 LWS。
信頭的名稱和值。
規則 TEXT-UTF8-TRIM 用在描述性的欄位內容,並不打算給訊息解析器解釋,字元來自
UTF-8 字元集,不能是「quoted-string」,其中開頭和結束 LWS 是無意義的。
TEXT-UTF8-TRIM = 1*TEXT-UTF8char *(*LWS TEXT-UTF8char)
TEXT-UTF8char = %x21-7E / UTF8-NONASCII
UTF8-NONASCII = %xC0-DF 1UTF8-CONT /
%xE0-EF 2UTF8-CONT /
%xF0-F7 3UTF8-CONT /
%xF8-Fb 4UTF8-CONT /
%xFC-FD 5UTF8-CONT
UTF8-CONT = %x80-BF
TEXT-UTF8-TRIM 只在 LWS 使用 CRLF 作為折行,LWS 會換成一個 SP 來解釋。
註:HTTP 使用 ISO 8859-1 字元集,以 ASCII 為基礎,在空置的 0xA0-0xFF 加入 96 個字母及符號,藉以供使用附加符號的拉丁字母語言使用。
許多 SIP 欄位包含來自「token」的字元,用 LWS 或「separators 」分隔的字。除非特別提到,「token」是不分大小寫 (case-insensitive)。在參數值如需要用到這些分隔字元,必須在「quoted-string」裡面。「word」特別用在 Call-ID,可使用「token」和大部分分隔字元。
token = 1*(alphanum / "-" / "." / "!" / "%" / "*"
/ "_" / "+" / "`" / "'" / "~" )
DQUOTE = %x22 ; " (Double Quote)
separators = "(" / ")" / "<" / ">" / "@" /
"," / ";" / ":" / "\" / DQUOTE /
"/" / "[" / "]" / "?" / "=" /
"{" / "}" / SP / HTAB
word = 1*(alphanum / "-" / "." / "!" / "%" / "*" /
"_" / "+" / "`" / "'" / "~" /
"(" / ")" / "<" / ">" /
":" / "\" / DQUOTE /
"/" / "[" / "]" / "?" /
"{" / "}" )
當分隔字元用在 token 間,這些字元前後常可以允許 whitespace:
STAR = SWS "*" SWS ; 星號
SLASH = SWS "/" SWS ; slash
EQUAL = SWS "=" SWS ; 等號
LPAREN = SWS "(" SWS ; 左括號, %x28
RPAREN = SWS ")" SWS ; 右括號, %x29
RAQUOT = ">" SWS ; 左角括號
LAQUOT = SWS "<" ; 右角括號
SEMI = SWS ";" SWS ; 分號
LDQUOT = SWS DQUOTE ; 雙引號開始
RDQUOT = DQUOTE SWS ; 雙引號結束
comment 的內容用 () 括號包起來,只用在少數 header 欄位值。
其它欄位,括號是參數值的一部分。
comment = LPAREN *(ctext / quoted-pair / comment) RPAREN
ctext = %x21-27 / %x2A-5B / %x5D-7E / UTF8-NONASCII
/ LWS ; 所有字元,除了左右括號和反斜線。
用雙引號 quoted 的文字串解析為單一字,裡面的雙引號和反斜線要 escaped。
quoted-string = SWS DQUOTE *(qdtext / quoted-pair ) DQUOTE
qdtext = LWS / %x21 / %x23-5B / %x5D-7E
/ UTF8-NONASCII ; 不含雙引號和反斜線。
backslash 字元 ("\") 只用在「quoted-string」和「comment 」作單字元 quoting 機制。為避免與折行和 header separation 衝突,CR 和 LF 不能用此機制 escaped。
註:HTTP/1.1 可以 escape CR 和 LF。
quoted-pair = "\" (%x00-09 / %x0B-0C
/ %x0E-7F) ; 不含 CR 和 LF
任何字元用在 message-body
OCTET = %x00-FF ; 8 bits of data
註:規則名稱雖然不分大小寫,特殊基本規則多用大寫。
alphanum ! ' * - . _ ~ | unreserved | token | word |
| ( ) | unreserved | sep | word |
| $ & | reserved | - | - |
| + | reserved | token | word |
| , ; = @ | reserved | sep | - |
| / : ? | reserved | sep | word |
| " <> [] {} \ | - | sep | word |
| # ^ | | - | - | - |
| % ` | - | token | word |
| SP, HTAB | - | sep | - |
- unreserved 和 reserved 沒有重疊。在有些欄位,unreserved 會擴充,例如 user-unreserved (擴充只取自 reserved?)。word 包含全部 unreserved。
- token 則不含 unreserved 的 (),但多了 % 和 `、及 reserved 中的 +。
- token 和 separators 沒有重疊。
SIP-message = Request / Response ; SIP 訊息 只有兩種,Request 和 Response。
Request = Request-Line *( message-header ) CRLF [ message-body ]
Response = Status-Line *( message-header ) CRLF [ message-body ]
= (Accept
/ Accept-Encoding
/ Accept-Language
/ Alert-Info
/ Allow
/ Authentication-Info
/ Authorization
/ Call-ID
/ Call-Info
/ Contact
/ Content-Disposition
/ Content-Encoding
/ Content-Language
/ Content-Length
/ Content-Type
/ CSeq
/ Date
/ Error-Info
/ Expires
/ From
/ In-Reply-To
/ Max-Forwards
/ MIME-Version
/ Min-Expires
/ Organization
/ Priority
/ Proxy-Authenticate
/ Proxy-Authorization
/ Proxy-Require
/ Record-Route
/ Reply-To
/ Require
/ Retry-After
/ Route
/ Server
/ Subject
/ Supported
/ Timestamp
/ To
/ Unsupported
/ User-Agent
/ Via
/ Warning
/ WWW-Authenticate
/ extension-header) CRLF
INVITEm = %x49.4E.56.49.54.45 ; INVITE in caps
ACKm = %x41.43.4B ; ACK in caps
OPTIONSm = %x4F.50.54.49.4F.4E.53 ; OPTIONS in caps
BYEm = %x42.59.45 ; BYE in caps
CANCELm = %x43.41.4E.43.45.4C ; CANCEL in caps
REGISTERm = %x52.45.47.49.53.54.45.52 ; REGISTER in caps
Method = INVITEm / ACKm / OPTIONSm / BYEm
/ CANCELm / REGISTERm ; 以上是大寫的 method 名稱,實際上不分大小寫。
/ extension-method
extension-method = token
Response = Status-Line
*( message-header )
CRLF
[ message-body ]
Accept = "Accept" HCOLON
[ accept-range *(COMMA accept-range) ]
accept-range = media-range *(SEMI accept-param)
media-range = ( "*/*"
/ ( m-type SLASH "*" )
/ ( m-type SLASH m-subtype )
) *( SEMI m-parameter )
accept-param = ("q" EQUAL qvalue) / generic-param
qvalue = ( "0" [ "." 0*3DIGIT ] )
/ ( "1" [ "." 0*3("0") ] )
generic-param = token [ EQUAL gen-value ]
gen-value = token / host / quoted-string
Accept-Encoding = "Accept-Encoding" HCOLON
[ encoding *(COMMA encoding) ]
encoding = codings *(SEMI accept-param)
codings = content-coding / "*"
content-coding = token
Accept-Language = "Accept-Language" HCOLON
[ language *(COMMA language) ]
language = language-range *(SEMI accept-param)
language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) / "*" )
Alert-Info = "Alert-Info" HCOLON alert-param *(COMMA alert-param)
alert-param = LAQUOT absoluteURI RAQUOT *( SEMI generic-param )
Allow = "Allow" HCOLON [Method *(COMMA Method)]
Authorization = "Authorization" HCOLON credentials
credentials = ("Digest" LWS digest-response)
/ other-response
digest-response = dig-resp *(COMMA dig-resp)
dig-resp = username / realm / nonce / digest-uri
/ dresponse / algorithm / cnonce
/ opaque / message-qop
/ nonce-count / auth-param
username = "username" EQUAL username-value
username-value = quoted-string
digest-uri = "uri" EQUAL LDQUOT digest-uri-value RDQUOT
digest-uri-value = request-uri ; Equal to request-uri as specified
by HTTP/1.1
message-qop = "qop" EQUAL qop-value
cnonce = "cnonce" EQUAL cnonce-value
cnonce-value = nonce-value
nonce-count = "nc" EQUAL nc-value
nc-value = 8LHEX
dresponse = "response" EQUAL request-digest
request-digest = LDQUOT 32LHEX RDQUOT
auth-param = auth-param-name EQUAL
( token / quoted-string )
auth-param-name = token
other-response = auth-scheme LWS auth-param
*(COMMA auth-param)
auth-scheme = token
Authentication-Info = "Authentication-Info" HCOLON ainfo
*(COMMA ainfo)
ainfo = nextnonce / message-qop
/ response-auth / cnonce
/ nonce-count
nextnonce = "nextnonce" EQUAL nonce-value
response-auth = "rspauth" EQUAL response-digest
response-digest = LDQUOT *LHEX RDQUOT
Call-ID = ( "Call-ID" / "i" ) HCOLON callid
callid = word [ "@" word ]
Call-Info = "Call-Info" HCOLON info *(COMMA info)
info = LAQUOT absoluteURI RAQUOT *( SEMI info-param)
info-param = ( "purpose" EQUAL ( "icon" / "info"
/ "card" / token ) ) / generic-param
delta-seconds = 1*DIGIT
Content-Disposition = "Content-Disposition" HCOLON
disp-type *( SEMI disp-param )
disp-type = "render" / "session" / "icon" / "alert"
/ disp-extension-token
disp-param = handling-param / generic-param
handling-param = "handling" EQUAL
( "optional" / "required"
/ other-handling )
other-handling = token
disp-extension-token = token
Content-Encoding = ( "Content-Encoding" / "e" ) HCOLON
content-coding *(COMMA content-coding)
Content-Language = "Content-Language" HCOLON
language-tag *(COMMA language-tag)
language-tag = primary-tag *( "-" subtag )
primary-tag = 1*8ALPHA
subtag = 1*8ALPHA
Content-Length = ( "Content-Length" / "l" ) HCOLON 1*DIGIT
Content-Type = ( "Content-Type" / "c" ) HCOLON media-type
media-type = m-type SLASH m-subtype *(SEMI m-parameter)
m-type = discrete-type / composite-type
discrete-type = "text" / "image" / "audio" / "video"
/ "application" / extension-token
composite-type = "message" / "multipart" / extension-token
extension-token = ietf-token / x-token
ietf-token = token
x-token = "x-" token
m-subtype = extension-token / iana-token
iana-token = token
m-parameter = m-attribute EQUAL m-value
m-attribute = token
m-value = token / quoted-string
CSeq = "CSeq" HCOLON 1*DIGIT LWS Method
Date = "Date" HCOLON SIP-date
SIP-date = rfc1123-date
rfc1123-date = wkday "," SP date1 SP time SP "GMT"
date1 = 2DIGIT SP month SP 4DIGIT
; day month year (e.g., 02 Jun 1982)
time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
; 00:00:00 - 23:59:59
wkday = "Mon" / "Tue" / "Wed"
/ "Thu" / "Fri" / "Sat" / "Sun"
month = "Jan" / "Feb" / "Mar" / "Apr"
/ "May" / "Jun" / "Jul" / "Aug"
/ "Sep" / "Oct" / "Nov" / "Dec"
Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri)
error-uri = LAQUOT absoluteURI RAQUOT *( SEMI generic-param )
Expires = "Expires" HCOLON delta-seconds
In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid)
Max-Forwards = "Max-Forwards" HCOLON 1*DIGIT
MIME-Version = "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT
Min-Expires = "Min-Expires" HCOLON delta-seconds
Organization = "Organization" HCOLON [TEXT-UTF8-TRIM]
Priority = "Priority" HCOLON priority-value
priority-value = "emergency" / "urgent" / "normal"
/ "non-urgent" / other-priority
other-priority = token
Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge
challenge = ("Digest" LWS digest-cln *(COMMA digest-cln))
/ other-challenge
other-challenge = auth-scheme LWS auth-param
*(COMMA auth-param)
digest-cln = realm / domain / nonce
/ opaque / stale / algorithm
/ qop-options / auth-param
realm = "realm" EQUAL realm-value
realm-value = quoted-string
domain = "domain" EQUAL LDQUOT URI
*( 1*SP URI ) RDQUOT
URI = absoluteURI / abs-path
nonce = "nonce" EQUAL nonce-value
nonce-value = quoted-string
opaque = "opaque" EQUAL quoted-string
stale = "stale" EQUAL ( "true" / "false" )
algorithm = "algorithm" EQUAL ( "MD5" / "MD5-sess"
/ token )
qop-options = "qop" EQUAL LDQUOT qop-value
*("," qop-value) RDQUOT
qop-value = "auth" / "auth-int" / token
Proxy-Authorization = "Proxy-Authorization" HCOLON credentials
Proxy-Require = "Proxy-Require" HCOLON option-tag
*(COMMA option-tag)
option-tag = token
Require = "Require" HCOLON option-tag *(COMMA option-tag)
Retry-After = "Retry-After" HCOLON delta-seconds
[ comment ] *( SEMI retry-param )
retry-param = ("duration" EQUAL delta-seconds)
/ generic-param
Server = "Server" HCOLON server-val *(LWS server-val)
server-val = product / comment
product = token [SLASH product-version]
product-version = token
Subject = ( "Subject" / "s" ) HCOLON [TEXT-UTF8-TRIM]
Supported = ( "Supported" / "k" ) HCOLON
[option-tag *(COMMA option-tag)]
Timestamp = "Timestamp" HCOLON 1*(DIGIT)
[ "." *(DIGIT) ] [ LWS delay ]
delay = *(DIGIT) [ "." *(DIGIT) ]
Unsupported = "Unsupported" HCOLON option-tag *(COMMA option-tag)
User-Agent = "User-Agent" HCOLON server-val *(LWS server-val)
Via = ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm)
via-parm = sent-protocol LWS sent-by *( SEMI via-params )
ia-params = via-ttl / via-maddr
/ via-received / via-branch
/ via-extension
via-ttl = "ttl" EQUAL ttl
via-maddr = "maddr" EQUAL host
via-received = "received" EQUAL (IPv4address / IPv6address)
via-branch = "branch" EQUAL token
via-extension = generic-param
sent-protocol = protocol-name SLASH protocol-version
SLASH transport
protocol-name = "SIP" / token
protocol-version = token
transport = "UDP" / "TCP" / "TLS" / "SCTP"
/ other-transport
sent-by = host [ COLON port ]
ttl = 1*3DIGIT ; 0 to 255
Warning = "Warning" HCOLON warning-value *(COMMA warning-value)
warning-value = warn-code SP warn-agent SP warn-text
warn-code = 3DIGIT
warn-agent = hostport / pseudonym
; the name or pseudonym of the server adding
; the Warning header, for use in debugging
arn-text = quoted-string
pseudonym = token
WWW-Authenticate = "WWW-Authenticate" HCOLON challenge
extension-header = header-name HCOLON header-value
header-name = token
header-value = *(TEXT-UTF8char / UTF8-CONT / LWS)
message-body = *OCTET ; 任何長度任何字元
Request-URI = SIP-URI / SIPS-URI / absoluteURI
absoluteURI = scheme ":" ( hier-part / opaque-part )
scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
- Request-URI 較複雜一點,基本結構都會有「:」,之前的部份稱 scheme,之後依照 scheme 解釋。
Header 欄位
message-header = (Accept / Accept-Encoding / Accept-Language / Alert-Info / Allow / Authentication-Info / Authorization / Call-ID / Call-Info / Contact / Content-Disposition / Content-Encoding / Content-Language / Content-Length / Content-Type / CSeq / Date / Error-Info / Expires / From / In-Reply-To / Max-Forwards / MIME-Version / Min-Expires / Organization / Priority / Proxy-Authenticate / Proxy-Authorization / Proxy-Require / Record-Route / Reply-To / Require / Retry-After / Route / Server / Subject / Supported / Timestamp / To / Unsupported / User-Agent / Via / Warning / WWW-Authenticate / extension-header) CRLF
extension-header = header-name HCOLON header-value
- 把各種 header 都列出來了,最終都有 CRLF。
Contact、From、Reply-To、和 To 的格式都是 name-addr 或 addr-spec 加上參數,另外 name-addr 也用在 Record-Route 和 Route。 name-addr 含有用 angle bracket 包起來的 addr-spec,所以 addr-spec 可以看成是 name-addr 的簡化,只有在沒有 display-name 且 addr-spec 沒有 「,」、「?」、「;」時使用。「;」為了跟信頭參數的區別。
name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
display-name = *(token LWS)/ quoted-string
addr-spec = SIP-URI / SIPS-URI / absoluteURI
angle bracket 前後可有 LWS
參考
- wikipedia: Augmented_Backus-Naur_Form,擴充巴科斯範式
- RFC3966 The tel URI for Telephone Numbers obsolete RFC2806 URLs for Telephone Calls