跳到主要内容

7. SIP 消息 (SIP Messages)

7 SIP 消息 (SIP Messages)

SIP 是一种基于文本的协议, 使用 UTF-8 字符集 (RFC 2279 [7]).

SIP 消息要么是 client 发往 server 的 request, 要么是 server 发往 client 的 response.

Request (Section 7.1) 和 Response (Section 7.2) 消息都使用 RFC 2822 [3] 的基本格式, 尽管其语法在字符集和具体语法细节上有所不同. (例如, SIP 允许一些在 RFC 2822 中无效的 header field.) 两类消息都由 start-line, 一个或多个 header field, 一个表示 header field 结束的空行, 以及可选的 message-body 组成.

     generic-message  =  start-line
*message-header
CRLF
[ message-body ]
start-line = Request-Line / Status-Line

start-line, 每一行 message-header, 以及空行 MUST 以 carriage-return line-feed 序列 (CRLF) 结束. 注意, 即使没有 message-body, 该空行也 MUST 存在.

除上述字符集差异外, SIP 的 message 和 header field 语法在很大程度上与 HTTP/1.1 相同. 为避免在此重复语法和语义, 我们使用 [HX.Y] 指代当前 HTTP/1.1 规范 (RFC 2616 [8]) 的 Section X.Y.

然而, SIP 不是 HTTP 的扩展.

7.1 请求 (Requests)

SIP request 以 Request-Line 作为 start-line, 这使其区别于其他消息. Request-Line 包含 method name, Request-URI 和 protocol version, 各元素之间由单个空格 (SP) 字符分隔.

Request-Line 以 CRLF 结束. 除行尾 CRLF 序列外, 不允许出现 CR 或 LF. 各元素中均不允许 linear whitespace (LWS).

     Request-Line  =  Method SP Request-URI SP SIP-Version CRLF

Method: 本规范定义六种方法: REGISTER 用于注册联系信息, INVITE, ACK 和 CANCEL 用于建立会话, BYE 用于终止会话, OPTIONS 用于查询服务器能力. 记录在 standards track RFC 中的 SIP 扩展可以定义其他方法.

Request-URI: Request-URI 是 Section 19.1 中描述的 SIP 或 SIPS URI, 或一个通用 URI (RFC 2396 [5]). 它指示该请求所寻址的用户或服务. Request-URI MUST NOT 包含未转义的空格或控制字符, 并且 MUST NOT 被包在 "\<>" 中.

SIP 元素 MAY 支持 scheme 不是 "sip" 和 "sips" 的 Request-URI, 例如 RFC 2806 [9] 的 "tel" URI scheme. SIP 元素 MAY 使用其可用的任何机制转换非 SIP URI, 结果可以是 SIP URI, SIPS URI 或其他 scheme.

SIP-Version: request 和 response 消息都包含正在使用的 SIP 版本, 并遵循 [H3.1] 中关于版本排序, 合规要求和版本号升级的规定 (其中 HTTP 替换为 SIP, HTTP/1.1 替换为 SIP/2.0). 为符合本规范, 发送 SIP 消息的应用 MUST 包含值为 "SIP/2.0" 的 SIP-Version. SIP-Version 字符串大小写不敏感, 但实现 MUST 发送大写形式.

与 HTTP/1.1 不同, SIP 将版本号视为字面字符串. 实际上, 这应该不会造成差异.

7.2 响应 (Responses)

SIP response 以 Status-Line 作为 start-line, 这使其区别于 request. Status-Line 由 protocol version 后跟数字 Status-Code 及其关联的文本短语组成, 各元素之间由单个 SP 字符分隔.

除最后的 CRLF 序列外, 不允许出现 CR 或 LF.

  Status-Line  =  SIP-Version SP Status-Code SP Reason-Phrase CRLF

Status-Code 是 3 位整数结果码, 指示理解并满足请求的尝试结果. Reason-Phrase 旨在给出 Status-Code 的简短文本描述. Status-Code 供自动机使用, 而 Reason-Phrase 供人类用户使用. client 不要求检查或显示 Reason-Phrase.

虽然本规范为 reason phrase 建议了特定措辞, 实现 MAY 选择其他文本, 例如使用请求的 Accept-Language header field 所指示的语言.

