问题:1002分机与1001分机正在通话,此时1003分机打给1001,怎么让1003分机知道1001正忙,拨一段语音,diaplan要怎么配置?

类似的问题有很多同学问到,这里,我们来看一下解决方案。

在传统的PSTN电话中,一个电话只能接听一路呼叫,如果被叫忙,主叫就会听到忙音。而在SIP电话中,大多数的SIP话机或者软电话都可以支持多路通话,所以,被叫一般不会那么“忙”。但,总是有些人怀念原来的习惯,希望SIP电话也跟以前用的电话表现起来一模一样。

最理想的解决方案,就是什么都不干。如A通过FS呼叫B,在B忙的情况下,B的终端会回`486 BUSY HERE` SIP消息,FS收到后转发给A,A收到`486`消息,播放指定的声音(这个声音可以在A的客户端配置,由于SIP终端本身就是智能终端,这不是什么事)。

然后,现实世界总是不那么理想。尤其是,现实世界是多样的。比方说,A可能是个PSTN话机,这样的话,就需要依赖FS给A播放一段声音。

好吧,我们继续尝试其实的解决方案。其实解决该问题,最简单的办法我们曾经讲过(参见『阅读原文』)。找一个仅支持一路呼叫的SIP话机,如果第二路呼叫进来,话机就会拒绝,并发送486(代表忙)SIP消息。在FreeSWITCH中就能收到USER_BUSY的挂机原因,然后,……

说到这里,还有没有其它的解决方案呢?当然有,只有想不到,没有做不到。

FreeSWITCH提供了一个`limit` App,专门做限制。当然,要理解`limit`,还需要多了解FS的一些基础知识。

好吧,我们先来做个实验。对于本节的问题,我们做如下Dialplan:

<extension name="busy">
      <condition field="destination_number" expression="^(100[1-3])$">
        <action application="bridge" data="user/$1"/>
      </condition>
    </extension>

上面这个Dialplan大家都比较熟悉了,当1002呼叫1001时,使用`bridge`把两者桥接起来。

好了,祭出我们的`limit`大神。`limit`的语法如下:

