![](http://www.ctiforum.com/uploadfile/2020/0310/20200310093931810.jpg)
此图例和以下讨论均来自于互联网资源
在后续的章节中,我们将讨论answer如何回应offer,会话修改的细节处理,向对方指示协商能力,offer/answer交互模式的拓展ICE。
1、背景介绍和基本操作
首先,我们介绍一下我们讨论的基本背景环境。到目前为止,我们讨论的核心话题涉及了SDP和准备要讨论的offer/anser交互模式。基本上我们都是围绕两个核心的规范来讨论,其中,RFC4566(SDP)为基本蓝图,然后配合RFC3264关于offer/answer交互模式。关于SDP的内容,我们在前面的章节已经有完整的介绍(SDP基础),那个章节涵盖了SDP的核心定义/专有名词,语法,特征属性,使用场景等相关细节,读者可以查阅上一个章节的内容,这里不再赘述。根据上一个章节的内容,我们在本章节进一步讨论SDP协商时使用的交互模式-offer/answer模式。在本章节,我们将重点以RFC3264为蓝本,介绍offer/anwer交互模式。笔者主要以offer和answer两个部分为核心主线,分别按照两个部分中的单播媒体和多播媒体的处理方式的不同来展开讨论。这里提醒读者,为了更好地支持IPv4,在RFC3264的基础上,RFC6157对媒体描述管理进行了更新。因此,如果读者涉及了在IPv6环境中关于SDP中的媒体描述,读者可以查阅RFC 6157-4.1章节的细节。如果读者对SDP协商模式有兴趣的话,可以结合具体的代码示例来做进一步的研究。以下示例是开源SIP协议栈-PJSIP中关于SDP协商状态机的处理流程示意图:
![](http://www.ctiforum.com/uploadfile/2020/0310/20200310093812572.png)
链接:https://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__SDP__NEG.htm#details
很多技术人员,一说到offer/answer交互模式,就不假思索说这个概念其实非常简单。事实上,很多人对此概念有不少误解或者还在半桶水的认知状态。因为很多技术人员经常排除的问题基本上都是一个简单的双方呼叫(单播会话),排查的交互会话描述也就双方的会话参数,并没有涉及到多播会话使用场景,例如IP广播,会议等处理。另外,关于单播和多播场景中的RTP媒体流的处理也非常不同(可参考RFC 6284-7.1.2的端口映射),需要读者对这些概念有一个充分的理解。因此,很多具体的协商需要大家了解。
![](http://www.ctiforum.com/uploadfile/2020/0310/20200310093823289.jpg)
此图片以及以下图例均来自互联网资源
我们需要首先提醒读者这些问题,在offer/answer交互模式下,单播会话和多播会话的处理方式是有差别的。SDP(RFC 4566)当时设计的构想是提供一种方式来描述多播骨干网中传输的多播会话。SAP(RFC 2947)的设计构想是作为一种多播机制传输SDP消息的。在很多业务场景中,虽然规范中支持也允许支持单播操作,但是规范中支持单播操作相对不太完整。多播会话操作需要覆盖全部会话参与者的操作,单播会话则仅涉及了两个参与者以及其各自的认同的工作参数。具体来说,多播会话比单播会话涉及了更多的关于处理机制和处理方式,在offer/answer交互模式下有不同的处理方式。因此,提醒读者,我们在下面的讨论中,针对各种环境都会分别介绍单播会话和多播会话的处理方式,希望读者千万不要迷惑。例如,如果是多播会话的话,它要求针对具体的媒体流对所有参与方地址发送一个单多播地址,如果是单播会话的话,它仅需要双方的两个地址即可。再比如,如果是多播会话的话,它仅要求标识出会话所使用的具体编码即可,通知所有会话参与方仅使用标识的编码,但是,如果是单播会话中,则需要列出一个编码支持列表,双方可能都支持某些重复的编码,通过二次协商才能决定使用何种编码。另外,读者可以想象一下,在单播会话环境中,随着技术和网络环境的不断发展,终端支持的各种编码或者协商标识越来越多,尽管双方的SDP提供了丰富的足够的会话描述信息,但是因为会话描述定义越来越多,它们所带来的问题也越来越多,例如定义的语法格式问题,操作细节的统一性问题。因此,会话双方究竟如何成功协商,在技术方面,这仍然存在很多争议,这也直接导致了很多环境下,软硬件终端包括服务器端的双方SDP协商不成功的问题。因此,为了实现协商的简化和规范化,RFC 3264基于SDP规定了一种简化的offer/answer 交互模式。接下来,我们简单介绍一下其基本工作原理。
“如无必要,勿增实体”-剃刀原理
在offer/answer交互模式环境中,会话中的发起方(offerer)生成一个offer数据,offer中包括媒体流参数和传输编码,希望接收媒体的IP地址和端口。offer数据传递到对端接收方(answerer),接收方也生成一个answer数据回复给offerer发起方,在answer回复数据中包含了已匹配的媒体会话描述参数,表示其媒体是否可以接受。然后通过协商好的传输编码,通过offer消息中的地址和端口对offerer发起方发送媒体流。无论是单播会话还是多播会话都可以支持offer/answer交互模式。注意,读者如果对交互模式下的offer/offerer和answer/answerer有歧义,最好查阅SDP基础章节中核心定义全解的内容。
现在,我们讨论一些关于协议层操作的流程。offer/answer模式工作的前提基于一些高级协议,例如SIP协议存在,SIP协议有能力支持SDP的协商来实现基于代理之间的对会话创建支持。协议层的操作从一方代理对另外一方发起初始化的offer开始。对端的代理可以接受offer,并且返回一个answer或者拒绝这个offer。拒绝offer取决于高级协议层。这里强调一点,offer/answer交互模式是atomic级的,这表示它具有一定的制锁功能。如果这个answer被拒绝的话,会话将回复到offer之前的状态。任何时间其中一个代理都可以生成一个新的offer来更新此会话状态。但是,如果代理已经收到了一个offer,代理还没有接受或者拒绝,此代理一定不能生成新的offer。此外,如果代理已经生成了一个较早的offer,这个代理在还没有收到针对较早的offer返回的answer消息或者拒绝消息,此代理一定不能生成一个新的offer。简单来说,就是代理在没有收到较早offer的回应结果(应答或者拒绝)之前,它一定不能再生成一个新的offer。有时,我们可能会看到一种特殊状态,代理已经发送了一个offer后,但是在没有收到此offer的answer前,如果代理收到了一个offer的话,这种状态称之为 “glare condition”。
![](http://www.ctiforum.com/uploadfile/2020/0310/20200310093812337.jpg)
Glare Case 状态
双方代理可能同时对对方发送一个更新offer。这种特殊情况下的处理机制需要更高层协议来对这种特殊状态进行数据包发送到排序处理。如果读者对glare case 或者异常处理有兴趣做进一步研究的话,可以参考RFC 6337-4章节。接下来,我们开始讨论生成offer的流程处理,以及在生成初始化offer中关于单播媒体和多播媒体的处理方式。
2、关于生成初始化offer处理流程
我们讨论生成offer消息之前,首先我们一定要确定,无论是offer消息还是answer消息,它们一定是一个有效的SDP消息。
在SDP中针对offer/answer的构成语法可以忽略“e”或者“p=”行。笔者不清楚为什么在offer/answer的消息中可以忽略“e”或者“p=”行,难道因为这两个会话描述不是十分重要的协商参数? “o“行中的会话ID的数值和版本号必须是一个64位的有符号整形数,并且版本的初始值必须小于(2**62) ? 1,这样可以防止翻转。在SDP规范中,可以允许多个SDP会话描述拼接在一起构成一个大的SDP消息,但是SDP消息使用在offer/answer交互模式下时,一个SDP消息必须包含一个完整的会话描述。
读者知道,SDP中的"s="传递会话主题,这种定义方式对多播会话方式是非常合理的,但是对单播会话方式存在一定问题。因此,一般推荐是”s“行有一个单空格字符或一个破折号构成。SDP "t="行负责传递会话时间,通常情况下,对单播会话的媒体来说,它的创建或者结束一般来自于外部的信令的控制,例如,我们现在讨论的SIP协议。那种情况下,"t="行应该设定为”0 0.“。
offer消息中包含零个或者多个媒体流,每个媒体流通过”m=“行的媒体会话和其关联特征属性进行说明。读者可能不明白,为什么offer消息中可能会包含零媒体信息?其实,包含零媒体仍然有它的原因。如果offer消息中包含零个媒体,这表示发起方-offerer希望和对端通信,但是发起方会在将来某一时间时间在此会话中添加那个媒体,添加媒体的方式是通过发送一个修改的offer来处理。 此媒体可以是一个单播和多播的混合。如果是多播的媒体,那offer消息中需要在"c="行添加多播地址。它们的构成方式取决于它们的媒体是单播还是多播媒体。简单理解,这里的零媒体不是表示offer没有什么可做,这表示发起方可能将来在某一时间发起媒体流,但是不是现在。如果将来发起媒体流,offerer会更新offer再次提醒对端answerer。下面,我们继续讨论offer中的单播媒体场景的处理流程。
3、关于offer的单播媒体处理讨论
这里,我们花费一点时间需要详细说明offer中的单播媒体处理流程。在offer中的单播媒体处理中,offer对媒体的发送和接收标注涉及了多个方向指示特征属性(a=sendonly,a=recvonly,a=sendrecv,a=inactive-参考RFC3108和RFC2327),多个特征属性又具有不同的含义,所以请读者在阅读本部分内容时一定要特别注意。读者也可以查阅笔者的历史文档来学习关于这三种属性应用场景示例。
如果offer仅希望对对端发送媒体时,offer必须对此媒体标注为send-only的表示,通过特征属性"a=sendonly"行来标识。如果媒体发送的方向属性作为媒体媒体流属性或者会话属性出现的话,我们就会认为此媒体标注了媒体发送方向。同理,如果此offer仅希望从对端接收媒体的话,offer必须对此媒体标识为recvonly,表示仅为接收状态,通过特征属性“a=recvonly”表示。如果,offer希望和对端通信,但是,此时,offer既不想发送媒体也不行接收媒体时,它通过对媒体标识为"a=inactive"行来表示其当时状态。
这里,笔者需要提醒一下,因为很多最新的规范已经对RTP协议的实时应用程序传输协议-RFC3550进行了更新(包括5761,6051,6222,7022,7160,7164,8083和8108),因此一些特别的处理流程需要提醒读者。如果是涉及了RFC3550中描述的实时传输协议和实时传输控制需要的话,为了支持以上三种方向指示的状态,RTCP同样需要被发送和接收。这种情况下,媒体流的方向指示不会影响RTCP的使用。如果offer希望对对端发送和接收媒体的话,它可以通过"a=sendrecv"行来标识也可以忽略其属性设置(因为此属性为默认设置属性)。
读者需要注意,offer消息中三种媒体流向的方向有一些不同。对于标记了“a=recvonly”和“a=sendrecv”的媒体流来说,在offer消息中,端口号和地址表示发起方offerer希望接收媒体流的端口和地址。对于标识为“a=sendonly” RTP 媒体流,端口号和地址间接指示为offerer希望接收RTCP数据的地址。除非有明确表示说明,否则RTCP报表数据将会发送到比标识的端口高一位的端口(这是默认的RTCP端口发送方式)。很多时候,读者可能对offer中的IP地址和端口使用有一些误解,这里笔者做进一步的解释。在offer中出现的ip地址和端口不能指示将要由发起方offerer发送出去的RTP/RTCP的源地址,源端口。在offer消息中,如果端口数为零,这表示媒体已经被经过offer消息处理,但是此媒体一定不能被使用,因为此初始的offer中没有任何有效的语法参数。有时,如果设置端口零可以结束现存的媒体流。一般来说,端口数量为零表示此媒体流不是offer/answer双方需要的媒体流。但是,一些特殊的环境下,编码类型一样,但是可能因为payload不同的话,也可能需要做一些协商处理。针对标识为”a=sendonly“ 或“a=sendrecv”的媒体,在answer的消息中同样的媒体可能标识了不同的payload。offerer发起方收到answerer回复后,重新发送一个offer。这次发送中,offerer发起方必须包含一个和answer消息中一样的媒体payload。这样才能保证双方的媒体的payload一致性。有时,为了保证和H323的兼容性,每个方向可以支持不同的payload类型号。
在所有的RTP流使用场景中,fmtp 媒体格式类型可能出现来支持更多的媒体格式类型描述。所有的媒体描述应该包含"a=rtpmap"行,它用来映射相应的payload 类型号码来对编码进行编码处理。如果没有"a=rtpmap"行的话,应该使用默认的当前的属性设置(RTP/AVP)。具体默认属性设置,读者可查阅RFC3551-6。
offer的协商过程中,读者需要另外注意几个经常使用的媒体描述参数。在协商过程中,offer消息中必须提供一个"m="行的格式列表,通过偏好优先级的顺序来通知对端offer中推荐使用的优先级编码格式。优先级最高的是最优先使用的编码格式。有时,我们在配置软交换或者媒体服务器时,双方呼叫失败,有可能是编码不匹配导致,比如说没有匹配的prefered的编码。所以,编码列表的顺序是非常重要的,技术人员需要对照服务器端的编码列表实现对照本地终端的编码列表顺序检查。比如FreeSWITCH中的编码优先级设置:
或者思科设备设置:
- Cisco-router(config-class)#codec preference 1 g723r63
- Cisco-router(config-class)#codec preference 2 g729br8
- Cisco-router(config-class)#codec preference 3 g711ulaw
- Cisco-router(config-class)#codec preference 4 g726r32 bytes 240
如果ptime特征属性出现offer中,它表示offer所期望的收到的打包时长,当然,ptime必须大于零。如果offer中出现了bandwidth的话,它表示offer所期望带宽来传输媒体流。当然,带宽值也允许设置为零(不建议),这表示没有媒体发送,同时也关闭了RTCP数据发送。
如果是offerer中的多媒体的话,根据多媒体类型的不同处理方式也有一定的差别。如果在offer中出现了不同类型的多媒体流(语音,视频,文本等),这表示发起方offerer希望同时使用这些多媒体流。比较典型的例子就是视频会议,视频会议中,语音和视频媒体流被同时使用。如果在offer中出现来同样的媒体类型的话,这表示offerer发起方期望同时接收或发送那种同一类型的媒体流。关于同一类型的媒体流收发,双方可能有一定的规则策略需要遵守,这取决于本地资源(例如,麦克风/摄像头和录像终端)和业务需求的设置。另外一些限制也可能影响多媒体的本地处理策略,例如不同语音或者视频媒体流的混音/混屏处理,按需录像录音处理等业务需求。
Offerer发送方需要根据不同的指示标识调整为一个相应的状态。一旦发起方Offerer发送了offer消息以后,发起方必须准备接收offer描述的任何标识为recvonly的媒体。另外,发起方必须准备发送和接收在offer中标识为sendrecv的媒体,并且准备发送在offer中标识为sendonly的媒体。当然,何时发送还要取决于对端answer的地址和端口。在RTP的环境中,虽然可能offerer在answer消息到达之前,提前收到了媒体流,但是发起方仍然需要收到answer消息后,它才能发送RTCP接收方报告数据。
4、关于offer的多播媒体处理讨论
在offer中,如果一个会话描述中包含一个多播媒体流,此多播媒体流列为仅接收或者发送状态,这表示参与者(包括了发起方offerer和接收方answerer)仅能接收或发送媒体流。和多播媒体流处理方式相比,单播媒体处理仅是发起方和接收方媒体流的直接收发。除了以上这个区别以外,offer中的多播媒体的语法定义可以查阅RFC4566的规范说明。
参考资料:
https://www.rfc-editor.org/rfc/rfc3264
https://tools.ietf.org/html/rfc6284
https://tools.ietf.org/html/rfc5939
https://www.pjsip.org/pjmedia/docs/html/group__PJMEDIA__SDP__NEG.htm
![](http://www.ctiforum.com/uploadfile/2019/1224/20191224014316600.jpg)
关注微信公众号:asterisk-cn,获得有价值的Asterisk行业分享
Asterisk freepbx FreeSBC技术文档: www.freepbx.org.cn
融合通信/IPPBX商业解决方案:www.hiastar.com
如何使用FreeSBC,qq技术分享群:334023047, www.freesbc.cn