Status-Code 的第一位定义响应类别. 最后两位没有分类作用. 因此, 任何状态码在 100 到 199 之间的响应称为 "1xx response", 状态码在 200 到 299 之间的响应称为 "2xx response", 以此类推. SIP/2.0 允许第一位取六种值:

  1xx: Provisional -- 请求已收到, 正在继续处理请求;

2xx: Success -- 动作已被成功接收, 理解和接受;

3xx: Redirection -- 为完成请求还需要采取进一步动作;

4xx: Client Error -- 请求包含错误语法, 或此服务器无法满足该请求;

5xx: Server Error -- 服务器未能满足一个看起来有效的请求;

6xx: Global Failure -- 任何服务器都无法满足该请求.

Section 21 定义这些类别并描述各个代码.

7.3 Header Field

SIP header field 在语法和语义上都类似 HTTP header field. 特别地, SIP header field 遵循 [H4.2] 对 message-header 的语法定义, 以及将 header field 扩展到多行的规则. 然而, 后者在 HTTP 中用隐式 whitespace 和 folding 指定. 本规范符合 RFC 2234 [10], 并且只使用显式 whitespace 和 folding 作为语法的组成部分.

[H4.2] 还规定, 多个同名且其值为逗号分隔列表的 header field 可以合并为一个 header field. 这也适用于 SIP, 但由于语法不同, 具体规则不同. 具体而言, 任何语法形式为

  header  =  "header-name" HCOLON header-value *(COMMA header-value)

的 SIP header 都允许把同名 header field 合并为一个逗号分隔列表. 除非 header field value 为 "*", Contact header field 允许逗号分隔列表.

7.3.1 Header Field 格式 (Header Field Format)

header field 遵循 RFC 2822 [3] Section 2.2 给出的相同通用 header 格式. 每个 header field 由 field name 后跟冒号 (":") 和 field value 组成.

  field-name: field-value

Section 25 中为 message-header 指定的形式语法允许冒号两侧存在任意数量的 whitespace; 然而, 实现应避免在 field name 与冒号之间使用空格, 并在冒号与 field-value 之间使用单个空格 (SP).

  Subject:            lunch
Subject : lunch
Subject :lunch
Subject: lunch

因此, 上述形式都有效且等价, 但最后一种是首选形式.

header field 可以扩展到多行, 方法是在每个额外行前放置至少一个 SP 或 horizontal tab (HT). 换行以及下一行开头的 whitespace 被视为单个 SP 字符. 因此, 以下形式等价:

  Subject: I know you're there, pick up the phone and talk to me!
Subject: I know you're there,
pick up the phone
and talk to me!

不同 field name 的 header field 的相对顺序没有意义. 然而, RECOMMENDED 将 proxy 处理所需的 header field (例如 Via, Route, Record-Route, Proxy-Require, Max-Forwards 和 Proxy-Authorization) 放在消息顶部附近, 以便快速解析. 同一 field name 的 header field row 的相对顺序很重要. 当且仅当该 header field 的整个 field-value 被定义为逗号分隔列表 (即遵循 Section 7.3 中定义的语法) 时, 一个消息中 MAY 出现多个同名 header field row. MUST 可以把多个 header field row 合并成一个 "field-name: field-value" 对, 且不改变消息语义; 做法是把每个后续 field-value 追加到第一个之后, 各值之间用逗号分隔. 该规则的例外是 WWW-Authenticate, Authorization, Proxy-Authenticate 和 Proxy-Authorization header field. 消息中 MAY 出现多个这些名称的 header field row, 但由于其语法不遵循 Section 7.3 中列出的一般形式, 它们 MUST NOT 被合并为单个 header field row.

实现 MUST 能够处理任意组合形式的多个同名 header field row, 无论是每行单值形式还是逗号分隔值形式.

以下 header field row 组都是有效且等价的:

  Route: `&lt;sip:[email protected]>`
Subject: Lunch
Route: `&lt;sip:[email protected]>`
Route: `&lt;sip:[email protected]>`

Route: `&lt;sip:[email protected]>`, `&lt;sip:[email protected]>`
Route: `&lt;sip:[email protected]>`
Subject: Lunch

Subject: Lunch
Route: `&lt;sip:[email protected]>`, `&lt;sip:[email protected]>`,
`&lt;sip:[email protected]>`

以下每个块都是有效的, 但彼此不等价:

  Route: `&lt;sip:[email protected]>`
Route: `&lt;sip:[email protected]>`
Route: `&lt;sip:[email protected]>`

