一个UA的核心概念就是对话。对话是表现为两个用户代理(UA)之间的持续一段时间的点对点的SIP关系。对话(Dialog)使得用户代理之间的消息顺序传递和两个用户代理之间的请求正确路由更加容易。对话(Dialog)可以认为是对SIP消息解释的上下文关系。本节将讨论如何通过请求和应答来创建一个对话(Dialog),并且在对话(Dialog)中如何发起和响应后续的请求。

一个对话在参与对话的UA中都有一个dialog ID作为标记,这个ID由Call-ID,和一个本地tag和远程tag组成。各个UA的dialog ID在对话中是不一样的。特别是,在一边UA的本地tag,在另外一方就是远程tag。这些tag都是互相不透明的,并且使得整个dialog ID是唯一的。

dialog ID同样是和所有的To头域中包含了tag参数的请求及应答相关。

填写一个消息中的dialog ID的规则依赖于SIP元素是UAC还是UAS。对于UAC来说,dialog ID中的Call-ID的值会填写到消息中的Call-ID域中,远程tag放在消息中的To的tag参数中,本地tag放在From的tag参数中。(这些规则对请求和应答都适用)。对于UAS来说,dialog ID的Call-ID值放在消息的Call-ID头域中,远程tag放在From头域的tag中,本地tag放在To头域的tag参数中。

