定义了语音等待的规范。IPPBX的功能热键可启用MoH功能。
音乐等待具体的实现方式是,当呼叫方(Alice)呼叫被呼叫方(Bob)后,接听以后,被呼叫方用户(Bob)设置此呼叫为等待状态,在等待状态时,通过媒体服务器对呼叫方播放音乐,或者其他的自定义的语音流。被呼叫方通过对媒体服务器或者音乐播放服务器发送一个REFER消息,携带呼叫方信息。然后媒体服务器对呼叫方发起INVITE,替换已经创建的会话中的被呼叫方。然后,媒体服务器对被呼叫方(Alice)发送音乐媒体流服务。一定时间后,Bob重新设置等待的呼叫,对呼叫方(Alice)发送INVITE消息,然后替换会话中的媒体服务器,变成Bob和Alice之间的通话。注意,这里仍然使用了渲染功能,但是在F5流程中实现,表示其等待状态开启。如果Alice拒绝对端的音乐播放,则Alice仍然会处于等待功能,但是会是静音状态(无声音)。

通过以上呼叫流程我们知道,完成音乐等待流程处理需要23个flow。其中,F5开启音乐等待功能,F12开始媒体服务器替换了Bob,媒体服务器对Alice发送音乐数据流确认。在F12的流程中使用了渲染功能,增加了对automation和byeless功能标签的支持。关于automation tag 的功能在rfc3840中定义,关于byeless tag 的支持在rfc4235中定义。rfc3840定义了媒体服务器的能力支持,rfc4235定义了自动对话事件包管理机制。具体的细节读者可以参考链接资源。以下是一个完整的音乐等待的呼叫流程,配合了SIP消息。我们根据此图例来进一步说明具体的呼叫流程。

首先是Alice对Bob发送INVITE消息(F1),表示要对Bob进行呼叫。

Bob对Alice发送180 振铃消息(F2):

紧接着,Bob对Alice发送200 ok消息(F3):

Alice对Bob发送确认ACK(F4),开始语音流传输通话。

之后,Bob把Alice呼叫设置为语音等待。Bob重新发送一个新的INVITE携带了SDP,并且包含了一个a=sendonly,表示等待开启。执行F5流程。

然后,Alice回复Bob 200 OK消息(F6),在SDP中增加了a=reconly 表示接受等待。

Bob回复Alice确认ACK,无RTP语音流。此时,Bob准备开始执行音乐媒体流服务。

Bob对媒体服务器发送REFER消息,通知媒体服务器使用Alice替换Bob。

媒体服务器对Bob发送202 消息,表示接受这个请求(F9)。

然后媒体服务器发送Notify消息(F10):

Bob发送200 OK(F11):

接下来,媒体服务器对Alice发送INVITE消息,替换Bob(F12),注意这里的SIP消息中增加了渲染功能的支持,包括automation和byeless功能标签,需要启用事件包处理,媒体服务器能力支持等渲染功能。

以上图例中没有显示contact中的渲染功能标签,但是在RFC5359中的音乐等待(F12)中的消息细节是:
F12 INVITE Music Server -> Alice
INVITE sips:a8342043f@atlanta.example.com;gr SIP/2.0
Via: SIP/2.0/TLS server.example.com:5061
;branch=z9hG4bK74rf
Max-Forwards: 70
From: <sips:music@server.example.com>;tag=0111
To: <sips:a8342043f@atlanta.example.com;gr>
Call-ID: a5-75-34-12-76@server.example.com
CSeq: 1 INVITE
Referred-By: <sips:bob@biloxi.example.com> Contact: <sips:music@server.example.com>;automaton
;+sip.byeless;+sip.rendering="no"
Require: replaces
Replaces: 12345600@atlanta.example.com
;from-tag=23431;to-tag=1234567
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY
Supported: replaces
Content-Type: application/sdp
Content-Length: …
Alice接受媒体服务器的请求,对媒体服务器发送200 OK(F13):

