正文

SIP的RFC中文文档(RFC3261)(7)2005-12-15 14:48:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/ddtme/8258.html

分享到:

8.1.2 发送一个请求

于是,我们就开始查找请求发送的目标。除非有其他的特定说明,目标必须是通过DNS来查找的(参见[4]说明)。如果路由表(route set)中的第一个元素表明这是一个严格路由(strict router,12.2.1.1节中讲述),那么这些过程必须在请求的Request-URI中说明。否则,这些过程在请求中被应用于第一个Route头域中(如果存在),或者在请求的Request-URI中(如果Route头域不存在)。这样一些过程产生了一系列的地址,端口,和用于传输的传输器。无论那个URI用在这个[4]中描述的过程的输入,如果Request-URI指明了SIPS,那么UAC必须按照[4]中描述的说明来认为输入的URISIPSURI

本地策略可以指定一套额外的目的地用于发送。如果Request-URI包含一个SIPS URI,任何额外的目的地都必须TLS来表达。除此之外,如果请求没有包含Route头域,那么就没有对额外的目的地有什么其他的限制了。这个就提供了一个简单的外发(outboundproxy的事前路由的选择。但是,用这样的方法配置一个外发proxy不推荐的;应该由单个UPI规定的预先设定的路由集来指定外发proxy。如果请求包含了Route头域,请求应该发送到Route头域最上边的一个位置,但是请求也可能被发给由本文档约定的Route或者Request-URI所指定的服务器(RFC2543定义的相反)。特别的,一个配置了外发proxyUAC应该首先尝试把请求发送给由第一个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必须能够处理100183应答。

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应答的时候必须不能重复添加任何URItarget 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层的通讯错误错误。注意有一部分响应码(8.1.3.5)表示请求可以被重试;这个时候,请求可以重发而不是简单的当作一个错误。如果某个contact地址发送失败,那么client应该尝试下一个contact地址。这个会导致创建一个新的客户事务来处理这个新的请求。

为了在处理3xx应答中创建一个基于一个contact地址的请求,UAC必须首先从target set中拷贝除了”method-param””header”URI参数之外的整个URIRequest-URI(见参数的定义见19.1.1)。通过使用”header”参数来创建新请求的头域值,按照19.1.5节的指引,根据重定向的请求来重写头域的值。

注意在某些情况下,在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 8.1.1.7节说明)

在其他的方面,转发的请求应该重用原始请求的头域和消息体。

在某些情况下,Contact头域的值可能在UAC中暂时或者永久保存,这个依赖于接收到的请求码和过期的时间;参见21.3.221.3.3节。

8.1.3.5 处理4xx应答

某个4xx应答码要求特定的UA处理,和请求的方法无关。

当接收到401(未授权)或者407Proxy认证需要)应答的时候,UAC应该遵循在22.222.3中规定的认证步骤,重新发送带认证信息的请求。

当收到413(请求过大)应答的时候(21.4.11节),这说明请求包含了一个UAS所不能接收长度的消息体。如果可能,UAC应该尝试重新retry这个请求,或者去掉包体或者换一个小一点的长度。

如果收到了一个415(不支持的媒体类型)应答(21.4.13节),那么请求中包含的媒体类别是UAS所不支持的。UAC应该重发这个请求,并且这次发出的请求只包含应答中的Accept头域所指明的媒体类别,并且采用Accept-Encoding头域中指明的encoding方法,还有Accept-Language指明的语言。

如果收到了一个416(不支持的URI Scheme)应答(21.4.14节),Request-URI使用的URI Scheme(方案)是服务端所不支持的。客户端应该重新尝试这个请求,并且换用SIP URI

如果收到了一个420(非法扩展)应答(21.4.15节),请求的Require或者Proxy-Require头域包含的option-tag中包含了UAS或者proxy不支持的特性。UAC应该尝试去掉应答中的Unsupported头域中列出的扩展以后然后再尝试。

在上述所有的情况中,所有需要重试的请求,都需要经过适当修正成为一个新的请求。这个新请求采用一个新的transaction并且应该有和上次请求相同的Call-ID,TO,From头域,Cseq应该有一个新的顺序号码(比原有顺序号码更大)。

其他的4xx应答,包括尚未制定的,是否允许请求重试,依赖于具体的方法和应用。

阅读(5671) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册