一个对话包含一些特定的状态用于以后的对话中的消息传送。这个状态由dialog ID、本地序列号(用来排序UA到对方的请求的序列)、远程序列号(用来排序请求从远端到本UA、本地URI、远端URI、remote target、一个布尔类型的标记“secure”,路由集合(一组有序的URI)组成。

路由集合是由发送请求到对方需要途径的一组服务器列表组成。一个对话可以处于“early”状态,这是由于当这个对话收到了临时应答而创建,并且当收到了2xx终结应答的时候转换到“confirmed”状态。对于其他应答,或者没有应答,“early”对话将会终结。

创建一个对话

对话是由对一组特定请求的没有失败的应答来创建的。只有包含To tag的2xx和101-199应答,并且请求是INVITE,会建立一个对话。当收到一个非终结应答的时候,对话会建立成“early”状态,并且成为early dailog。创建对话的时候可以使用Extension来定义扩展。在这里,我们描述与方法无关的对创建对话状态的处理。

UA必须按照下边描述的方法对dialog ID进行赋值。

UAS行为

当UAS响应一个请求给出一个应答,并且这个应答会建立一个对话的时候(比如对INVITE的2xx应答),UAS必须拷贝所有的请求中的Record-Route头域到应答中去(包括URI、URI参数和其他任何Record-Route头域的参数,无论UAS是不是认识的参数都需要原样拷贝),并且必须维持这些参数的顺序。UAS必须增加一个Contact头域给应答。这个Contact头域包含一个UAS在后续对话请求中接收请求的地址(这个包含了给INVITE请求的2xx应答的ACK请求处理的地址)。通常情况下,UAS会用IP地址或者FQDN形式来发布自己的这个Contact地址。这个在Contact头域中的URI必须是一个SIP或者SIPS URI。如果创建对话的请求在Request-URI中包含的是SIPS URI,或者在Record-Route头域的最上的一个值是SIPS URI,或者如果请求中没有Record-Route头域但是请求中的Contact头域是SIPS URI,那么给出的应答中的Contact头域必须是一个SIPS URI。这个URI应该是全局有效的(就是说,这个URI可以用于对话外的消息)。同样的,在请求INVITE中的Contact头域的URI也不应当仅限于这个对话中使用。因此它可以用于对话外的消息中。

UAS接着创建这个对话的状态。对话状态必须维持直到对话结束。

如果请求是通过TLS过来的,并且Request-URI包含一个SIPS URI,“secure”标志将被赋值成为TRUE。路由集合必须设置成为请求中的Record-Route的URI列表,保留所有的URI参数和顺序。如果请求中没有Record-Route头域,那么路由集合必须设置成为空。这个路由集合,即便是空的,为了以后的对话中的请求,也要覆盖任何预先存在(pre-existing)的路由集合。remote taget必须设置成为请求的Contact头域中的URI。

远程序列号必须设置成为请求中的Cseq头域的序列号。本地序列号必须设置成为空。dialog ID中的呼叫标志应该设置成为请求的Call-ID头域的值。dialog ID的本地tag必须设置成为对请求的应答包中的To头域的tag,并且dialog ID的远程tag必须设置成为请求中的From 头域中的tag。UAS必须能够处理接收到的请求中的From头域没有tag标志,在这种情况下,这个tag就是空值。这是为了兼容RFC2543协议,它并没有定义From tag。

UAC行为

当一个UAC发出一个请求,这个请求能够建立一个对话(比如这个请求是INVITE),它必须在Contact头域中提供一个基于全局的SIP或者SIPS URI(例如,可以在对话外使用的SIP URI)。如果请求包含一个Request-URI或者最上的Route头域是SIPS URI,Contact头域也必须包含的是SIPS URI。

当一个UAC接收到应答,并且这个应答建立对话的时候,它也同样构造这个对话的状态。这个状态必须维持到对话的结束。

如果这个请求是基于TLS发送的,并且Request-URI包含一个SIPS URI,那么“secure”标志被设置成为TRUE。

路由集合必须设置成为应答中的Record-Route头域的URI列表,保留所有的URI参数和顺序。如果在应答中没有Record-Route头域,那么这个路由集合必须设置成为空集合。这个路由集合即便是空的,为了以后的对话中的请求,也要覆盖任何预先存在(pre-existing)的路由集合。

本地序列号必须设置成为请求中的Cseq头域的序列号。远程序列号必须设置成为空(他会由远端的UA在对话中发送请求而建立)。dialog ID中的呼叫标志必须设置成为请求的Call-ID头域的值。dialog ID的本地tag必须设置成为请求中的From头域的tag,dialog ID的远程tag必须设置成为应答中的To头域的tag。UAC必须能够处理接收到的应答的To头域中没有tag的情况,在这个情况下,tag值取值成为空。这是为了能够向下兼容RFC2543,它没有规定To的tag。

remote URI必须设置成为To头域的URI,local URI必须设置成为From头域的URI。

对话中的请求

当两个UA之间的对话建立以后,他们都可以在对话中初始化一个新的事务(transaction)。如果UA发送请求,将遵循UAC的事务规则。UA接收请求将遵循UAS的规则。在建立对话的事务过程中,UA扮演的角色可能是不一样的。

在对话中的请求可以包含Record-Route和Contact头域。不过,虽然他们会修改remote target的URI,但是这些请求也不会导致对话的路由集被改变。明确说,如果请求不是刷新target的请求,那么这个请求不会更改对话的remote target URI,如果请求是刷新target的请求,那么这个请求才会更改对话的remote targetURI。对于用INVITE建立的对话来说,唯一的能够刷新target的请求就是re-INVITE。可能会有其他扩展定义通过其他方法来刷新target的请求。

注意ACK不是一个刷新target的请求。

刷新target请求只会更改对话的remote targetURI,并且更改由Record-Route指定的路由集合。如果更新路由集合会带来严重的和RFC2543向后兼容问题。

1.UAC的请求行为

1.1产生请求

在对话中的请求是通过用许多对话的状态部分来构造的。在TO头域中的URI部分必须设置成为对话状态中的remote URI。To头域的tag参数必须设置成为dialog ID中的remote tag部分。请求的From URI必须设置成为对话状态中的local URI。From头域的tag参数必须设置成为dialog ID的local tag部分。如果remote或者local tag是空值,那么tag参数必须分别从From或者To头域中去除。

在请求序列中的原始请求的To和From头域的URI的使用方法是为了向下兼容RFC2543协议的,在RFC2543协议中,使用URI作为对话的标志。在这个规范中,只有tags用于区分对话。有可能在本协议的后续版本中,在对话中的请求必须强制反应原始请求的To和From头域的URI将会去除。

请求的Call-ID必须设置成为对话的Call-ID。在对话中的请求必须严格遵循单个递增的Cseq序列号(每次增加1)(当然要除了ACK和CANCEL,这两个请求中的Cseq必须和原始的请求或者确认请求一样)。因此,如果本地序列号(local sequencenumber)不为空,那么本地序列号码必须依次增加1,并且这个数值要存放到Cseq头域中。如果本地序列号码是空的,那么必须按照约定的初始值填写进去。在Cseq头域中的method字段必须和请求的方法(method)一致。

通过使用32位的长整数,使得即使每秒种产生1个请求,也会要136年才会用完这个整数出现重复。这个序列号的初始值的选取是为了让对话中后续的请求序列号不会重复。非0的初始值可以考虑采用时间来作为初始的序列号。一个客户端可以用31位有符号整数或者32位无符号整数来存放时间作为初始化的序列号。

UAC使用remote target和路由集合来构造请求中的Request-URI和Route头域。如果路由集合是空的,那么UAC必须把remote target URI放到Request-URI中,并且UAC不能添加Route头域到请求中。

如果路由集合不为空,并且路由集合的第一个URI包含lr参数,那么UAC必须填写remote targetURI到Request-URI,并且必须包含Route头域,这个Route头域按照顺序填写路由集合和路由集合的参数。

如果路由集合不为空,并且路由集合的第一个URI没有包含lr参数,那么UAC必须把第一个URI放在Request-URI中,并且拆去所有不被Request-URI允许的参数。UAC必须增加一个Route头域顺序包含所有剩下的路由集合元素,及其参数。UAC接着必须把remote targetURI放在Route头域的最后一项。

例如,如果remote targe是:sip:user@remoteua 并且路由集合包括:

<sip:proxy1>,<sip:proxy2>,<sip:proxy3;lr>,<sip:proxy4>

那么请求应该有下列的Request-URI和Route头域

METHODsip:proxy1

Route:<sip:proxy2>,<sip:proxy3;lr>,<sip:proxy4>,<sip:user@remoteua>

如果路由集合的第一个URI不包含lr参数,那么对应的说明proxy并不能支持本文档所约定的路由机制,而是支持RFC2543文档所约定的路由机制,那么在发送信息的时候需要通过替换Request-URI为接收到的第一个Route头域的值。将Request-URI的值放在Route头域的目的是为了保护Request-URI,使得它经过严格路由的时候不丢失。

在对话内的任何一个刷新target的请求中,都应当包含一个Contact头域,并且这个URI除非有必要,否则都应当是和对话内上次请求的URI值一样。如果“secure”标志设置成为TRUE,那么URI也应当是SIPS URI。

在刷新target请求中的Contact头域会更新remote target URI。这个允许UA提供一个新的联系地址(Contact address),表明它在对话中改变了自己的地址。不过,如果请求不是刷新target的请求,那么不会影响对话中的remote target URI。

一般把请求发送到Route头域的最上一个地址,或者如果没有Route头域,那么就发送到Request-URI地址。由于受到特定的限制,这些步骤也允许把请求发送到另外一个地址(比如在route set中没有的缺省的外发proxy)

1.2处理应答

UAC将会从transaction层收到请求的应答。如果客户端的事务层返回一个超时,这会等同于一个408(请求超时)的应答。UAC处理3xx应答的时候,在这个应答是在对话内的请求的应答的处理方法和在对话外的处理方法是一样的。需要注意的是,虽然UAC会尝试新的地址(处理3xx应答的时候),但是它依旧使用对话内的路由集合来构造请求的Route头域。

当UAC收到一个刷新target请求的2xx应答的时候,如果对话的remote targetURI存在,那么它必须用这个应答的Contact头域的值来替换对话的remote targetURI。

如果对话那的请求的应答是481应答(呼叫/事务不存在Call/Transaction Does NotExits)或者一个408(请求超时),那么UAC应当终止这个对话。并且UAC应当在请求完全没有应答的时候(客户端transaciton将会通知TU这个超时)客户端transaction终止这个对话。

对于INVITE初始化的对话,终止对话需要发送一个BYE。

2. UAS行为

在对话中发送的请求,就像其他请求一样,是原子请求。如果UAS收到某个请求,所有的相关状态要么一起改变,要么就一起不变。在某些请求中,请求会影响好几个状态(比如INVITE请求)。

UAS从transaction层收到请求。如果请求的To头域有tag字段,UAS的处理核心需要校验对话的ID,拿请求中的tag和现存的对话相比较。如果匹配成功,那么就是一个在对话中的请求。在这种情况下,UAS首先使用对话外请求处理的步骤。如果请求To头域包括了一个tag字段,但是对话的ID并不匹配现存的对话,UAS可能是因为崩溃而重新启动,或者收到了一个另外(可能是错误的)UAS(UAS可以构造To的tags,这样UAS在灾备恢复下,可以把这个tag看成它自己的)。还有一种简单的可能是请求发送错误了。在这个基础上,UAS可以选择接受或者拒绝请求。在允许的情况下,尽量处理这些请求会提供灾难恢复的机制。UAS如果希望支持这样的特性就必须遵循一些原则,比如始终使用单调递增的Cseq序列号,甚至是在重新启动之后也这样,在重启动后重建路由集合,处理越界的RTP时间戳和序列号等等。

如果UAS由于不希望重构对话而拒绝这个请求,它必须应答对方一个481(呼叫/事务不存在。Call /Transaction不存在)应答。

对于在对话中接收到的,那些不会用任何形式更改对话状态的请求,比如OPTIONS请求,他们等同于在对话外的处理请求。

如果远端的序列号(remote sequence number)是空的,它必须设置成为请求中的Cseq头域的序列号(sequence number)。如果remote sequencenumber不是空的,但是请求中的sequence number小于这个remote sequencenumber,请求就是非顺序的,并且必须通过应答500(服务器内部错误)打回去。如果remote sequencenumber不是空的,并且请求中的序列号大于这个remote sequence number,请求就是按照顺序的。这个请求中的Cseq的序列号可以比remote sequencenumber大不止1。在这种情况下,并非是错误的,并且UAS应当准备接收和处理比上次处理的请求Cseq值大于1 的请求。UAS必须设置remote sequencenumber成为请求中的Cseq头域中的序列号。

如果一个proxy废弃掉一个UAC产生的请求,并且UAC重新递交这个请求的时候。这个请求是会具有一个全新的Cseq序列号。UAS是不会收到第一个请求的,这样,Cseq序列号就会出现间隔,这样的间隔并非是一种错误的情况。

当UAS接收到一个target刷新请求的时候,如果请求中存在Contact头域,它必须用Contact头域中的URI来替换对话的remote targetURI。

终止对话

在建立对话中的终结对话,跟请求方法无关,如果对话外的请求产生了一个非2xx终结应答,任何前边请求创建的“早期对话”(early dialogs)将会终止。在已经建立的对话中,终结对话就是请求方法相关的。在这个定义中,BYE方法将会终结一个对话。

对话(Dialog)相关推荐

  1. SIP 中的Dialog,call,session 和 transaction .

    如果你对Sip协议中Call, Dialog, Transaction和Message之间的关系感觉到迷惑,那么,那么我可以告诉你,你并不孤单,因为大多数初学者对于这些名词之间的关系都会感到疑惑. M ...

  2. 语音对话平台海尔五代智能电视落地

    智能语音交互(Intelligent Speech Interaction)是AI的入口,智能语音交互之于VUI,正如鼠标键盘之于GUI.但什么是智能语音交互呢?这个名词并非每位同学都能望文生义,我试 ...

  3. 简单笔记(rsrp/mbps/session/dialog/dbm)

    会话(session),对话(dialog),事务(transaction),分支(branch) 名词 定义 SIP 层 会话 session是媒体交换之后才建立的 SIP使用SDP来通知传输层(R ...

  4. SIP 中的Dialog,call,session 和 transaction

    如果你对Sip协议中Call, Dialog, Transaction和Message之间的关系感觉到迷惑,那么,那么我可以告诉你,你并不孤单,因为大多数初学者对于这些名词之间的关系都会感到疑惑. M ...

  5. java sip 携带sdp_SIP中的SDP offer/answer交换初探

    1.早期媒体 无论是在PSTN还是在VoIP网络中,一个呼叫的最终目的让两个用户进行交谈(conversation).这里我们将由用户之间的交谈所产生的媒体称为常规媒体("regular m ...

  6. SAP RFC通信模式

    在网络技术中,数据通信可以大致划分为两种基本模式:同步通信和异步通信. 其本义是:异步通信时,通信双方时钟允许存在一定误差:同步通信时,双方时钟的允许误差较小.在SAP的系统间的通信过程中,也借用术语 ...

  7. 【SIP协议】学习初学笔记

    1.SIP这玩意是怎么走来和如何构建的? 通俗的说,SIP就是一个轻量级信令协议,它可以作为音频.视频.及时信息的信令. 说到SIP是怎么出来的就要提H.323,而提到这个标准由不得不提到ITU-T, ...

  8. HTML 5 中的新元素

    2019独角兽企业重金招聘Python工程师标准>>> 超文本标记语言(HTML)的开发到 1999 年 HTML 4 就停止了.万维网联盟(W3C)把重点转向将 HTML 的底层语 ...

  9. abap 帮助文档 中文_一个13年ABAP老兵的建议:了解这些知识对ABAP开发有百利而无一害...

    在Jerry之前的图片推送中,我提到了SAP社区上这样一篇博客: Proof of Concept: Deploying ABAP in Kubernetes https://blogs.sap.co ...

  10. SIP协议详解(中文)-6

    由于MIME包体是在"inner"消息中的,实现中通常会加密MIME指定的头域,包括:MIME-Version,Content-Type,Content-Length, Conte ...

最新文章

  1. python基础知识练习题
  2. js小数运算出现多为小数问题_JS操作小数运算,结果莫名其妙出现多位小数问题...
  3. php隐藏文件链接,php隐藏文件实际下载地址的方法
  4. python xycoords_python可视化节点关系(三):matplotlib(2)鼠标交互
  5. python安装xlrd和xlwt及应用
  6. 1.6 语言模型和序列生成
  7. 【mfc】vs2019创建MFC基于对话框的项目没有插入任何代码运行报错:0xC0000005:读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突
  8. 3.Jenkins 权威指南 --- 设置构建作业
  9. 自动驾驶_感知_目标检测(基于图像)
  10. mysql分割字符串_mysql分割字符串
  11. java文件上传与下载
  12. LiveCharts心得
  13. Vuex Actions使用
  14. 和平精英追猎模式怎么没了 和平精英追猎下架原因
  15. Python常用函数总结(按照字母顺序)
  16. 2021高教杯数学建模A
  17. 百度地图 根据经纬度获取城市或省的名称
  18. 一场美好的婚礼对女孩子来说意味着什么?
  19. JUC笔记-共享模型之管程 (Monitor)
  20. MySQL数据恢复(通过.frm和.idb文件)

热门文章

  1. c# wince 小技巧
  2. C# 将数据导出到Excel汇总(转)
  3. 树形目录生成器.bat
  4. 400是什么错误_404、403、405、500 | 常见网页错误代码解析
  5. 【FPGA-F3】阿里云FAAS平台,极大简化FPGA开发部署流程 1
  6. 沙盒技术——selinux控制
  7. ActiveMQ笔记(二)
  8. 计算机操作系统笔记——线程及其实现
  9. css3ps—ps直接生成css3 使用方法
  10. 《MongoDB实战系列》系列文章导读