8.1.2 发送一个请求
于是,我们就开始查找请求发送的目标。除非有其他的特定说明,目标必须是通过DNS来查找的(参见[4]说明)。如果路由表(route set)中的第一个元素表明这是一个严格路由(strict router,在
本地策略可以指定一套额外的目的地用于发送。如果Request-URI包含一个SIPS URI,任何额外的目的地都必须用TLS来表达。除此之外,如果请求没有包含Route头域,那么就没有对额外的目的地有什么其他的限制了。这个就提供了一个简单的外发(outbound)proxy的事前路由的选择。但是,用这样的方法配置一个外发proxy是不推荐的;应该由单个UPI规定的预先设定的路由集来指定外发proxy。如果请求包含了Route头域,请求应该发送到Route头域最上边的一个位置,但是请求也可能被发给由本文档约定的Route或者Request-URI所指定的服务器(同RFC2543定义的相反)。特别的,一个配置了外发proxy的UAC应该首先尝试把请求发送给由第一个Route头域值指定的位置,而不是采用把所有消息都发给外发proxy的策略。这就保证了外发的proxy通过不增加Record-Route头域而不参与后续请求的路径。这个也允许让不能分析第一个Route URI的终端,把请求交给外发proxy来发送。UAC应该遵循[4]中定义的过程来实现有状态的元素,尝试每一个地址直到连接到一个服务器。每一个尝试都是一个事务,因此,每一个都有一个不同的Via头域值和一个新的branch参数值。
此外,在Via头域中的transport的值被设置成为要到目标服务器所必须的transport。
8.1.3 处理应答
应答首先是被transport层处理,并且被transport层发送给上一层transaction层处理。transaction层处理完成之后将应答发送给更上一层TU处理。在TU层进行的对应答的主要处理是方法相关的。但是也有集中通用的处理原则:
8.1.3 .1: transaction 层的错误
在某些情况下,从transaction层返回的应答不一定是一个SIP消息,而是一个transaction层的错误。当从transaction层收到一个timeout错误的时候,必须将这个timeout错误当作是收到了一个状态码是408(请求timeout)的应答。如果transport层报告了一个严重错误(通常取决于UDP传输中的严重的ICMP错误,或者是TCP连接中的错误),必须把这个错误当作是状态码503(服务未提供)的错误。
8.1.3 .2 未知的应答
UAC必须把自己不认识的所有最终应答当作是x00的那类应答,当然UAC也必须能够处理所有的类别应答的x00的应答。比如,如果UAC收到了不认识的应答代码431,他可以很安全的假设在他发出的请求中有什么地方弄错了,并且可以很简单的把这个应答错误当作是接收到了一个应答代码是400(非法请求)的错误应答。并且,UAC必须能够处理所有的不认识的非终结应答响应当作是183(session progress)。一个UAC必须能够处理100和183应答。
8.1.3 .3 Vias
如果在应答中,有不只一个Via头域值存在,那么UAC应该丢弃这个消息。包含超过一个Via头域值的消息是因为被错误的路由或者消息被破坏。
8.1.3 .4 处理3xx应答
由于接收到一个重定向的应答(比如,状态码是301的应答),客户端应该用在Contact头域中的URI(s)来组织一个或者多个基于重定向以后的新请求,这个处理过程同proxy处理一个3xx类别的应答很类似,相关资料在16.5节和16.6节中有描述。客户发起请求的时候只有一个目标URI,就是原始请求中的Request-URI。如果客户端想在这个请求基础上重构一个基于3xx类别应答的新请求,那么就需要把这个需要尝试的URIs放到目标集合中去。基于本规范的规定,一个客户端可以选择放置那个Contact URIs到目标集合中(target set)。同proxy会递归一样,客户端处理3xx应答的时候必须不能重复添加任何URI到target set。如果原始请求的Request-URI头域中包含了一个SIPS URI,那么客户端可以选择改乘一个非SIPS URI,但是需要知会客户转发到一个非安全的URI去。任何新的请求都可能导致接收到这些请求的3xx应答,并且在Contact中包含原始的URI。可以通过对两个位置的配置来形成互相重定向。只要保证在target set中任何URI都只出现1次就能避免无穷的重定向循环。当target set增长了,客户端可以对这个URIs,用任意顺序来产生新的请求。常见机制是通过在Contact头域的值中设置”q”参数来指定这个顺序。对这些URIs的请求可以是并行产生的也可以是串行产生的。有一个实现是按照q参数值递减的方法顺序处理URIs,并且对相同q参数值的URIs进行并行处理。还有一种就是直接按照顺序的方法处理URIs,对于q参数值不同的按照递减的顺序处理,对于q参数值相同的按照随机顺序处理。
如果发送给连接表上的地址失败了,(在下一段我们有定义),那么就选择列表中的下一个地址进行发送,直到列表全部遍历一遍。如果列表遍历完了还没有,那么请求就失败了。
通过响应码(大于399)我们可以知道请求的失败;对于网络错误来说,客户transaction会给transaciton user报告transport层的通讯错误错误。注意有一部分响应码(
为了在处理3xx应答中创建一个基于一个contact地址的请求,UAC必须首先从target set中拷贝除了”method-param”和”header”URI参数之外的整个URI到Request-URI(见参数的定义见
注意在某些情况下,在contact地址中进行通讯所需要的头域,可能代替添加到现有的在原始转发的请求的请求头域中。作为通用的规则,如果头域可以接受用逗号分割的值列表,那么新的头域值可以添加到原始转发的请求的任何值后边。如果请求头域不接收多值列表,那么原始转发请求中的头域值可以由contact地址中进行通讯所需要的头域的值所替换。比如,如果contract地址返回了如下的值:
sip:user@host?Subject=foo&Call-Info=Http://www.foo.com
那么在原始转发请求中的任何Subject头域都被重写,但是HTTP URL仅仅添加到现存的Call-info 头域值中。
我们推荐UAC重用与原始转发请求相同的To,From,和Call-ID域值,但是也允许UAC为新的请求改变Call-ID头域。
最后,当一个新的请求构造好以后,这个请求将通过一个新的客户transaction发送,应此在最开始的Via头域中必须有一个新的branch ID (
在其他的方面,转发的请求应该重用原始请求的头域和消息体。
在某些情况下,Contact头域的值可能在UAC中暂时或者永久保存,这个依赖于接收到的请求码和过期的时间;参见
8.1.3 .5 处理4xx应答
某个4xx应答码要求特定的UA处理,和请求的方法无关。
当接收到401(未授权)或者407(Proxy认证需要)应答的时候,UAC应该遵循在22.2和22.3中规定的认证步骤,重新发送带认证信息的请求。
当收到413(请求过大)应答的时候(
如果收到了一个415(不支持的媒体类型)应答(
如果收到了一个416(不支持的URI Scheme)应答(
如果收到了一个420(非法扩展)应答(
在上述所有的情况中,所有需要重试的请求,都需要经过适当修正成为一个新的请求。这个新请求采用一个新的transaction并且应该有和上次请求相同的Call-ID,TO,From头域,Cseq应该有一个新的顺序号码(比原有顺序号码更大)。
其他的4xx应答,包括尚未制定的,是否允许请求重试,依赖于具体的方法和应用。
评论