Route: `&lt;sip:[email protected]>`
Route: `&lt;sip:[email protected]>`
Route: `&lt;sip:[email protected]>`

Route: `&lt;sip:[email protected]>`,`&lt;sip:[email protected]>`,
`&lt;sip:[email protected]>`

header field-value 的格式按 header-name 分别定义. 它始终要么是 TEXT-UTF8 octet 的不透明序列, 要么是 whitespace, token, separator 和 quoted string 的组合. 许多现有 header field 会遵循一种通用形式: 一个 value 后跟以分号分隔的一系列 parameter-name, parameter-value 对:

     field-name: field-value *(;parameter-name=parameter-value)

即使可以在 header field value 后附加任意数量的参数对, 任意给定 parameter-name MUST NOT 出现超过一次.

比较 header field 时, field name 始终大小写不敏感. 除非某个特定 header field 的定义另有说明, field value, parameter name 和 parameter value 都大小写不敏感. token 始终大小写不敏感. 除非另有指定, 以 quoted string 表达的值大小写敏感. 例如,

  Contact: `&lt;sip:[email protected]>`;expires=3600

等价于

  CONTACT: `&lt;sip:[email protected]>`;ExPiReS=3600

并且

  Content-Disposition: session;handling=optional

等价于

  content-disposition: Session;HANDLING=OPTIONAL

以下两个 header field 不等价:

  Warning: 370 devnull "Choose a bigger pipe"
Warning: 370 devnull "CHOOSE A BIGGER PIPE"

7.3.2 Header Field 分类 (Header Field Classification)

有些 header field 只在 request 或 response 中有意义. 它们分别称为 request header field 和 response header field. 如果 header field 出现在与其类别不匹配的消息中 (例如 response 中出现 request header field), 则 MUST 忽略它. Section 20 定义每个 header field 的分类.

7.3.3 紧凑形式 (Compact Form)

SIP 提供一种机制, 可用缩写形式表示常见 header field name. 当消息否则会过大而无法由可用传输承载时, 这可能很有用 (例如使用 UDP 时超过 maximum transmission unit (MTU)). 这些 compact form 在 Section 20 中定义. header field name 的 compact form MAY 在任何时候替代较长形式, 而不改变消息语义. 同一消息中, 一个 header field name MAY 同时以长形式和短形式出现. 实现 MUST 接受每个 header name 的长形式和短形式.

7.4 Body

除非另有说明, request (包括本规范扩展中新定义的 request) MAY 包含 message body. body 的解释取决于请求方法.

对于 response message, 请求方法和响应状态码决定任何 message body 的类型和解释. 所有 response MAY 包含 body.

7.4.1 Message Body 类型 (Message Body Type)

message body 的 Internet media type MUST 由 Content-Type header field 给出. 如果 body 经过任何编码, 例如压缩, 则这 MUST 由 Content-Encoding header field 指示; 否则, Content-Encoding MUST 被省略. 如适用, message body 的字符集作为 Content-Type header-field value 的一部分指示.

RFC 2046 [11] 中定义的 "multipart" MIME type MAY 用在消息 body 内. 如果远端实现通过不包含 multipart 的 Accept header field 请求非 multipart message body, 则发送包含 multipart message body 的请求的实现 MUST 将 session description 作为非 multipart message body 发送.

SIP message MAY 包含二进制 body 或 body part. 当发送方没有提供显式 charset 参数时, "text" 类型的 media subtype 被定义为具有默认 charset 值 "UTF-8".

7.4.2 Message Body 长度 (Message Body Length)

body 长度以字节为单位, 由 Content-Length header field 提供. Section 20.14 详细描述该 header field 的必要内容.

HTTP/1.1 的 "chunked" transfer encoding MUST NOT 用于 SIP. (Note: chunked encoding 会修改消息 body, 以便将其作为一系列 chunk 传输, 每个 chunk 都有自己的 size indicator.)

7.5 SIP 消息分帧 (Framing SIP Messages)

与 HTTP 不同, SIP 实现可以使用 UDP 或其他不可靠 datagram protocol. 每个此类 datagram 承载一个 request 或 response. 关于不可靠传输的使用约束, 见 Section 18.

通过 stream-oriented transport 处理 SIP message 的实现 MUST 忽略 start-line 之前出现的任何 CRLF [H4.1].

  Content-Length header field value 用于定位流中每个 SIP message 的结束位置. 当 SIP message 通过 stream-oriented transport 发送时, 它始终存在.