13. 发起会话
13 发起会话
13.1 概述
当用户代理客户端希望启动会话(例如,音频,视频或游戏)时,它会制定一个INVITE请求.INVITE请求请求服务器建立会话.该请求可由代理转发,最终到达可能接受INVITE的一个或多个UAS.这些UAS经常需要向用户查询是否接受该请求
INVITE一段时间后,这些UAS可以通过发送2xx响应来接受INVITE(意味着将建立会话).如果INVITE未被接受,将根据拒绝的原因发送3xx,4xx,5xx或6xx响应.在发送最终响应之前,UAS还可以发送临时响应(1xx),告知UAC联系被叫用户的进度.
在可能收到一个或多个临时响应后,UAC将得到一个或多个2xx响应或一个非2xx最终响应.由于接收INVITE的最终响应可能需要较长的时间,INVITE事务的可靠性机制与其他请求(如OPTIONS)的可靠性机制不同.一旦收到最终响应,UAC需要为收到的每个最终响应发送ACK.发送此ACK的过程取决于响应的类型.对于300和699之间的最终响应,ACK处理在事务层中完成,并遵循一组规则(参见第17节).对于2xx响应,ACK由UAC核心生成.
对INVITE的2xx响应将建立一个会话,它还将在发出INVITE的UA和生成2xx响应的UA之间创建一个对话.因此,当从不同的远程UAs接收到多个2xx响应时(因为INVITE分叉),每个2xx都会建立一个不同的对话.所有这些对话都是同一调用的一部分.
本节提供有关使用INVITE建立会话的详细信息.支持INVITE的UA还必须支持ACK,CANCEL和BYE.
13.2 UAC处理
13.2.1 创建初始INVITE
由于初始INVITE表示对话外部的请求,因此其构造遵循第8.1.1节的过程.对于INVITE的特定情况,需要进行额外处理.
INVITE中应存在允许头字段(第20.5节).它指示在对话期间,在发送INVITE的UA上,可以在对话内调用哪些方法.例如,能够在对话[34]中接收信息请求的UA应包括列出信息方法的Allow header字段.
INVITE中应包含受支持的头字段(第20.37节).它列举了UAC理解的所有扩展.
INVITE中可能存在接受(第20.1节)头字段.它在UA接收到的响应以及在INVITE建立的对话中发送给UA的任何后续请求中指示UA可接受的Content-Type.Accept header字段对于指示支持各种会话描述格式特别有用.
UAC可以添加Expires头字段(第20.19节),以限制INVITE的有效性.如果达到Expires头字段中指示的时间且未收到INVITE的最终答复,则UAC核心应根据第9节生成INVITE的CANCEL request.
UAC可能还发现,添加主题(第20.36节),组织(第20.25节)和用户代理(第20.41节)头字段等也很有用.它们都包含与INVITE相关的信息.
UAC可以选择向INVITE添加消息体.第8.1.1.10节讨论了如何构造描述消息体所需的头字段(Content-Type等).
对于包含会话描述的消息体,有一些特殊的规则——它们对应的Content-Disposition是"会话".SIP使用提供/应答模型,其中一个UA发送一个会话描述,称为提供,其中包含会话的建议描述.要约表明了期望的通信手段(音频,视频,游戏),这些手段的参数(例如编解码器类型)以及从应答者接收媒体的地址.另一个UA用另一个会话描述(称为应答)进行响应,该会话描述指示接受哪些通信手段,适用于这些手段的参数以及从报价人接收媒体的地址.提供/应答交换在对话的上下文中,因此,如果SIP INVITE导致多个对话,则每个对话都是单独的提供/应答交换."报价/答复"模型定义了对何时可以提供报价和答复的限制(例如,在进行报价时不能提供新报价).这导致限制了在SIP消息中提供和应答的位置.在本规范中,提供和回答只能出现在INVITE request和响应以及ACK中.提议和答复的使用受到进一步限制.对于初始INVITE事务,规则如下:
o 初始报价必须包含在INVITE函中,如果没有,则包含在从UAS返回给UAC的第一条可靠的非失败消息中.在本规范中,这是最终的2xx响应.
o 如果初始报价是在INVITE中,则答案必须是从UAS返回给UAC的可靠无故障消息,该消息与该INVITE相关.对于本规范,这只是对该INVITE的最终2xx响应.同样的确切答案也可以放在答复之前发送的任何临时答复中.UAC必须将收到的第一个会话描述视为答案,并且必须在对初始INVITE的后续响应中忽略任何会话描述.
o 如果初始报价在从UAS返回给UAC的第一条可靠无故障消息中,则答案必须在该消息的ACK中(在本规范中,2xx响应的ACK).
o 在发送或接收到第一个报价的答复后,UAC可以根据为该方法指定的规则在请求中生成后续报价,但前提是它已经收到任何先前报价的答复,并且没有发送任何未得到答复的报价.
o 一旦UAS发送或接收到对初始INVITE的回复,它不得在对初始INVITE的任何响应中生成后续INVITE.这意味着,仅基于此规范的UAS在初始事务完成之前永远无法生成后续报价.
具体地说,上述规则规定了仅符合本规范的UAs的两种交换——报价在INVITE中,答案在2xx中(可能也在1xx中,具有相同的值),或者报价在2xx中,答案在ACK中.所有支持INVITE的用户代理都必须支持这两种交换.
会话描述协议(SDP)(RFC 2327[1])必须得到所有用户代理的支持,作为描述会话的一种手段,其用于构建报价和应答的使用必须遵循[13]中定义的过程.
刚才描述的要约-应答模型的限制仅适用于内容处置头字段值为"session"的主体.因此,INVITE和ACK都可能包含正文消息(例如,INVITE携带照片(内容处置:呈现),ACK携带会话描述(内容处置:会话)).
如果缺少Content Disposition header字段,则Content Type application/sdp的正文表示处置"会话",而其他Content-Type表示"呈现".
创建INVITE后,UAC将遵循为在对话外部发送请求而定义的过程(第8节).这将导致构建一个客户端事务,该事务最终将向UAC发送请求并交付响应.
13.2.2 处理INVITE响应
将INVITE传递给INVITE客户端事务后,UAC将等待INVITE的响应.如第8.1.3节所述,如果INVITE客户端事务返回的是超时而不是响应,则TU的行为就好像收到了408(请求超时)响应一样.
13.2.2.1 1xx响应
在收到一个或多个最终响应之前,可能会收到零个,一个或多个临时响应.INVITE请求的临时响应可以创建"早期对话".如果临时响应在"到"字段中有标记,并且响应的对话ID与现有对话不匹配,则使用第12.1.2节中定义的程序构建一个对话.
只有当UAC需要在初始INVITE事务完成之前向对话中的对等方发送请求时,才需要早期对话.只要对话处于早期状态,临时响应中的头字段就适用(例如,临时响应中的允许头字段包含对话处于早期状态时可以使用的方法).
13.2.2.2 3xx响应
3xx响应可能包含一个或多个Contact 头字段值,这些字段值提供了被呼叫方可以访问的新地址.根据3xx响应的状态代码(参见第21.3节),UAC可以选择尝试这些新地址.
13.2.2.3 4xx,5xx和6xx响应
可能会收到INVITE的单个非2xx最终响应.4xx,5xx和6xx响应可能包含一个Contact header字段值,该字段值指示可以找到有关错误的其他信息的位置.必须忽略后续的最终响应(只有在错误条件下才会到达).
收到非2xx最终响应后,所有早期对话均视为终止.
收到非2xx最终响应后,UAC核心认为INVITE事务已完成.INVITE client事务处理响应的ACK生成(请参见第17节).
13.2.2.4 2xx响应
由于分叉代理,对于单个INVITE请求,可能会有多个2xx响应到达UAC.每个响应都通过To header字段中的tag参数进行区分,每个响应都表示一个具有不同对话标识符的不同对话.
如果2xx响应中的对话标识符与现有对话的对话标识符匹配,则必须将对话转换为"已ACK"状态,并且必须使用第12.2.1.2节中的程序基于2xx响应重新计算对话的路由设置.否则,必须使用第12.1.2节中的程序构建处于"已ACK"状态的新对话.
请注意,重新计算的唯一状态是路由集.不会重新计算对话中发送的其他状态,例如最高序列号(远程和本地).仅为向后兼容而重新计算路由集.RFC 2543未要求在1x(仅2xx)中镜像Record-Route头字段.但是,我们无法更新对话的整个状态,因为中间对话请求可能已在早期对话中发送,例如修改序列号.
UAC核心必须为从事务层接收的每个2xx生成ACK请求.ACK的头字段的构造方式与在对话中发送的任何请求的构造方式相同(参见第12节),CSeq和与身份验证相关的头字段除外.CSeq头字段的序列号必须与ACK的INVITE相同,但CSeq方法必须为ACK.ACK必须包含与INVITE相同的凭据.如果2xx包含报价(基于上述规则),则ACK必须在其正文中包含答案.如果2xx响应中的报价不可接受,UAC核心必须在ACK中生成有效的应答,然后立即发送BYE.
一旦构建了ACK,则使用[4]中的过程来确定目的地地址,端口和传输.但是,请求直接传递到传输层进行传输,而不是客户端事务.这是因为UAC核心处理ACK的重传,而不是事务层.每次触发ACK的2xx最终响应的重传到达时,ACK必须传递给客户端传输.
UAC核心认为INVITE事务在收到第一个2xx响应后64*T1秒完成.此时,所有尚未转换为已建立对话的早期对话都将终止.一旦UAC核心认为INVITE事务已完成,则预计不会再收到新的2xx响应.
如果在ACK对INVITE的任何2xx响应后,UAC不想继续该对话,则UAC必须按照第15节所述发送BYE请求来终止该对话.
13.3 UAS处理
13.3.1 INVITE的处理
UAS核心将从事务层接收INVITE请求.它首先执行第8.2节中的请求处理过程,该过程适用于对话内部和外部的请求.
假设这些处理状态在不生成响应的情况下完成,UAS核心将执行额外的处理步骤:
1. 如果请求是包含Expires头字段的INVITE,UAS core将为头字段值中指示的秒数设置计时器.计时器启动时,INVITE被视为已过期.如果INVITE在UAS生成最终响应之前过期,则应生成487(请求终止)响应.
2. 如果请求是mid对话请求,则首先应用第12.2.2节中描述的方法独立处理.它还可能修改会话;第14节提供了详细信息.
3. 如果请求的"收件人"头字段中有一个标记,但对话标识符与任何现有对话都不匹配,则UAS可能已崩溃并重新启动,或者可能已收到针对不同(可能失败)UAS的请求.第12.2.2节提供了在这种情况下实现稳健行为的指南.
从此处开始的处理假定INVITE位于对话之外,因此用于建立新会话.
INVITE可能包含会话描述,在这种情况下,UAS将收到该会话的报价.用户可能已经是该会话的参与者,即使INVITE在对话之外.当多个其他参与者INVITE用户参加同一个多播会议时,可能会发生这种情况.如果需要,UAS可以使用会话描述中的标识符来检测该重复.比如SDP
在源(o)字段中包含会话id和版本号.如果用户已经是会话的成员,并且会话描述中包含的会话参数没有更改,UAS可以静默地接受INVITE(即,在不提示用户的情况下发送2xx响应).
如果INVITE不包含会话描述,则会要求UAS参与会话,并且UAC已要求UAS提供会话报价.它必须在返回给UAC的第一条非故障可靠消息中提供报价.在本规范中,这是对INVITE的2xx响应.
UAS可以指示进度,接受,重定向或拒绝INVITE.在所有这些情况下,其使用第8.2.6节中描述的程序制定响应.
13.3.1.1 进步
如果UAS无法立即回复INVITE,它可以选择向UAC指示某种进展(例如,指示电话正在响).这是通过101和199之间的临时响应完成的.这些临时响应建立了早期对话,因此除了第8.2.6节的程序外,还遵循第12.1.1节的程序.UAS可以发送任意数量的临时响应.其中每一个都必须指示相同的对话ID.但是,这些将无法可靠地交付.
如果UAS希望延长应答INVITE的时间,则需要请求"延长",以防止代理CANCEL交易.当事务中的响应之间有3分钟的间隔时,代理可以选择CANCEL事务.为了防止CANCEL,UAS必须每分钟发送一个非100临时响应,以处理丢失临时响应的可能性.
当用户处于等待状态时,或者当与PSTN系统互通时,INVITE事务可以持续更长的时间,PSTN系统允许在不接听电话的情况下进行通信.后者在交互式语音应答(IVR)系统中很常见.
13.3.1.2 INVITE被重定向
如果UAS决定重定向呼叫,则发送3xx响应.300(多选),301(永久移动)或302(临时移动)响应应包含Contact 头字段
包含一个或多个要尝试的新地址的URI.响应被传递到INVITE服务器事务,该事务将处理其重传.
13.3.1.3 INVITE被拒绝
当被叫方当前不愿意或无法在该终端系统上接听额外电话时,会出现一种常见的情况.在这种情况下,应返回486(此处繁忙).如果UAS知道没有其他终端系统能够接受此呼叫,则应发送600(到处忙)响应.然而,UAS一般不太可能知道这一点,因此通常不会使用此响应.响应被传递到INVITE服务器事务,该事务将处理其重传.
拒绝INVITE中包含的报价的UAS应返回488(此处不接受)响应.此类响应应包括一个警告头字段值,解释拒绝报价的原因.
13.3.1.4 INVITE被接受了
UAS核心生成2xx响应.该响应建立了一个对话,因此除了第8.2.6节的程序外,还遵循第12.1.1节的程序.
对INVITE的2xx响应应包含允许头字段和支持的头字段,并且可能包含接受头字段.包括这些头字段允许UAC在呼叫期间确定UAS支持的功能和扩展,而无需进行探测.
如果INVITE请求包含报价,且UAS尚未发送答复,则2xx必须包含答复.如果INVITE不包含报价,则如果UAS尚未发送报价,则2xx必须包含报价.
构造响应后,将其传递给INVITE服务器事务.但是,请注意,一旦INVITE服务器事务收到此最终响应并将其传递给传输,它就会被销毁.因此,有必要定期将响应直接传递给传输,直到ACK到达.2xx响应以从T1秒开始的间隔传递给传输,每次重传的间隔加倍,直到达到T2秒(T1和T2在第17节中定义).当接收到响应的ACK请求时,响应重传停止.这与用于发送响应的任何传输协议无关.
由于2xx是端到端重新传输的,因此UAS和UAC之间可能存在UDP跳数.为了确保跨这些跃点的可靠传输,即使UAS处的传输是可靠的,也会定期重新传输响应.
如果服务器在未收到ACK的情况下重新传输2xx响应64*T1秒,则对话将被ACK,但会话应终止.如第15节所述,这是通过BYE完成的.