FreeSwitch呼入处理流程

        为了简单起见,本文分析一个单边呼叫。让终端呼入到FS,然后播放一个文件就退出,不执行FS的呼出动作。参考拨号方案:

    <extension name="fs_one_way_inbound">
      <condition field="destination_number" expression="^10086$">
        <action application="sleep" data="1000 "/>
        <action application="answer"/>
        <action application="playback" data="ivr/8000/ivr-welcome_to_freeswitch.wav"/>
      </condition>
    </extension>

        Sofia栈捕获INVITE消息后,处理100 Trying,调用模块初始化时注册的回调函数sofia_event_callback()。处理新的INVITE请求,首先调用switch_core_session_request_uuid()实例化Session对象,同时实例化Channel对象,并把Channel状态初始化为CS_NEW,激活通道处理线程。

        Sofia栈进一步处理INVITE消息,抛出nua_i_invite事件通报事件进展,这时驱动状态机变化,状态机由CS_NEW状态迁移到CS_INIT状态。最终由状态机核心代码里的switch_core_standard_on_init()驱动状态迁移到CS_ROUTING。进而执行核心回调switch_core_standard_on_routing(),这个函数执行拨号方案的定位与查找,记录一个todo list,查找结束后,状态迁移到CS_EXECUTE。核心回调switch_core_standard_on_execute()挨个执行前一步todo list的APP。执行answer时,会触发 SIP的200 OK消息发出;当执行完最后一条APP后,触发一个hangup,即发SIP BYE消息。

        后续的状态迁移省略。

 

说明:呼叫状态机会调用所有注册的状态回调函数,上图中仅体现推动状态迁移的关键调用。

