8. 一般 User Agent 行为 (General User Agent Behavior)
8 一般 User Agent 行为 (General User Agent Behavior)
user agent 表示一个端系统. 它包含生成请求的 user agent client (UAC), 以及响应这些请求的 user agent server (UAS). UAC 能够基于某种外部刺激 (用户点击按钮, 或 PSTN 线路上的信号) 生成请求并处理响应. UAS 能够接收请求, 并基于用户输入, 外部刺激, 程序执行结果或其他机制生成响应.
当 UAC 发送请求时, 该请求会经过若干 proxy server, 这些 proxy server 将请求向 UAS 转发. 当 UAS 生成响应时, 该响应会向 UAC 转发.
UAC 和 UAS 过程强烈依赖两个因素. 第一, 请求或响应是在 dialog 内还是 dialog 外; 第二, 请求的方法. dialog 在 Section 12 中有完整讨论; 它们表示 user agent 之间的 peer-to-peer 关系, 并由特定 SIP 方法建立, 例如 INVITE.
本节讨论 UAC 和 UAS 处理 dialog 外请求时与方法无关的行为规则. 当然, 这包括那些本身会建立 dialog 的请求.
dialog 外请求和响应的安全过程在 Section 26 中描述. 具体而言, 存在用于 UAS 和 UAC 相互认证的机制. 还通过使用 S/MIME 加密 body 支持一组有限的隐私功能.
8.1 UAC 行为 (UAC Behavior)
本节覆盖 dialog 外的 UAC 行为.
8.1.1 生成请求 (Generating the Request)
由 UAC 形成的有效 SIP 请求至少 MUST 包含以下 header field: To, From, CSeq, Call-ID, Max-Forwards 和 Via; 所有这些 header field 在所有 SIP 请求中都是强制性的. 这六个 header field 是 SIP 消息的基本构件, 因为它们共同提供大多数关键消息路由服务, 包括消息寻址, 响应路由, 限制消息传播, 消息排序以及事务的唯一标识. 除这些 header field 外, 还需要强制性的 request line, 其中包含 method, Request-URI 和 SIP version.
dialog 外发送的请求示例包括用于建立会话的 INVITE (Section 13), 以及用于查询能力的 OPTIONS (Section 11).
8.1.1.1 Request-URI
消息的初始 Request-URI SHOULD 设置为 To field 中 URI 的值. 一个显著例外是 REGISTER 方法; REGISTER 的 Request-URI 设置行为见 Section 10. 出于隐私原因或便利性, 也可能不希望把这些 field 设置为相同值 (特别是当发起 UA 预期 Request-URI 会在传输途中被改变时).
在某些特殊情况下, 预先存在的 route set 会影响消息的 Request-URI. 预先存在的 route set 是一个有序 URI 集合, 标识一条 server 链, UAC 会把 dialog 外的出站请求发送到这条链. 通常, 它们由用户或服务提供商手工配置在 UA 上, 或通过某种非 SIP 机制配置. 当提供商希望为 UA 配置 outbound proxy 时, RECOMMENDED 通过提供一个仅包含单个 URI 的预先存在 route set 来完成, 该 URI 即 outbound proxy 的 URI.
当存在预先存在的 route set 时, MUST 遵循 Section 12.2.1.1 中详述的填充 Request-URI 和 Route header field 的过程 (即使没有 dialog), 并使用期望的 Request-URI 作为 remote target URI.
8.1.1.2 To
To header field 首先指定请求所期望的 "logical" 接收者, 或作为该请求目标的用户或资源的 address-of-record. 这可能是也可能不是请求的最终接收者. To header field MAY 包含 SIP 或 SIPS URI, 但在适当时也可以使用其他 URI scheme (例如 tel URL (RFC 2806 [9])). 所有 SIP 实现 MUST 支持 SIP URI scheme. 任何支持 TLS 的实现 MUST 支持 SIPS URI scheme. To header field 允许 display name.
UAC 可以通过多种方式获知如何为特定请求填充 To header field. 通常, 用户会通过人机界面建议 To header field, 可能是手工输入 URI, 或从某种地址簿中选择. 用户经常不会输入完整 URI, 而是输入一串数字或字母 (例如 "bob"). UA 可自行决定如何解释此输入. 使用该字符串形成 SIP URI 的 user part, 意味着 UA 希望该名称在 SIP URI 中 at-sign 右侧 (RHS) 的域内解析 (例如 sip:[email protected]). 使用该字符串形成 SIPS URI 的 user part, 意味着 UA 希望进行安全通信, 且该名称将在 at-sign RHS 的域内解析. RHS 通常是请求者的 home domain, 这允许 home domain 处理出站请求. 这对 "speed dial" 等需要在 home domain 内解释 user part 的功能很有用. 当 UA 不希望指定应解释用户输入电话号码的域时, 可以使用 tel URL. 相反, 请求经过的每个域都会获得解释机会. 例如, 机场中的用户可能登录并通过机场中的 outbound proxy 发送请求. 如果他们输入 "411" (这是美国本地目录查询的电话号码), 则需要由机场中的 outbound proxy 解释和处理, 而不是由用户的 home domain 处理. 在这种情况下, tel:411 是正确选择.
dialog 外的请求 MUST NOT 包含 To tag; 请求 To field 中的 tag 标识 dialog 的对端. 由于尚未建立 dialog, 因此不存在 tag.
关于 To header field 的更多信息, 见 Section 20.39. 以下是有效 To header field 的示例:
To: Carol `<sip:[email protected]>`
8.1.1.3 From
From header field 指示请求发起者的逻辑身份, 可能是用户的 address-of-record. 与 To header field 一样, 它包含一个 URI, 并可选包含 display name. SIP 元素使用它来确定对请求应用哪些处理规则 (例如自动拒接呼叫). 因此, From URI 不包含 IP 地址或 UA 所运行主机的 FQDN 非常重要, 因为这些不是逻辑名称.
From header field 允许 display name. 如果客户端身份需要保持隐藏, UAC SHOULD 使用 display name "Anonymous", 并附带一个语法正确但除此之外无意义的 URI (例如 sip:[email protected]).
通常, 特定 UA 生成的请求中用于填充 From header field 的值由用户或用户本地域的管理员预先配置. 如果某个 UA 由多个用户使用, 它可能具有可切换 profile, 其中包含与 profile 用户身份对应的 URI. 请求接收者可以认证请求发起者, 以确认他们确实是其 From header field 所声称的身份 (关于认证, 见 Section 22).
From field MUST 包含一个由 UAC 选择的新 "tag" 参数. 关于选择 tag 的细节, 见 Section 19.3.
关于 From header field 的更多信息, 见 Section 20.20. 示例:
From: "Bob" `<sips:[email protected]>` ;tag=a48s
From: sip:[email protected];tag=887s
From: Anonymous `<sip:[email protected]>`;tag=hyh8
8.1.1.4 Call-ID
Call-ID header field 作为唯一标识符, 用于把一系列消息组合在一起. 在一个 dialog 中, 任一 UA 发送的所有请求和响应的 Call-ID MUST 相同. UA 的每次注册中, 它 SHOULD 相同.
在 UAC 于任何 dialog 外创建的新请求中, 除非被特定方法行为覆盖, Call-ID header field MUST 由 UAC 选择为在空间和时间上全局唯一的标识符. 所有 SIP UA 都必须具有某种手段, 保证它们生成的 Call-ID header field 不会被任何其他 UA 偶然生成. 注意, 当某些失败响应要求修改请求后重试请求时 (例如认证 challenge), 这些重试请求不被视为新请求, 因此不需要新的 Call-ID header field; 见 Section 8.1.3.5.
RECOMMENDED 在生成 Call-ID 时使用 cryptographically random identifier (RFC 1750 [12]). 实现 MAY 使用 "localid@host" 形式. Call-ID 大小写敏感, 并且仅逐字节比较.
使用 cryptographically random identifier 可提供一定防护, 防止 session hijacking, 并降低无意 Call-ID 冲突的可能性.
为请求选择 Call-ID header field value 不需要配置或人机界面.
关于 Call-ID header field 的更多信息, 见 Section 20.8.
示例:
Call-ID: [email protected]
8.1.1.5 CSeq
CSeq header field 用作标识和排序事务的方式. 它由 sequence number 和 method 组成. method MUST 与请求的方法匹配. 对 dialog 外的非 REGISTER 请求, sequence number value 是任意的. sequence number value MUST 能表示为 32-bit unsigned integer, 并且 MUST 小于 2**31. 只要遵循上述指导, client 可以使用任意机制选择 CSeq header field value.
Section 12.2.1.1 讨论 dialog 内请求的 CSeq 构造.
示例:
CSeq: 4711 INVITE
8.1.1.6 Max-Forwards
Max-Forwards header field 用于限制请求在到达目的地途中可经过的跳数. 它由一个整数构成, 每经过一跳减一. 如果 Max-Forwards 值在请求到达目的地之前达到 0, 请求将以 483(Too Many Hops) 错误响应被拒绝.
UAC MUST 在它发起的每个请求中插入 Max-Forwards header field, 其值 SHOULD 为 70. 选择此数值是因为它足够大, 可保证在没有 loop 时请求不会在任何 SIP 网络中被丢弃, 但又不会大到在发生 loop 时消耗过多 proxy 资源. 较低值应谨慎使用, 且仅在 UA 已知网络拓扑时使用.
8.1.1.7 Via
Via header field 指示事务使用的传输, 并标识响应应发送到的位置. 只有在选择了用于到达下一跳的传输之后 (这可能涉及使用 [4] 中的过程), 才会添加 Via header field value.
当 UAC 创建请求时, 它 MUST 在该请求中插入 Via. header field 中的 protocol name 和 protocol version MUST 分别为 SIP 和 2.0. Via header field value MUST 包含 branch 参数. 该参数用于标识由该请求创建的事务. client 和 server 都使用此参数.
对 UA 发送的所有请求, branch parameter value MUST 在空间和时间上唯一. 此规则的例外是 CANCEL 和针对非 2xx 响应的 ACK. 如下文所述, CANCEL 请求将具有与其取消的请求相同的 branch 参数值. 如 Section 17.1.1.3 所述, 针对非 2xx 响应的 ACK 也将具有与其确认响应的 INVITE 相同的 branch ID.
branch ID 参数用于充当 transaction ID 的唯一性属性, 并不是 RFC 2543 的一部分.
符合本规范的元素插入的 branch ID MUST 始终以字符 "z9hG4bK" 开始. 这 7 个字符用作 magic cookie (7 被认为足以确保较旧 RFC 2543 实现不会选择这样的值), 使接收请求的服务器能够判断 branch ID 是按本规范描述的方式构造的 (即全局唯一). 除此要求外, branch token 的精确格式由实现定义.
Via header 的 maddr, ttl 和 sent-by 组件会在请求由传输层处理时设置 (Section 18).
proxy 的 Via 处理在 Section 16.6 Item 8 和 Section 16.7 Item 3 中描述.
8.1.1.8 Contact
Contact header field 提供一个 SIP 或 SIPS URI, 可用于在后续请求中联系该 UA 的特定实例. 对任何可能导致建立 dialog 的请求, Contact header field MUST 存在并且恰好包含一个 SIP 或 SIPS URI. 对本规范中定义的方法而言, 这只包括 INVITE 请求. 对这些请求, Contact 的作用域是全局的. 也就是说, Contact header field value 包含 UA 希望接收请求的 URI, 并且即使在任何 dialog 外的后续请求中使用, 该 URI 也 MUST 有效.
如果 Request-URI 或顶部 Route header field value 包含 SIPS URI, Contact header field MUST 也包含 SIPS URI.
关于 Contact header field 的更多信息, 见 Section 20.10.
8.1.1.9 Supported 和 Require
如果 UAC 支持可由 server 应用于响应的 SIP 扩展, UAC SHOULD 在请求中包含 Supported header field, 列出这些扩展的 option tag (Section 19.2).
列出的 option tag MUST 仅引用 standards-track RFC 中定义的扩展. 这是为了防止 server 坚持要求 client 实现非标准的 vendor-defined feature 才能获得服务. experimental 和 informational RFC 定义的扩展明确排除在请求的 Supported header field 用法之外, 因为它们也经常用于记录 vendor-defined extension.
如果 UAC 希望坚持要求 UAS 理解某个扩展, 且 UAC 将把该扩展应用于请求以便处理该请求, 它 MUST 在请求中插入 Require header field, 列出该扩展的 option tag. 如果 UAC 希望将扩展应用于请求, 并坚持要求经过的任何 proxy 理解该扩展, 它 MUST 在请求中插入 Proxy-Require header field, 列出该扩展的 option tag.
与 Supported header field 一样, Require 和 Proxy-Require header field 中的 option tag MUST 仅引用 standards-track RFC 中定义的扩展.
8.1.1.10 其他消息组件 (Additional Message Components)
创建新请求并正确构造上述 header field 后, 添加任何额外的可选 header field, 以及该方法专有的任何 header field.
SIP 请求 MAY 包含 MIME-encoded message-body. 无论请求包含何种类型的 body, 都必须形成某些 header field 来表征 body 的内容. 关于这些 header field 的更多信息, 见 Section 20.11 到 Section 20.15.
8.1.2 发送请求 (Sending the Request)
随后计算请求目的地. 除非本地策略另有规定, 目的地 MUST 按如下方式应用 [4] 中描述的 DNS 过程来确定. 如果 route set 中第一个元素指示 strict router (导致按 Section 12.2.1.1 中描述的方式形成请求), 则该过程 MUST 应用于请求的 Request-URI. 否则, 该过程应用于请求中的第一个 Route header field value (如果存在), 或者在没有 Route header field 时应用于请求的 Request-URI. 这些过程产生一组有序的 address, port 和 transport 供尝试. 不管使用哪个 URI 作为 [4] 过程的输入, 如果 Request-URI 指定 SIPS resource, UAC MUST 遵循 [4] 的过程, 就好像输入 URI 是 SIPS URI.
本地策略 MAY 指定一组替代目的地供尝试. 如果 Request-URI 包含 SIPS URI, 则任何替代目的地 MUST 使用 TLS 联系. 除此之外, 如果请求不包含 Route header field, 对替代目的地没有限制. 这提供了一种简单替代方案, 可用来指定 outbound proxy, 而无需预先存在的 route set. 然而, 这种配置 outbound proxy 的方法 NOT RECOMMENDED; SHOULD 改用包含单个 URI 的预先存在 route set. 如果请求包含 Route header field, 请求 SHOULD 发送到从其最顶部值派生的位置, 但 MAY 发送到 UA 确信会遵守本文档中指定的 Route 和 Request-URI 策略 (而不是 RFC 2543 中的策略) 的任何 server. 特别地, 配置了 outbound proxy 的 UAC SHOULD 尝试把请求发送到第一个 Route header field value 指示的位置, 而不是采用把所有消息都发送到 outbound proxy 的策略.
这确保不添加 Record-Route header field value 的 outbound proxy 会从后续请求路径中退出. 它允许无法解析第一个 Route URI 的端点把该任务委托给 outbound proxy.
UAC SHOULD 遵循 [4] 中为有状态元素定义的过程, 逐个尝试地址直到联系到 server. 每次尝试都构成一个新事务, 因而每次都携带不同的 topmost Via header field value, 并带有新的 branch 参数. 此外, Via header field 中的 transport 值被设置为为目标 server 确定的任何 transport.
8.1.3 处理响应 (Processing Responses)
响应首先由传输层处理, 然后向上传递给事务层. 事务层执行其处理, 然后把响应向上传递给 TU. TU 中大部分响应处理是特定于方法的. 然而, 有一些与方法无关的一般行为.
8.1.3.1 事务层错误 (Transaction Layer Errors)
在某些情况下, 事务层返回的响应不是 SIP 消息, 而是事务层错误. 当从事务层收到 timeout error 时, MUST 将其视为已收到 408 (Request Timeout) 状态码. 如果传输层报告 fatal transport error (通常是由于 UDP 中的 fatal ICMP error 或 TCP 中的连接失败), 则该条件 MUST 被视为 503 (Service Unavailable) 状态码.
8.1.3.2 无法识别的响应 (Unrecognized Responses)
UAC MUST 将任何无法识别的最终响应视为等价于该类别的 x00 response code, 并且 MUST 能处理所有类别的 x00 response code. 例如, 如果 UAC 收到无法识别的响应码 431, 它可以安全地假定其请求有问题, 并把该响应当作收到 400 (Bad Request) response code 来处理. UAC MUST 将任何不同于 100 且无法识别的临时响应视为 183 (Session Progress). UAC MUST 能处理 100 和 183 响应.
8.1.3.3 Vias
如果 response 中存在多个 Via header field value, UAC SHOULD 丢弃该消息.
在请求发起者之前存在额外 Via header field value, 表明消息被错误路由或可能已损坏.
8.1.3.4 处理 3xx 响应 (Processing 3xx Responses)
收到重定向响应 (例如 301 response status code) 后, client SHOULD 使用 Contact header field 中的 URI, 基于被重定向请求构造一个或多个新请求. 此过程类似于 proxy 对 3xx 类响应进行 recursion, 详见 Section 16.5 和 Section 16.6. client 从初始 target set 开始, 其中恰好包含一个 URI, 即原始请求的 Request-URI. 如果 client 希望基于该请求的 3xx 类响应构造新请求, 它把要尝试的 URI 放入 target set. 在本规范限制内, client 可以选择把哪些 Contact URI 放入 target set. 与 proxy recursion 一样, 处理 3xx 类响应的 client MUST NOT 将任何给定 URI 添加到 target set 超过一次. 如果原始请求在 Request-URI 中有 SIPS URI, client MAY 选择递归到非 SIPS URI, 但 SHOULD 通知用户已重定向到不安全 URI.
任何新请求本身都可能收到包含原始 URI 作为 contact 的 3xx 响应. 两个位置可以被配置为相互重定向. 只把任何给定 URI 放入 target set 一次可防止无限重定向 loop.
随着 target set 增长, client MAY 以任意顺序向其中的 URI 生成新请求. 一种常见机制是按 Contact header field value 中的 "q" 参数值对集合排序. 向 URI 的请求 MAY 串行或并行生成. 一种方法是按递减 q-value 串行处理各组, 并在每个 q-value 组内并行处理 URI. 另一种方法是只按递减 q-value 顺序进行串行处理, 对相同 q-value 的 contact 任意选择.
如果联系列表中的某个地址导致失败 (按下一段定义), 元素移动到列表中的下一个地址, 直到列表耗尽. 如果列表耗尽, 则请求失败.
失败 SHOULD 通过失败响应码 (大于 399 的代码) 检测; 对于网络错误, client transaction 会向 transaction user 报告任何 transport layer failure. 注意, 某些响应码 (详见 8.1.3.5) 表示可以重试请求; 重新尝试的请求不应视为失败.
当收到特定 contact address 的失败时, client SHOULD 尝试下一个 contact address. 这将涉及创建新的 client transaction 来递送新请求.
为了基于 3xx 响应中的 contact address 创建请求, UAC MUST 将 target set 中的整个 URI 复制到 Request-URI 中, 但 "method-param" 和 "header" URI 参数除外 (这些参数的定义见 Section 19.1.1). 它使用 "header" 参数为新请求创建 header field value, 并按照 Section 19.1.5 中的指导覆盖与被重定向请求关联的 header field value.
注意, 在某些情况下, 在 contact address 中传递的 header field 可能改为追加到原始被重定向请求中的现有 request header field. 一般规则是, 如果 header field 可接受逗号分隔的值列表, 则新的 header field value MAY 追加到原始被重定向请求中的任何现有值. 如果 header field 不接受多个值, 原始被重定向请求中的值 MAY 被 contact address 中传递的 header field value 覆盖. 例如, 如果返回的 contact address 具有以下值:
sip:user@host?Subject=foo&Call-Info=`\`http://www.foo.com\``
则原始被重定向请求中的任何 Subject header field 会被覆盖, 但 HTTP URL 只会追加到任何现有 Call-Info header field value.
RECOMMENDED UAC 重用原始被重定向请求中使用的相同 To, From 和 Call-ID, 但 UAC MAY 也选择为新请求更新 Call-ID header field value 等.
最后, 一旦构造出新请求, 它会使用新的 client transaction 发送, 因而 MUST 在顶部 Via field 中具有新的 branch ID, 如 Section 8.1.1.7 所述.
在所有其他方面, 收到 redirect response 后发送的请求 SHOULD 重用原始请求的 header field 和 body.
在某些情况下, Contact header field value 可根据收到的状态码和是否存在过期间隔, 在 UAC 处临时或永久缓存; 见 Section 21.3.2 和 Section 21.3.3.
8.1.3.5 处理 4xx 响应 (Processing 4xx Responses)
某些 4xx response code 需要特定 UA 处理, 与方法无关.
如果收到 401 (Unauthorized) 或 407 (Proxy Authentication Required) 响应, UAC SHOULD 遵循 Section 22.2 和 Section 22.3 的授权过程, 使用凭据重试请求.
如果收到 413 (Request Entity Too Large) 响应 (Section 21.4.11), 则请求包含的 body 长度超过 UAS 愿意接受的长度. 如果可能, UAC SHOULD 重试请求, 要么省略 body, 要么使用较短长度的 body.
如果收到 415 (Unsupported Media Type) 响应 (Section 21.4.13), 则请求包含 UAS 不支持的 media type. UAC SHOULD 重试发送请求, 这次只使用响应中 Accept header field 列出的类型, 响应中 Accept-Encoding header field 列出的编码, 以及响应中 Accept-Language 列出的语言.
如果收到 416 (Unsupported URI Scheme) 响应 (Section 21.4.14), 则 Request-URI 使用了 server 不支持的 URI scheme. client SHOULD 重试请求, 这次使用 SIP URI.
如果收到 420 (Bad Extension) 响应 (Section 21.4.15), 则请求包含 Require 或 Proxy-Require header field, 其中列出了 proxy 或 UAS 不支持功能的 option-tag. UAC SHOULD 重试请求, 这次省略响应中 Unsupported header field 列出的任何扩展.
在以上所有情况下, 通过创建带有适当修改的新请求来重试请求. 此新请求构成新事务, 并 SHOULD 具有与前一请求相同的 Call-ID, To 和 From 值, 但 CSeq 应包含比前一值大一的新 sequence number.
对于其他 4xx 响应, 包括尚未定义的响应, 能否重试取决于方法和使用场景.
8.2 UAS 行为 (UAS Behavior)
当 UAS 处理 dialog 外的请求时, 会遵循一组与方法无关的处理规则. Section 12 给出 UAS 如何判断请求在 dialog 内还是 dialog 外的指导.
注意, 请求处理是原子的. 如果请求被接受, 与其关联的所有状态变更 MUST 执行. 如果请求被拒绝, 所有状态变更 MUST NOT 执行.
UAS SHOULD 按本节后续步骤的顺序处理请求 (即从认证开始, 然后检查 method, header field, 依此贯穿本节剩余部分).
8.2.1 Method 检查 (Method Inspection)
一旦请求通过认证 (或认证被跳过), UAS MUST 检查请求的 method. 如果 UAS 识别但不支持某请求的 method, 它 MUST 生成 405 (Method Not Allowed) 响应. 生成响应的过程在 Section 8.2.6 中描述. UAS MUST 还向 405 (Method Not Allowed) 响应添加 Allow header field. Allow header field MUST 列出生成该消息的 UAS 支持的方法集合. Allow header field 在 Section 20.5 中介绍.
如果 method 是 server 支持的方法之一, 则继续处理.
8.2.2 Header 检查 (Header Inspection)
如果 UAS 不理解请求中的某个 header field (即该 header field 未在本规范或任何受支持扩展中定义), server MUST 忽略该 header field 并继续处理消息. UAS SHOULD 忽略处理请求不需要的任何格式错误 header field.
8.2.2.1 To 和 Request-URI
To header field 标识由 From field 中所标识用户指定的请求原始接收者. 由于呼叫转发或其他 proxy 操作, 原始接收者可能是也可能不是处理该请求的 UAS. 当 To header field 不是 UAS 身份时, UAS MAY 应用任何它希望的策略来决定是否接受请求. 然而, RECOMMENDED 的是, 即使 UAS 不识别 To header field 中的 URI scheme (例如 tel: URI), 或 To header field 未寻址到该 UAS 的已知或当前用户, 也接受请求. 另一方面, 如果 UAS 决定拒绝请求, 它 SHOULD 生成状态码为 403 (Forbidden) 的响应并将其传递给 server transaction 进行传输.
然而, Request-URI 标识要处理该请求的 UAS. 如果 Request-URI 使用 UAS 不支持的 scheme, 它 SHOULD 以 416 (Unsupported URI Scheme) 响应拒绝请求. 如果 Request-URI 未标识 UAS 愿意为其接受请求的地址, 它 SHOULD 以 404 (Not Found) 响应拒绝请求. 通常, 使用 REGISTER 方法把其 address-of-record 绑定到特定 contact address 的 UA 会看到 Request-URI 等于该 contact address 的请求. 接收到的 Request-URI 的其他潜在来源包括 UA 发送的用于建立或刷新 dialog 的请求和响应中的 Contact header field.
8.2.2.2 合并请求 (Merged Requests)
如果请求在 To header field 中没有 tag, UAS core MUST 对照正在进行的事务检查该请求. 如果 From tag, Call-ID 和 CSeq 与某个正在进行事务关联的值完全匹配, 但请求不匹配该事务 (基于 Section 17.2.3 的匹配规则), UAS core SHOULD 生成 482 (Loop Detected) 响应并将其传递给 server transaction.
同一请求沿不同路径多次到达 UAS, 很可能是由于 forking. UAS 处理收到的第一个此类请求, 并用 482 (Loop Detected) 响应其余请求.
8.2.2.3 Require
假设 UAS 判定自己是处理该请求的适当元素, 它会检查 Require header field (如果存在).
Require header field 由 UAC 用于告知 UAS: 为了正确处理请求, UAC 期望 UAS 支持哪些 SIP 扩展. 其格式在 Section 20.32 中描述. 如果 UAS 不理解 Require header field 中列出的某个 option-tag, 它 MUST 生成状态码 420 (Bad Extension) 的响应. UAS MUST 添加 Unsupported header field, 并在其中列出请求的 Require header field 中那些它不理解的 option.
注意, Require 和 Proxy-Require MUST NOT 用在 SIP CANCEL 请求中, 也 MUST NOT 用在针对非 2xx 响应发送的 ACK 请求中. 如果这些 header field 出现在这些请求中, MUST 忽略它们.
针对 2xx 响应的 ACK 请求 MUST 只包含初始请求中存在的那些 Require 和 Proxy-Require 值.
示例:
UAC->UAS: INVITE sip:[email protected] SIP/2.0
Require: 100rel
UAS->UAC: SIP/2.0 420 Bad Extension
Unsupported: 100rel
该行为确保当双方都理解所有 option 时, client-server 交互不会延迟, 只有在 option 不被理解时才会变慢 (如上例). 对匹配良好的 client-server 对, 交互快速进行, 节省协商机制通常需要的一个往返. 此外, 当 client 需要 server 不理解的功能时, 它也消除了歧义. 某些功能, 例如 call handling field, 只对端系统有意义.
8.2.3 内容处理 (Content Processing)
假设 UAS 理解 client 要求的任何扩展, UAS 会检查消息 body 以及描述它的 header field. 如果存在任何 body, 其类型 (由 Content-Type 指示), 语言 (由 Content-Language 指示) 或编码 (由 Content-Encoding 指示) 不被理解, 且该 body part 不是可选的 (由 Content-Disposition header field 指示), 则 UAS MUST 以 415 (Unsupported Media Type) 响应拒绝请求. 如果请求包含 UAS 不支持类型的 body, 响应 MUST 包含 Accept header field, 列出它理解的所有 body 类型. 如果请求包含 UAS 不理解的 content encoding, 响应 MUST 包含 Accept-Encoding header field, 列出 UAS 理解的编码. 如果请求包含 UAS 不理解语言的内容, 响应 MUST 包含 Accept-Language header field, 指示 UAS 理解的语言. 除这些检查外, body 处理取决于方法和类型. 关于 content-specific header field 的处理, 见 Section 7.4 以及 Section 20.11 到 Section 20.15.
8.2.4 应用扩展 (Applying Extensions)
UAS 如果希望在生成响应时应用某个扩展, 除非请求的 Supported header field 中指示支持该扩展, 否则 MUST NOT 这样做. 如果期望的扩展不受支持, server SHOULD 只依赖 baseline SIP 和 client 支持的任何其他扩展. 在少见情况下, 如果 server 无法在没有该扩展的情况下处理请求, server MAY 发送 421 (Extension Required) 响应. 此响应指示如果不支持特定扩展, 就无法生成适当响应. 所需扩展 MUST 包含在响应的 Require header field 中. 此行为 NOT RECOMMENDED, 因为它通常会破坏互操作性.
应用于非 421 响应的任何扩展 MUST 列在该响应包含的 Require header field 中. 当然, server MUST NOT 应用请求的 Supported header field 中未列出的扩展. 因此, 响应中的 Require header field 只会包含 standards-track RFC 中定义的 option tag.
8.2.5 处理请求 (Processing the Request)
假设前面小节中的所有检查都通过, UAS 处理转为特定于方法. Section 10 覆盖 REGISTER 请求, Section 11 覆盖 OPTIONS 请求, Section 13 覆盖 INVITE 请求, Section 15 覆盖 BYE 请求.
8.2.6 生成响应 (Generating the Response)
当 UAS 希望为请求构造响应时, 它遵循以下小节详述的一般过程. 也可能需要与所讨论响应码相关但未在本节详述的其他行为.
与创建响应相关的所有过程完成后, UAS 将响应交还给它从中收到请求的 server transaction.
8.2.6.1 发送临时响应 (Sending a Provisional Response)
生成响应的一条大体与方法无关的指导是, UAS SHOULD NOT 为非 INVITE 请求发出 provisional response. 相反, UAS SHOULD 尽快为非 INVITE 请求生成 final response.
当生成 100 (Trying) 响应时, 请求中存在的任何 Timestamp header field MUST 复制到该 100 (Trying) 响应中. 如果生成响应有延迟, UAS SHOULD 在响应的 Timestamp value 中添加 delay value. 该值 MUST 包含发送响应的时间与接收请求的时间之间的差值, 以秒为单位测量.
8.2.6.2 Header 和 Tag
响应的 From field MUST 等于请求的 From header field. 响应的 Call-ID header field MUST 等于请求的 Call-ID header field. 响应的 CSeq header field MUST 等于请求的 CSeq field. 响应中的 Via header field value MUST 等于请求中的 Via header field value, 并且 MUST 保持相同顺序.
如果请求在请求中包含 To tag, 响应中的 To header field MUST 等于请求中的 To header field. 然而, 如果请求中的 To header field 不包含 tag, 响应中 To header field 的 URI MUST 等于 To header field 中的 URI; 此外, UAS MUST 向响应的 To header field 添加 tag (100 (Trying) 响应除外, 其中 MAY 存在 tag). 这用于标识正在响应的 UAS, 可能形成 dialog ID 的一个组成部分. 对该请求的所有响应, 无论 final 还是 provisional, MUST 使用相同 tag (同样不包括 100 (Trying)). tag 生成过程在 Section 19.3 中定义.
8.2.7 无状态 UAS 行为 (Stateless UAS Behavior)
stateless UAS 是不维护事务状态的 UAS. 它正常回复请求, 但在发送响应后丢弃通常会由 UAS 保留的任何状态. 如果 stateless UAS 收到请求重传, 它会重新生成响应并重新发送, 就像在回复该请求的第一个实例一样. 除非该方法的请求处理在请求相同时总会产生相同响应, 否则 UAS 不能是 stateless. 例如, 这排除了 stateless registrar. stateless UAS 不使用事务层; 它们直接从传输层接收请求, 并直接向传输层发送响应.
stateless UAS 角色主要用于处理未认证请求, 对这些请求会发出 challenge response. 如果以有状态方式处理未认证请求, 恶意的未认证请求洪泛可能会创建大量事务状态, 从而减慢或完全停止 UAS 中的呼叫处理, 实际上造成 denial of service 条件; 更多信息见 Section 26.1.5.
stateless UAS 最重要的行为如下:
o stateless UAS MUST NOT 发送 provisional (1xx) response.
o stateless UAS MUST NOT 重传响应.
o stateless UAS MUST 忽略 ACK 请求.
o stateless UAS MUST 忽略 CANCEL 请求.
o To header tag MUST 以无状态方式为响应生成 - 即以一种对同一请求始终生成相同 tag 的方式生成. 关于 tag 构造的信息, 见 Section 19.3.
在所有其他方面, stateless UAS 的行为与 stateful UAS 相同. UAS 可以对每个新请求以 stateful 或 stateless 模式运行.
8.3 Redirect Server
在某些体系结构中, 可能希望通过依赖重定向来减少负责路由请求的 proxy server 的处理负载, 并提高 signaling path 的健壮性.
重定向允许 server 在响应中把请求的路由信息推回给 client, 从而在仍协助定位请求目标的同时, 将自身从该事务后续消息的 loop 中移除. 当请求发起者收到重定向时, 它会基于收到的 URI 发送新请求. 通过把 URI 从网络核心传播到网络边缘, 重定向可提供相当大的网络可伸缩性.
redirect server 在逻辑上由 server transaction layer 和一个可访问某种 location service 的 transaction user 构成 (关于 registrar 和 location service 的更多信息见 Section 10). 此 location service 实际上是一个数据库, 包含单个 URI 与一个或多个可找到该 URI 目标的替代位置之间的映射.
redirect server 不发出自己的任何 SIP 请求. 在收到 CANCEL 以外的请求后, server 要么拒绝该请求, 要么从 location service 收集替代位置列表并返回 3xx 类 final response. 对于格式良好的 CANCEL 请求, 它 SHOULD 返回 2xx 响应. 此响应结束 SIP 事务. redirect server 在整个 SIP 事务期间维护事务状态. client 负责检测 redirect server 之间的 forwarding loop.
当 redirect server 为请求返回 3xx 响应时, 它把一个或多个替代位置的列表填入 Contact header field. 也可以为 Contact header field value 提供 "expires" 参数, 指示 Contact 数据的生命周期.
Contact header field 包含给出要尝试的新位置或用户名的 URI, 或者可以只指定附加传输参数. 301 (Moved Permanently) 或 302 (Moved Temporarily) 响应也可以给出初始请求所指向的相同位置和用户名, 但指定附加传输参数, 例如要尝试的不同 server 或 multicast address, 或 SIP transport 从 UDP 改为 TCP 或反之.
然而, redirect server MUST NOT 将请求重定向到等于 Request-URI 中 URI 的 URI; 相反, 只要该 URI 不指向自身, server MAY 把请求 proxy 到目的 URI, 或 MAY 以 404 拒绝它.
如果 client 正在使用 outbound proxy, 且该 proxy 实际上会重定向请求, 则可能产生无限重定向 loop.
注意, Contact header field value MAY 也引用与最初被呼叫资源不同的资源. 例如, 连接到 PSTN gateway 的 SIP call 可能需要递送特殊信息公告, 例如 "The number you have dialed has been changed."
Contact response header field 可以包含任何合适 URI, 指示可在何处到达被叫方, 不限于 SIP URI. 例如, 它可以包含 phone, fax 或 irc 的 URI (如果它们被定义), 或 mailto: (RFC 2368 [32]) URL. Section 26.4.4 讨论将 SIPS URI 重定向到非 SIPS URI 的影响和限制.
Contact header field value 的 "expires" 参数指示 URI 有效多久. 参数值是表示秒数的数字. 如果未提供此参数, Expires header field 的值决定 URI 有效多久. 格式错误的值 SHOULD 被视为等价于 3600.
这提供了对 RFC 2543 的适度向后兼容, 该 RFC 允许此 header field 中使用绝对时间. 如果收到绝对时间, 它将被视为格式错误, 然后默认为 3600.
redirect server MUST 忽略不理解的功能 (包括无法识别的 header field, Require 中任何未知 option tag, 甚至 method name), 并继续重定向相关请求.