limit <backend> <realm> <resource> <max[/interval]> [<transfer_destination_number> [<dialplan> [<context>]]

其中,`backend`是`limit`的后台,可以是`hash`(存在内存的哈希表里),`db`(存在数据库里)以及`redis`(存在redis里)等;而`realm`是一个域,可以是任意值,在多租户环境下,一般用当前的`domain`;`resource`表示对哪些资源进行限制,可以是一个分机号;`max`是限制的最大值,后面有个可选的`interval`,表示在多长时间内该最大值有效;`transfer_destination_number`、`dialplan`、`context`是可选的,表示,如果超出限制,要`transfer`到哪个Dialplan。

参照上面的语法,我们做如下Dialplan:

<extension name="busy">
      <condition field="destination_number" expression="^(100[1-3])$">
        <action application="limit" data="hash ${domain} $1 1 user_busy XML default"/>
        <action application="bridge" data="user/$1"/>
      </condition>
    </extension>

<extension name="busy">
      <condition field="destination_number" expression="^user_busy$">
        <action application="playback" data="user_busy.wav"/>
      </condition>
    </extension>

有了上述Dialplan,当有用户呼叫`1001`时,会先执行`limit`,对当前的被叫号码`1001`的资源占用数加`1`。如果在通话过程中用第二个电话呼叫`1001`,则由于超出了资源限制,系统会自动转接到`user_busy`处,播放一个用户忙的语音提示 `user_busy.wav`。

细心的读者可能发现,其实我们上面做的不够全面。如果`1002`呼叫`1001`,那么,当有用户呼叫主叫号码`1002`时,也应该播放忙音。原来的问题没有说明`1001`到底是主叫还是被叫,这是提问者提的不够完善的地方,不过,无论如何,我们可以同时用两个limit限制两个资源,如:

<action application="limit" data="hash ${domain} $1 1 user_busy XML default"/>
    <action application="limit" data="hash ${domain} ${caller_id_number} 1 user_busy"/>

好了,打个电话,我们可以在日志里看到类似如下的内容:

[DEBUG] switch_limit.c:126 incr called: 192.168.7.6_1002 max:1, interval:0
    [DEBUG] mod_hash.c:196 Usage for 192.168.7.6_1002 is now 1/1
    [DEBUG] switch_limit.c:126 incr called: 192.168.7.6_1001 max:1, interval:0
    [DEBUG] mod_hash.c:196 Usage for 192.168.7.6_1001 is now 1/1

挂断电话,看到资源被释放了:

[DEBUG] mod_hash.c:297 Usage for 192.168.7.6_1002 is now 0
    [DEBUG] mod_hash.c:297 Usage for 192.168.7.6_1001 is now 0

在上述解决方案中,如果主被叫都是在内网上,当然是没有问题的。但是,如果主叫是PSTN呼入的,一般的运营商不允许你在应答(`answer`)前播放语音(即它们不会透传Early Media),所以,你需要在`playback`前加上一个`answer`,这是运营商的限制。不过,加了`answer`以后又破坏了这么做的语义,本来你是想在应答之前通过Early Media通知主叫被叫忙,电话打不通本来不应该收费的,加了`answer`会触发计费。

所以,如果你有PSTN的主叫的话,你可以尝试直接在SIP中返回用户忙,由运营商来给主叫用户播放忙音提示。Dialplan如下:

<extension name="busy">
      <condition field="destination_number" expression="^user_busy$">
        <action application="respond" data="486"/>
      </condition>
    </extension>

部分日志供参考:

```
[INFO] mod_hash.c:183 Usage for 192.168.7.6_1002 is already at max value (1)
[NOTICE] switch_ivr.c:2167 Transfer sofia/internal/1000@192.168.7.6 to XML[user_busy@default]
Dialplan: sofia/internal/1000@192.168.7.6 parsing [default->busy] continue=false
[DEBUG] switch_core_state_machine.c:328 sofia/internal/1000@192.168.7.6 Standard EXECUTE
EXECUTE sofia/internal/1000@192.168.7.6 respond(486)
[DEBUG] switch_core_state_machine.c:60 sofia/internal/1000@192.168.7.6 Standard HANGUP, cause: USER_BUSY
send 869 bytes to udp/[192.168.7.6]:16664 at 14:37:53.273916:
   ------------------------------------------------------------------------
   SIP/2.0 486 Busy Here
```

在本文完成后,笔者又发现了另一种用法。如果最后只是返回USER BUSY,不用单独写一个Dialplan Extension,而是直接在`limit`的参数中写上即可,如:

<action application="limit" data="hash ${domain} $1 1 !USER_BUSY"/>

注意,USER_BUSY前面应该有个叹号。

freeswitch被叫忙处理相关推荐

  1. FreeSWITCH在呼叫失败的情况下如何播放语音提示

    看到好多网友问到这个问题.一般我们在打电话时会听到"您拨的电话正在通话中,请稍后再拨....",或"电话无应答..."之类的提示,我们在 freeswitch ...

  2. Hello, FreeSWITCH(1)VoIP 基础

            笔者最近刚开始接触 FreeSwitch.作为炮灰级别的程序员,适时地写一些日志巩固一下还是很有必要的.         另外推荐一本入门书籍<FreeSWITCH 权威指南&g ...

  3. 《FreeSWITCH: VoIP实战》:PSTN 与 PBX 业务

    PSTN 业务 POTS 除为用户提供基本的话音通话外,PSTN 还能提供一些附加的业务,这些业务在国外称为普通老式电话业务(POTS,Plain Old Telephone Service),而在国 ...

  4. PSTN 与 PBX 业务

    在继续学习 FreeSWITCH 之前,我们有必要了解一下传统的电话网所能提供的服务.这些服务有的是你已经熟悉的,有的也可能没听说过.有一些业务在 VoIP 中实现起来就异常简单,而有一些业务已经不需 ...

  5. Dialplan 编程基础

    Dialplan编程其实是在extensions.conf文件中来完成的.主要目的就是完成对来电和去电的处理.所有的代码都是在一个"context"下面 以"exten ...

  6. 405 not allowed怎么解决_英语口语:“您拨叫的用户不在服务区”这类电话常用语怎么说...

    1.空号: 中文:您好!您所拨打的号码是空号,请核对后再拨. 英文:Sorry! The number you dialed does not exist, please check it and d ...

  7. sip协议呼叫流程详解

    1.SIP业务基本知识 1.1 业务介绍 会话初始协议(Session Initiation Protocol)是一种信令协议,用于初始.管理和终止网络中的语音和视频会话,具体地说就是用来生成.修改和 ...

  8. 国标28181:什么是SIP协议

    前言 对讲设备作为一种专业无线通信工具,能进行一对一,多对多的群组即时通信,在应急调度和突发事故处理中是其他通信工具所不能替代的,在城市治理.公安.运输等行业有广泛的应用. 对讲机按照通信方式分模拟对 ...

  9. CAP MAP VLR HLR GMSC DP gsmSSF简介

    CAMEL:  Customized Applications for Mobile network Enhanced Logic CAP:    CAMEL Applicaiton Part   归 ...

  10. html 提示语为英文,耳熟能详的电话提示语英文版

    [导语]想必大家都遇到过电话打不通的情况,这时优美的女声语音提示就出场了.但是英文版的电话提示语说的都是什么你知道吗? 1.空号: Sorry! The number you dialed does ...

最新文章

  1. 屠龙之路_战胜View对DataBase猛烈进攻_ThirdDay
  2. 大剑无锋之DQL、DML、DDL、DCL,简单举个例子【面试推荐】
  3. 汇总:一些不错的使用频率比较高的JS函数
  4. html5在zigbee中起什么作用,ZigBee是什么?ZigBee在智能家居中扮演什么角色
  5. iOS DLNA
  6. python全栈工程师培训_2018.03《Python3全栈工程师》_技术能力内训
  7. fingerprint模块管理指纹识别
  8. 中国联通家庭网关破解管理员账户
  9. 任务栏文件资源管理器打开特别卡
  10. Uva 437 巴比伦塔  UVA10003
  11. DNS服务器ttl修改不生效,中科三方DNS专家手把手教学——定位域名解析不生效问题...
  12. Django——创建数据库和表
  13. java数组重置_Java:如何重置数组列表,使其为空
  14. mac服务器文件夹权限设置密码,如何在Mac os优胜美地给文件和文件夹加密
  15. Abstract Factory模式(抽象工厂模式)
  16. Imagenomic Portraiture 2.3 Key
  17. 小米、华为、联想数据分析
  18. 微信小程序(应用号)开发新闻客户端的实战课程
  19. 软件测试简历,别再做无用的简历了
  20. Cocos论坛九问九答

热门文章

  1. Visual Studio 2010添加新项缺失[ADO.NET 实体数据模型]解决方法
  2. 【原】创建 WPF 不规则窗口
  3. 要么战胜,要么战死,绝不投降
  4. PRM–endRequest事件
  5. DataSet与XML导入导出方法
  6. python垃圾回收机制gcgo_python垃圾处理机制
  7. 在Java中如何高效判断数组中是否包含某个元素
  8. PostgreSQL on Docker部署是的shm配置注意
  9. Silverlight提示“Load 操作失败。远程服务器返回了错误: NotFound”
  10. 一道容易栽坑的有趣的面试题(关于js,定时器,闭包等)