<think>我们正在讨论FreeSWITCH中的组呼功能配置,特别是主叫方的配置。根据之前的引用,我们知道EndPoints是FreeSWITCH与外部通信的接口,而拨号计划是控制呼叫路由的核心。组呼(GroupCall)通常指的是一个主叫同时呼叫多个被叫,并建立会议或群聊。在FreeSWITCH中,实现组呼的一种常见方法是通过拨号计划(dialplan)来配置。我们可以创建一个扩展(extension),当主叫拨打该扩展时,FreeSWITCH将主叫和多个被叫加入到一个会议室(conference)中,或者依次呼叫多个被叫(串行或并行)。下面我们介绍两种常见的组呼实现方式:1.**会议模式(Conference)**:将主叫和多个被叫加入同一个会议室,实现多方通话。2.**桥接模式(Bridging)**:主叫依次或同时呼叫多个被叫,将每个被叫桥接到主叫的通话中。###1.会议模式配置示例在会议模式中,我们可以预先定义一个会议室,然后让主叫和被叫都进入该会议室。主叫拨打一个特定的号码(如`3000`)进入会议室,同时我们需要在拨号计划中设置呼叫多个被叫并将它们也加入同一个会议室。在拨号计划中,我们可以这样配置(在`dialplan/default.xml`中):```xml<extensionname="group_call_conference"><conditionfield="destination_number"expression="^(3000)$"><actionapplication="answer"/><!--首先将主叫加入会议室--><actionapplication="conference"data="$1-${domain}@default"/><!--同时,我们需要在后台呼叫其他成员并加入会议室--><!--这里可以使用`bgdial`或者通过其他方式实现,但通常会议模式需要被叫主动加入,或者通过外呼邀请--><!--所以,更常见的是让主叫进入会议室后,再通过拨号计划外呼被叫并加入会议室--></condition></extension>```但是,上述配置只能让主叫加入会议室,我们还需要呼叫其他成员。我们可以使用`<actionapplication="bridge">`来同时呼叫多个被叫,并执行一个脚本(比如Lua脚本)将每个被叫加入会议室。或者,我们可以使用`<actionapplication="transfer">`将主叫转移到会议,然后使用`session.execute("bgdial",...)`来后台呼叫被叫并加入会议。然而,更简单的方法是使用`conference`的`dialout`功能。在会议配置中,可以设置当有人加入会议时自动呼叫其他成员。但这种方式通常需要提前配置会议成员。另一种方法是使用Lua脚本实现更灵活的控制。例如,我们可以在拨号计划中调用一个Lua脚本来完成外呼并加入会议室的逻辑。###2.桥接模式(串行或并行呼叫)在桥接模式中,我们可以使用FreeSWITCH的`bridge`应用同时呼叫多个被叫(并行)或者依次呼叫(串行)。当任一被叫接听时,将其与主叫桥接。但是,组呼通常需要多个被叫同时加入,因此并行桥接更常用。并行桥接配置示例(在`dialplan/default.xml`中):```xml<extensionname="group_call_bridge"><conditionfield="destination_number"expression="^(4000)$"><actionapplication="answer"/><!--并行呼叫多个被叫,使用逗号分隔的呼叫字符串--><actionapplication="bridge"data="user/1001,user/1002,user/1003"/></condition></extension>```注意:并行桥接时,所有被叫将同时振铃,第一个接听的被叫会与主叫通话,其他被叫的通话会被取消。这通常是组呼(多方通话)的需求,因为组呼需要多个被叫同时参与。因此,要实现真正的多方通话,会议模式是更合适的选择。###针对主叫的配置在组呼中,主叫方通常需要特殊配置,只需要拨打一个特定的号码(如上述的3000或4000)即可触发组呼。但是,我们可能需要对主叫进行身份验证或设置其他参数(如呼叫超时等)。在拨号计划中,我们可以通过设置变量或条件判断来对主叫进行控制。例如,只允许特定主叫发起组呼:```xml<extensionname="group_call_auth"><conditionfield="destination_number"expression="^(3000)$"><!--检查主叫号码是否在允许的列表中--><conditionfield="${caller_id_number}"expression="^(1000|1001|1002)$"break="on-true"><actionapplication="conference"data="$1-${domain}@default"/></condition><!--如果在列表中,可以播放提示音并挂断--><conditionfield="${caller_id_number}"expression="^.*$"><actionapplication="playback"data="ivr/ivr-call_rejected.wav"/><actionapplication="hangup"/></condition></condition></extension>```###使用Lua脚本实现更复杂的组呼对于更复杂的需求,比如动态获取组呼成员,我们可以使用Lua脚本来实现。例如,从数据库或API获取组呼成员列表,然后逐个呼叫并将他们加入会议室。下面是一个简单的Lua脚本示例(`group_call.lua`):```luasession:answer()--获取主叫号码localcaller_id=session:getVariable("caller_id_number")--假设根据主叫号码获取组呼成员列表(这里简化,直接写死)localmembers={"1001","1002","1003"}--主叫加入会议室session:execute("conference","group1@default")--后台呼叫每个成员并加入会议室for_,memberinipairs(members)dosession:execute("bgdial","sofia/internal/"..member.."@$${domain},conference:group1@default")end```在拨号计划中调用该脚本:```xml<extensionname="group_call_lua"><conditionfield="destination_number"expression="^(5000)$"><actionapplication="lua"data="group_call.lua"/></condition></extension>```###注意事项-在并行呼叫多个被叫时,注意系统的并发呼叫限制。-确保会议室配置(`conference`)正确,例如在`autoload_configs/conference.conf.xml`中定义了`default`会议室模板。-组呼可能会占用较多系统资源,需要合理规划。###总结在FreeSWITCH中配置组呼(主叫方)主要涉及拨号计划的设置,可以选择会议模式或桥接模式。会议模式更适合多方通话,而桥接模式通常用于呼叫转移。通过拨号计划的条件判断,我们可以对主叫进行权限控制。对于复杂场景,可以使用Lua脚本实现动态组呼。[^1]:FreeSWITCH中的EndPoints和拨号计划[^2]:FreeSWITCH入门到精通系列(一):什么是FreeSWITCH?§§相关问题§§1.如何在FreeSWITCH中配置会议室的参数(如最大成员数、静音设置等)?2.如何通过数据库动态管理组呼的成员列表?3.FreeSWITCH中如何实现组呼的录音功能?</think>### FreeSWITCH 组呼功能的主叫方配置指南 在 FreeSWITCH 中实现组呼功能(Group Call)时,主叫方的配置核心是通过拨号计划(Dialplan)控制呼叫流程。以下是关键配置步骤: #### 1. **创建组呼拨号计划** 在 `dialplan/default.xml` 中添加扩展规则,当主叫拨打特定号码时触发组呼: ```xml <extension name="group_call"> <!-- 匹配组呼接入码(如 888) --> <condition field="destination_number" expression="^888$"> <!-- 应答主叫 --> <action application="answer"/> <!-- 同时呼叫多个目标(组呼成员) --> <action application="bridge" data="{ignore_early_media=true}user/1001,user/1002,user/1003"/> <!-- 可选:呼叫失败处理 --> <action application="log" data="WARNING Group call to ${destination_number} failed"/> </condition> </extension> ``` #### 2. **主叫权限控制** 在 `directory/default.xml` 中限制主叫权限,确保只有授权用户可发起组呼: ```xml <user id="caller_101"> <params> <!-- 允许拨打组呼号码 888 --> <param name="dialplan" value="(888|SIP/.+)"/> </params> </user> ``` #### 3. **动态组呼配置(使用 Lua 脚本)** 通过脚本动态获取组呼成员列表(如从数据库): 1. 创建脚本 `group_call.lua`: ```lua session:answer() members = {"1001", "1002", "1003"} -- 从数据库/API获取 bridge_string = table.concat(members, ",") session:execute("bridge", bridge_string) ``` 2. 在拨号计划中调用: ```xml <action application="lua" data="group_call.lua"/> ``` #### 4. **主叫定制化体验** - **等待提示音**: ```xml <action application="playback" data="custom_music.wav"/> ``` - **呼叫状态通知**: ```xml <action application="speak" data="您正在发起组呼,请稍候"/> ``` #### 5. **重要参数说明** | 参数 | 作用 | |-----------------------|----------------------------------------------------------------------| | `ignore_early_media` | 忽略早期媒体,避免部分应答导致组呼失败 | | `group_confirm_key` | 主叫确认键(如按1开始组呼) | | `call_timeout` | 设置呼叫超时(秒) | #### 6. **调试命令** ```bash # 查看主叫呼叫状态 fs_cli> show calls # 检查拨号计划匹配 fs_cli> originate user/1000 888 ``` ### 常见问题处理 1. **主叫听回铃音太久** 添加 `ringback=${us-ring}` 参数或设置超时: ```xml <action application="set" data="call_timeout=20"/> ``` 2. **部分成员无法接通** 使用 `continue_on_fail=true` 参数: ```xml <action application="bridge" data="{continue_on_fail=true}user/1001,user/1002"/> ``` 3. **主叫需按键确认** 在呼叫前添加菜单: ```xml <action application="read" data="1 1 3 5000 # press 1 to confirm"/> ``` [^1]: FreeSWITCH 通过拨号计划控制呼叫路由,组呼本质是多目标桥接 [^2]: 权限控制需在用户目录中配置呼叫权限规则
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值