18. 传输
18 传输
传输层负责通过网络传输的请求和响应的实际传输.这包括在面向连接的传输情况下,确定用于请求或响应的连接.
传输层负责管理传输协议(如TCP和SCTP)或这些协议上的TLS(包括对传输层开放的协议)的持久连接.这包括由客户端或服务器传输打开的连接,以便在客户端和服务器传输功能之间共享连接.这些连接由连接远端的地址,端口和传输协议形成的元组索引.当传输层打开连接时,此索引设置为目标IP,端口和传输.当传输层接受连接时,此索引将设置为源IP地址,端口号和传输.请注意,由于源端口通常是临时的,但无法知道它是临时的还是通过[4]中的过程选择的,因此传输层接受的连接通常不会被重用.结果是,使用面向连接的传输的"对等"关系中的两个代理经常会使用两个连接,一个用于在每个方向启动的事务.
建议在通过该连接发送或接收最后一条消息后,将连接保持打开状态一段实现定义的持续时间.该持续时间应至少等于元素将事务从实例化状态转换为终止状态所需的最长时间.这是为了使事务有可能在启动它们的同一连接上完成(例如,请求,响应,在INVITE的情况下,非2xx响应的ACK).这通常意味着至少64*T1(T1的定义见第17.1.1.1节).然而,例如,在具有TU的元素中,它可以更大,使用定时器C的大值(第16.6节中的项目符号11).
所有SIP元素都必须实现UDP和TCP.SIP元素可以实现其他协议.
将TCP强制用于UA是对RFC 2543的重大更改.它产生于处理较大消息的需要,这些消息必须使用TCP,如下所述.因此,即使一个元素从不发送大消息,它也可能会收到一条消息,并且需要能够处理它们.
18.1 客户
18.1.1 发送请求
传输层的客户端负责发送请求和接收响应.传输层的用户将请求,IP地址,端口,传输以及可能的多播目的地TTL传递给客户端传输层.
如果请求位于路径MTU的200字节以内,或者如果请求大于1300字节且路径MTU未知,则必须使用RFC 2914[43]拥塞控制传输协议(如TCP)发送请求.如果这导致传输协议从顶部通孔中指示的协议发生更改,则必须更改顶部通孔中的值.这可以防止UDP上的消息碎片,并为较大的消息提供拥塞控制.但是,实现必须能够处理最大数据报数据包大小的消息.对于UDP,此大小为65535字节,包括IP和UDP标头.
消息大小和MTU之间的200字节"缓冲区"适应了SIP中的响应可能大于请求的事实.例如,这是由于在INVITE响应中添加了Record-Route头字段值所致.有了额外的缓冲区,响应可以比请求大大约170字节,并且在IPv4上仍然不会被分段(大约30字节)
由IP/UDP使用,假设没有IPSec).基于1500字节以太网MTU的假设,当路径MTU未知时,选择1300.
如果由于这些消息大小限制,某个元素通过TCP发送请求,而该请求本来是通过UDP发送的,如果尝试建立连接时生成不支持的ICMP协议,或者导致TCP重置,则该元素应使用UDP重试该请求.这只是为了提供与不支持TCP的RFC 2543兼容实现的向后兼容性.预计该行为将在本规范的未来版本中被弃用.
向多播地址发送请求的客户端必须将"maddr"参数添加到其包含目标多播地址的Via 头字段值中,对于IPv4,应添加值为1的"ttl"参数.本规范中未定义IPv6多播的使用,并将在需要时作为未来标准化的主题.
这些规则有目的地限制了SIP中的多播.它的主要功能是提供"类似单跳发现"的服务,将请求传递给一组同构服务器,在这些服务器中,只需要处理其中任何一个服务器的响应.此功能对于REGISTER非常有用.事实上,根据第17.1.3节中的交易处理规则,客户端交易将接受第一个响应,并将任何其他响应视为重传,因为它们都包含相同的Via 分支标识符.
在发送请求之前,客户端传输必须在Via 头字段中插入"sent-by"字段的值.此字段包含IP地址或主机名以及端口.建议使用FQDN.此字段用于在某些条件下发送响应,如下所述.如果缺少端口,则默认值取决于传输.UDP,TCP和SCTP为5060,TLS为5061.
对于可靠的传输,响应通常在接收请求的连接上发送.因此,客户端传输必须准备好在用于发送请求的同一连接上接收响应.在错误情况下,服务器可能会尝试打开新连接以发送响应.为了处理这种情况,传输层还必须准备好在发送请求的源IP地址和"sent-by"字段中的端口号上接收传入连接.它也
必须准备好接收服务器根据[4]第5节所述程序选择的任何地址和端口上的传入连接.
对于不可靠的单播传输,客户端传输必须准备好接收来自发送请求的源IP地址的响应(因为响应被发送回源地址)和"sent-by"字段中的端口号.此外,与可靠传输一样,在某些情况下,响应将发送到其他地方.客户机必须准备好接收服务器根据[4]第5节所述程序选择的任何地址和端口的响应.
对于多播,客户端传输必须准备好在请求发送到的同一多播组和端口上接收响应(也就是说,它需要是发送请求的多播组的成员)
如果请求的目的地是现有连接已打开的IP地址,端口和传输,建议使用此连接发送请求,但也可以打开并使用另一个连接.
如果使用多播发送请求,则会将其发送到传输用户提供的组地址,端口和TTL.如果使用单播不可靠传输发送请求,则会将其发送到传输用户提供的IP地址和端口.
18.1.2 收到答复
当接收到响应时,客户端传输将检查最上方 Via 头字段值.如果该头字段值中"sent-by"参数的值与客户端传输配置为插入到请求中的值不对应,则必须以静默方式放弃响应.
如果存在任何客户交易,客户传输将使用第17.1.3节中的匹配程序,尝试将响应与现有交易匹配.如果存在匹配项,则必须将响应传递给该事务.否则,必须将响应传递给核心(无论是无状态代理,有状态代理还是UA)进行进一步处理.这些"杂散"响应的处理取决于核心(例如,代理将转发它们,而UA将丢弃它们).
18.2 服务器
18.2.1 接收请求
服务器应准备好接收任何IP地址,端口和传输组合上的请求,这些请求可能是为了与该服务器通信而分发的SIP或SIPS URI[4]上DNS查找的结果.在此上下文中,"分发"包括将URI放置在REGISTER request或重定向响应中的Contact 头字段中,或放置在请求或响应中的Record-Route头字段中.URI也可以通过放在网页或名片上"分发".还建议服务器在所有公共接口的默认SIP端口(5060用于TCP和UDP,5061用于TCP上的TLS)上侦听请求.典型的例外情况是专用网络,或者当多个服务器实例在同一主机上运行时.对于服务器侦听UDP的任何端口和接口,它必须侦听TCP的同一端口和接口.这是因为如果消息太大,可能需要使用TCP而不是UDP发送消息.因此,情况并非如此.服务器不需要侦听特定地址和端口上的UDP,因为它正在侦听同一地址和端口上的TCP.当然,服务器需要侦听特定地址和端口上的UDP可能还有其他原因.
当服务器传输通过任何传输接收到请求时,它必须检查最上方 Via 头字段值中"sent-by"参数的值.如果"sent-by"参数的主机部分包含域名,或者如果它包含与数据包源地址不同的IP地址,则服务器必须向该 Via 头字段值添加"received"参数.此参数必须包含从中接收数据包的源地址.这是为了帮助服务器传输层发送响应,因为它必须发送到请求来自的源IP地址.
考虑服务器传输所接收的请求,该请求看起来像:
INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP bobspc.biloxi.com:5060
接收请求时,源IP地址为192.0.2.4.在向上传递请求之前,传输会添加一个"received"参数,以便请求的部分外观如下:
INVITE sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP bobspc.biloxi.com:5060;received=192.0.2.4
接下来,服务器传输尝试将请求与服务器事务相匹配.它使用第17.2.3节中描述的匹配规则进行匹配.如果找到匹配的服务器事务,则将请求传递给该事务进行处理.如果没有找到匹配项,请求将传递给核心,核心可能决定为该请求构造一个新的服务器事务.请注意,当UAS核心向INVITE发送2xx响应时,服务器事务将被销毁.这意味着,当ACK到达时,将没有匹配的服务器事务,并且根据此规则,ACK将传递到UAS核心,在那里进行处理.
18.2.2 发送响应
服务器传输使用最上方 Via header字段的值来确定发送响应的位置.它必须遵循以下过程:
o 如果"发送协议"是可靠的传输协议,如TCP或SCTP,或通过这些协议的TLS,则必须使用创建事务的原始请求源的现有连接发送响应(如果该连接仍然打开).这要求服务器传输维护服务器事务和传输连接之间的关联.如果该连接不再打开,服务器应使用"sent-by"值中的端口(如果存在)或该传输的默认端口(如果未指定端口),在"received"参数中打开与IP地址的连接.如果该连接尝试失败,服务器应使用[4]中针对服务器的过程,以确定打开连接并向发送响应的IP地址和端口.
o 否则,如果Via 头字段值包含"maddr"参数,则必须使用"sent-by"中指示的端口或端口5060(如果不存在)将响应转发到此处列出的地址.如果地址是多播地址,则应使用"TTL"参数中指示的TTL发送响应,如果该参数不存在,则应使用1的TTL发送响应.
o 否则(对于不可靠的单播传输),如果顶部通孔具有"received"参数,则必须使用"sent-by"值中指示的端口将响应发送到"received"参数中的地址,如果未明确指定,则使用端口5060.例如,如果此操作失败,导致ICMP"端口不可访问"响应,则应使用[4]第5节中的程序来确定将响应发送到何处.
o 否则,如果未标记收件人,则必须使用[4]第5节中的程序将响应发送到"sent-by"值指示的地址.
18.3 框架
在面向消息的传输(如UDP)的情况下,如果消息具有Content-Length头字段,则假定消息体包含那么多字节.如果传输数据包中有超出正文末尾的额外字节,则必须丢弃这些字节.如果传输数据包在消息体结束之前结束,则认为这是一个错误.如果消息是响应,则必须将其丢弃.如果消息是一个请求,那么元素应该生成一个400(错误请求)响应.如果消息没有Content-Length头字段,则假定消息体在传输数据包的末尾结束.
在面向流的传输(如TCP)的情况下,Content-Length头字段指示主体的大小.Content-Length头字段必须与面向流的传输一起使用.
18.4 错误处理
错误处理与消息是请求还是响应无关.
如果传输用户要求通过不可靠的传输发送消息,并且结果是ICMP错误,则行为取决于ICMP错误的类型.主机,网络,端口或协议不可访问错误或参数问题错误应导致传输层通知传输用户发送失败.应忽略源猝灭和TTL超出的ICMP错误.
如果传输用户要求通过可靠传输发送请求,结果导致连接失败,则传输层应通知传输用户发送失败.