您的位置:首页 > 编程语言 > C语言/C++

SIP协议解析与实现(c和c++ 使用osip) 6

2007-12-10 15:40 597 查看
发送请求
这时候确定请求要发送的目标。除非本地策略指定,除非发送目标必须按照下面提到的DNS来确定。如果路由集中的第一个元素是一个严格的路由,那么路由过程必须被设置在请求的Request-URI头域中。否则路由过程被设置在请求中第一个Route头域的值(如果有Route头域存在)中,或者如果Route头域不存在路由过程被设置在Request-URI头域中。这些路由过程生成的一序列地址、端口和传输协议,传输时将尝试向这序列中的地址和端口传输。无论哪一种URI作为路由过程的输入,如果Request-URI指定了一个SIPS资源,那么UAC必须将后继的路由过程都当作SIPS URI来处理。

本地策略可能试图指定一个请求目标的其它地址。如果Request-URI包含一个SIPS URI,那么任何的请求目标的其它地址必须使用TLS。此外,对于不包含Route头域的请求没有其它限制。这里提供了一种简单的可选择的方法来预先设置路由表,就像指定了外部代理。尽管如此,这样配置一个外部路由是不被推荐的。应该由一个URI指定一个预存在的路由集。如果请求包含一个Route头域,它应该被发送到Route头域最顶部的值所表示的位置,但它可能发送到任何本文档规定的路由和Request-URI指定的服务器,且该服务器是被UA确认的。特别的,如果UAC被配置使用一个外部代理,那么请求应该被尝试发送到Route头域中第一个值所指示的位置,而不是用来发送所有消息的外部代理的策略。这使得外部代理不向请求中增加Record-Route头域,从而使后继请求不包含这个外部代理路径。同时它也允许不能处理第一个Route URI的终端将这个任务委托给一个外部代理。

UAC应该按照[4]中提到的处理过程实现有状态的元素,尝试每一个地址直到连接到服务器。每一个连接尝试都启动一个新的事物,因此每次连接尝试的Via头域顶部的值都不同,并且还有一个新的branch参数。此外,Via头域中transport的值设置成请求目标服务器的值。

处理应答
应答首先被传输层处理,然后被向上传送到事物层。事物层做完处理后把应答传送给TU。TU处理大多数的应答是与方法相关的。尽管如此,TU还是有一些公共的方法。

事物层错误
有时事物层返回的应答不是一个SIP消息,而是一个事物层错误。当从事物层接收到一个超时错误,必须将这个错误视为状态码是408(请求超时)的应答。如果传输层报告了一个致命的传输错误(在UDP中这通常是致命的IMCP错误或者在TCP中是连接失败),必须视为状态码为503(服务无法获得)的应答。

未知的应答
一个UAC必须将所有未知的最终应答视为那一类应答中状态码是x00的应答。并且它必须能够处理所有类中的x00应答。例如如果一个UAC接收到一个应答码是431的未知应答,它能够知道所发送的请求出现了问题并且将这个应答视为应答码为400(错误请求)的最终应答来处理。UAC必须将非100的临时应答视为183(会话处理中)进行处理。并且UAC必须能够处理100应答和183应答。

多个Via
如果多于一个Via头域出现在应答中,UAC应该丢弃这个消息。多余的Vias头域出现说明消息被错误的路由或者消息已经被破坏。

处理3xx应答
收到一个重定向应答(如状态码是301的应答),用户应该基于重定向后的请求,使用应答Contact头域中的一个或多个URI重新生成新的一个或者多个新的请求。这个处理过程与RFC3261第16.5和16.6节中代理处理3xx类请求的处理方式很类似。一个用户开始请求时只有一个目标地址集的URI,就是原始请求的Request-URI。如果用户希望基于3xx应答构造一个新的请求,他应该把可能的URI放置到目标集当中。在遵循本说明中限制的前提下,客户可以选择将哪一个可联系到目标的URI放置到目标集当中。就像代理服务器会递归,用户处理3xx类的应答必须不增加任何已经出现的URI。如果原始请求的Request-URI中是SIPS URI,用户可以选择一个非SIPS URI,但是应该通知用户请求要被发送到一个不安全的URI。任何请求都可能接收到3xx应答,应答本身的Contact头域包含原始的URI。两个地址可能被设置成互相重定向,任何URI在目标集中只出现一次是为了放置无限的重定向循环。

目标集中条目的增长,用户可能按照任何顺序创建向这些目标地址的新请求。一个一般的方法是使用Contact头域中q参数的值来决定目标地址的次序。向这些URI请求的消息可能是串行或者并行产生的。一种实现方法是按照q值进行降序分组,对每一组进行串行处理,对每组中的URI进行并行处理。另外一种方法是按照q值降序排列,q值相等的URI顺序任意,然后顺序处理这个序列。

如果与目标集上的某个地址通信失败了,继续尝试目标地址集中下一个地址,直到全部尝试完成。如果全部尝试完成那么请求失败。请求失败应该通过失败应答码来检测(应答码大于399)。对于网络错误,客户事物将传输层失败报告给事物用户。注意,一些应答码(RFC3261第8.1.3.5节详细说明)指出请求可以被重试。重试的请求不被认为是失败请求。

如果向Contact中某个地址发送失败,用户应该尝试下一个Contact地址,这将为传输这个新的请求创建一个新的事务。

为了基于一个3xx应答的Contact头域创建请求,UAC必须从目标集中拷贝除了"method-param"和"header"参数(RFC3261第19.1.1节)外的完整的URI。"header"的值用于按照RFC3261第19.1.5节中的方法创建和重写新请求中某些头域的值。

注意,有些时候,被用来通讯的Contact头域附加到被重定向的原始请求头域后。作为一般规则,如果头域能够接受逗号分隔的多个值,那么新的值将被附加到重定向的原始请求头域后面。如果头域不能接受多个值,那么重定向的原始请求头域将被覆盖。例如,返回的contact头域是下面的值:
sip:user@host?Subject=foo&Call-Info=<http://www.foo.com>
任何重定向的原始请求中的主要头域都将被重写。HTTP URL仅仅附加到存在的Call-Info头域的值后面。

推荐UAC使用原始请求的To, From, and Call-ID头域。但是UAC可能为新请求选择更新Call-ID头域的值。

最后,一旦新请求被创建,它将被一个新的客户事务所发送。因此,它必须在Via头域顶部有一个新的branch ID(RFC3261第8.1.1.7节讨论)。

在其它方面,基于接收到一个重定向应答的请求应该重用原始请求的头域和消息体。

有时候,Contact头域的值可能被UAC临时或者永久的缓存起来,这依赖于应答的状态码和超时参数。参看RFC3261第21.3.2节和21.3.3节。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: