本文章为RFC3261文档的中文翻译。由于在工作中使用SIP协议,但是对协议的一些细节了解不够深入,因此在阅读RFC文档的过程中,将文档翻译成中文,希望可以帮助其他想要学习了解SIP的同学。由于英文水平有限,若有翻译不准确的地方,欢迎指正。
8 普通用户代理的行为描述
一个用户代理(UA)代表一个终端系统。其中包含一个用于产生请求的用 户代理客户端(UAC)和一个响应请求的用户代理服务器(UAS)。UAC能够根据一些外部信号产生一个 请求并处理其响应。UAS能够接受请求并根据用户的输入、外部信号、处理结果或者其他机制来响应 请求。UAC发出的请求可以通过一些代理服务器(proxy server)转发,然后 后送达UAS。UAS处理后产生响应回复给UAC。UAC和UAC的处理流程依赖于两个因素。第一,请求或响应是会话内消息还是会话外消息;第二,请求的类型。关于会话的讨论在第12章;会话反映出两个用户代理(UA)之间的根据请求消息建立的关系,比如INVITE消息。本章讨论UAC和UAS在处理会话外的请求消息时,遵循的的一些与消息类型无关的通用准则。其中也包括了能够建立会话的请求消息。处理会话外的请求和响应的安全机制在26章描述,特别是UAS和UAC之间的相互认证机制。通过使用S/MIME携带加密体,可以在一定程度支持隐私保护特性。
8.1 UAC行为描述
本节描述会话外的UAC行为。
8.1.1 产生请求消息
一个合法的SIP请求最少必须包含以下几个头域:To、From、CSeq、Call-ID、Max-Forwards、Via;所有的SIP请求都必须包含以上几个 头域。这六个头域是SIP消息的基本元素,他们共同提供了大部分鉴定消息的路由服务,包括消息的地址,响应消息的路由信息,消息的路由次数限制,消息的顺序,会话的唯一标识符。除了这些头域之外,还必须包括request line,其中携带了方法类型、Request-URI、SIP的版本说明。
发送会话外请求消息的例子有通过发送INVITE消息来建立一路会话(详见13章),发送一个OPTIONS来查询服务器性能(详见11章)。
8.1.1.1 Request-URI
消息的初始Request-URI应该与To头域的URI相同。REGISTER消息是一个例外,具体的讨论在第10章。也有可能因为隐私还或者便利的原因不是用与To头域相同的URI(尤其是如果起始的UA预期Request-URI在传递过程中将被改变)。
在一些特定的场景下,一个预设的路由信息集合会影响消息的Request-URI。预设的路由信息集合是一组安排好的URI,通过他们来识别一连串的服务器,最终将UAC发出的会话外请求消息发送到这些服务器。通常通过用户或者服务提供者或者其他的非SIP机制手动将预设的路由信息集合配置到UA。当服务器提供者希望为UA配置一个外出代理时,建议通过提供一个只包含外出代理的URI的预设路由集合来实现。
当一个预设路由集合已存在时,必须遵循在12.2.1.1节描述的填充Request-URI和Route头域的规则,使用需要的Request-URI作为远端的目的URI
8.1.1.2 To
TO头域首先要指定请求希望被发送到的逻辑上的接收者,或者作为接收请求的用户或者资源的记录地址(address-of-record)。这可能并不是请求消息的最终接受者。To头域可能包含一个SIP或者SIPS URI,但是在合适的时候它也可能使用 其他类型的URI组合(例如RFC2806描述的tel URI)。任何支持TLS的实现都必须支持SIPS URI组合。To头域允许携带一个用于显示的用户名字。
UAC在构造一个特定请求的To头域时,可能会了解到有多种方式。通常用户通过人类友好的界面显示To头域,这些头域也许手动输入URI或者从地址簿中选择。通常用户不输入完整的URI,而是输入一串数字或者字母(例如“Bob”)。UA可以选择任意方式来翻译这些输入。使用字符串来组成URI的用户部分意味着UA希望被解析的域名在@符号的右边(例如:sip:bob@example.com)。使用字符串来组成URIS的用户部分意味着UA希望能够安全的通信,被解析的域名放在@符号右边。@符号右侧通常有请求者的域名组成,这样就允许归属域能够处理外发的请求。这对如快速拨号这类需要在归属域中解释URI用户部分的特性很有帮助。当UA不希望指定域解析用户输入的电话号码时,应该使用tel URI。当然,请求通过的每个域都可以对其进行解析。举个例子,一个用户在机场登录并且通过机场的外出代理服务器发送了一个请求。如果输入“411”(美国的电话号码查询服务中心号码),此时就需要被外发代理服务器解释然后处理,而不是用户的归属域。这种情况下,正确的选择是使用tel URI(tel:411)。
会话外请求不能包含有To标签;To头域中的标签用于标记同一路会话。但是会话外请求存在时还没有建立的会话,因此标签也不应存在。
更多关于To头域的信息,在20.39节。以下为一个正确格式的To头域:
To: Carol <sip:carol@chicago.com>
8.1.1.3 From
From头域表明请求的创建者的逻辑身份,可能是用户的记录地址(address-of-record)。与To头域一样,它包含一个URI和一个可选的显示名称(display name)。From头域用于决定使用何种方式处理请求(例如,自动的呼叫拒绝)。同样的,From URI不包含运行UA的主机的IP地址或者正式域名(FQND),因为这些不是逻辑名称。
如果客户需要隐藏身份,UAC应该使用"Anonymous"作为显示名称,同时使用格式正确却无意义的URI(例如:sip:thisis@anonymous.invalid)。
通常,不同UA产生的请求中的构成From头域的值是用户或者本地域的管理员预先设置好的。如果某个UA被多个用户使用,他可能切换配置文件,其中包含对于标识不同用户的URI。请求的接收者能够鉴权发起人以便确定他们的确与From头域中声明的身份一致。(更多关于鉴权的信息在22章)
From头域必须包含一个UAC选择的新标签(tag)参数。关于选择标签的细节在19.3节描述。
更多关于From头域的信息在20.20节。例:
From: "Bob" <sips:bob@biloxi.com> ;tag=a48s
From: sip:+12125551212@phone2net.com;tag=887s
From: Anonymous <sip:c8oqz84zk7z@privacy.org>;tag=hyh8
8.1.1.4 Call-ID
Call-ID头域是一个唯一标识符,用于将一系列消息标记在一个组合中。在同一个会话中,两个UA间的所有的请求和响应的Call-ID头域都必须保持一致。UA发出的每个注册信息的Call-ID都应该保持一致。
当UAC产生一个新的会话外请求时,UAC必须产生一个全局唯一的标志符作为Call-ID头域,该标识符不受空间、时间、影响,除非是被特定方法的行为影响。所有的SIP UA必须有保证他们产生的Call-ID头域不会意外的与其他UA产生的Call-Id相同。当某一个失败响应请求修改请求消息而导致请求消息重发时(例如,鉴权的挑战),重发的请求消息不能看作是新的请求,不需要产生新的Call-ID;详见8.1.3.5节。
建议产生Call-ID时使用加密的随机标识符(RFC 1750[12])。实现可以使用"localid@host"这种格式。Call-ID是大小写敏感的,并且使用简单的按自己对比。
使用加密的随机标识符能够防止会话劫持,减少无意义的Call-ID碰撞。
不提供为请求消息选择Call-ID头域值的备用或者用户接口。
关于Call-ID头域的更多信息,查看20.8节
例:
Call-ID: f81d4fae-7dec-11d0-a765-00a0c91e6bf6@foo.bar.com
8.1.1.5 CSeq
CSeq头域用于识别和整理事务。她有一个序列号和一个方法名称组成。方法名称必须与请求类型一直。除REGISTER请求外,其他会话外请求的序列号可以是任意值。这个序列号必须是一个32-bit的无符号整型且小于2^32。只要符合以上规则,客户端可以使用任何机制来选择CSeq头域的值。
12.2.1.1节讨关于论会话中请求的CSeq。
例:
CSeq: 4711 INVITE
8.1.1.6 Max-Forwards
Max-Forwards头域用于决定请求消息在传输过程中跳跃的次数限制。它由一个整数组成,每一跳过后,数值减一。如果在请求到达目的地钱值减到0,它将被拒绝,并回复483错误。
UAC必须在创建请求消息的时候,添加一个Max-Forward头域,值可以为70。选择一个足够大的值,以保证请求消息正常的无循环SIP网络中发送时不会被抛弃掉,但是也不能太大,导致当网络中出现循环时,转发请求消息消耗代理服务器的资源。较小的值应该谨慎使用且网络拓扑为已知。