媒体服务器收到200 OK以后,对Alice发送确认ACK消息(F14),然后对Alice发送音乐媒体流,Alice现在可以听到媒体服务器对Alice播放的音乐文件。

因为已经播放媒体流流程开始,Alice对Bob发送BYE消息(F16):

Bob接受来自于Alice的BYE消息,对Alice发送200 OK(F16)。

媒体服务器对Bob发送NOTIFY消息(F17),表示媒体播放成功,并且包含一个200 OK的响应消息。

Bob对媒体服务器响应了一个200 OK(F18),表示收到此提示,同时包含了dialog的确认内容,包括了REFER需要的call-id,to tga和from tag。

到此为止,Alice被完全驻留在媒体服务器的会话中。接下来,Bob可能需要重新接听Alice的电话,那么,Bob就会重新对Alice发送INVITE请求消息(F19),然后替换会话中的媒体服务器。

Alice对Bob回复200 OK消息,表示接受替换,重新恢复到通话状态(F20)。

Bob最后对Alice回复确认ACK(F21),可以恢复正常通话状态。

双方通话以后,因为媒体服务器仍然和Alice有会话的绑定关系,因此为了结束媒体播放,Alice仍然需要对媒体服务器发送一个BYE消息,表示音乐等待播放结束(F22):

媒体服务器收到200 OK以后,对Alice发送一个最后的200 OK(F23),告知媒体服务器已经收到Alice的响应,媒体服务器正式释放被驻留在媒体服务器的会话,解除Alice对媒体服务器的绑定关系。Bob和Alice的正常通话才算成功完成,双方开始正式的通话过程。

在音乐等待的处理流程中使用了REFER的method来帮助处理音乐等待,具体的RFER规范在RFC3515中定义,读者可以查阅学习。
我们的讨论中使用了一般的IPPBX媒体服务器来替换音乐媒体服务器,用户也可以通过第三方的音乐服务的服务器端来处理音乐文件,用户使用过程中可能可以获得更多的体验。另外,很多媒体服务器也可以对其播放文件实现自定义处理。例如,在Asterisk/FreePBX或者FreeSWITCH开源平台都可以通过修改配置文件来实现自定义的MoH文件支持。
在上面的讨论中,我们仅根据呼叫流程的正常状态说明的整个MoH的处理过程。事实上,在MOH的实际部署过程中,读者会遇到很多的其他的技术问题。例如,播放文件的格式支持问题,终端兼容性问题,语音播放的带宽消耗问题,音乐播放的服务会话的管理问题,回复消息失败问题,安全问题等。所以,一般的MoH功能仅在内网环境下使用一般不会出现问题,如果通过第三方的媒体平台提供所谓的比较灵活的媒体播放业务,读者一定要注意以上问题。
参考资料:
https://www.rfc-editor.org/rfc/rfc5359.txt
https://tools.ietf.org/html/rfc7088
https://www.rfc-editor.org/rfc/rfc3515.txt
https://tools.ietf.org/html/rfc3840
https://tools.ietf.org/html/rfc3891
https://support.sonus.net/display/SBXDOC51/GRUU+Support
www.freepbx.org.cn
https://svn.resiprocate.org/viewsvn/resiprocate/main/resip/recon/MOHParkServer/doc/MOHParkServer_User_Documentation.pdf?revision=8937&view=co
http://ijsetr.com/uploads/463152IJSETR13872-273.pdf
https://tools.ietf.org/html/rfc3665
https://tools.ietf.org/html/rfc3265
https://tools.ietf.org/html/rfc3515
https://tools.ietf.org/html/rfc4317
关注微信公众号:asterisk-cn,获得有价值的Asterisk行业分享
Asterisk freepbx 中文官方论坛:http://bbs.freepbx.cn/forum.php
Asterisk freepbx技术文档: www.freepbx.org.cn
融合通信商业解决方案,协同解决方案首选产品:www.hiastar.com
Asterisk/FreePBX中国合作伙伴,官方qq技术分享群(3000千人):589995817