让 7101 打给 7102。7102 接起,双方说一句话,再挂断。在旁边的终端里,应该能看到接听、桥接和挂断完成三类事件,并能用通道 UUID 对上两条腿。上一期从落盘话单查结果,这一期看这些变化什么时候发生。测试用同一台内网 FreeSWITCH,两个 SIP 分机已注册且能互拨。
配好本机的 ESL 入口
ESL 是 Event Socket 的接口。这里用 inbound 模式,终端上的 fs_cli 主动连 FreeSWITCH。拨号计划里还有一种由 FreeSWITCH 主动连接应用的 outbound 模式,这个实验不需要新增拨号计划。
用现有控制台运行 global_getvar conf_dir,确认真正的配置根目录。如果旧控制台已经不可用,从服务启动参数或安装清单确认目录。备份 autoload_configs/event_socket.conf.xml,再替换成下面的文件。检查 autoload_configs/modules.conf.xml 的启动清单已有 <load module="mod_event_socket"/>,模块由安装包提供。原环境若有其他 ESL 客户端,先记下它们依赖的地址和端口。这个示例适合独立测试机。
<configuration name="event_socket.conf" description="Local ESL">
<settings>
<!-- 监听范围仅限本机 IPv4 回环地址。 -->
<param name="listen-ip" value="127.0.0.1"/>
<param name="listen-port" value="8021"/>
<!-- 使用本机生成的独立强密码替换占位符。 -->
<param name="password" value="REPLACE_WITH_LOCAL_SECRET"/>
<!-- 在认证前检查来源地址,关闭 NAT 端口映射。 -->
<param name="apply-inbound-acl" value="loopback.auto"/>
<param name="nat-map" value="false"/>
</settings>
</configuration>
listen-ip 决定 FreeSWITCH 绑定哪个本地地址。这里写 127.0.0.1,终端也要在 FreeSWITCH 所在的主机或容器网络命名空间里。宿主机的回环地址和容器里的回环地址各归各。vanilla 文件显式使用 ::,实际监听范围比本例宽。改完用系统命令确认最终绑定地址。
listen-port 是 ESL 的 TCP 端口,客户端必须对上。本例使用 8021,SIP 注册和 RTP 音频沿用原来的配置。password 是连接认证使用的共享密码。把占位符换成独立的随机强密码,例如用密码管理器生成的长字母数字串,服务端文件和客户端配置都限制读取权限。ESL 这套认证授权范围较宽,后面只订阅事件是本次客户端的用法。
apply-inbound-acl 在发认证挑战前检查连接来源,loopback.auto 只放行回环。源码里没有配置 ACL 时也会补上这个默认名单,本例显式写出来。若以后应用要跨主机收事件,可以把接收进程放在 FreeSWITCH 本机,再通过受控的内部接口向业务系统转发所需字段。nat-map=false 关闭这里的 NAT 端口映射请求。它和电话经过 NAT 时如何走媒体是两处设置。
常见可选项还有 stop-on-bind-error。v1.11.3 中,绑定失败时该选项打开会退出监听启动路径,关闭时会继续尝试。碰上端口冲突,先从系统监听表和日志确认谁占了端口。debug 会增加模块日志,遇到连接问题可以短时使用,收集够了再恢复。
让 fs_cli 用新的连接配置
在登录 FreeSWITCH 主机的测试账号下,新增 ~/.fs_cli_conf,已有文件就追加一个独立的 esl-lab 节。将权限设为 600,密码换成与服务端一致的实际值。这样运行命令时不用把密码放到参数或终端历史里。
[esl-lab]
host => 127.0.0.1
port => 8021
password => REPLACE_WITH_LOCAL_SECRET
本期在无活跃通话的独立节点通过服务管理器重启,使模块重新读监听配置。重启会中断该节点上的活动通话及现有 ESL 连接,生产节点要在维护窗口处理并预留系统控制台。单跑 reloadxml 不会重新绑定已经运行的监听套接字。以下以 Linux 的 systemd 安装为例,单元名以本机为准。
# 服务单元名按测试机的安装方式调整。
sudo systemctl restart freeswitch
# 查看监听地址,再验证客户端配置能用。
sudo ss -lntp 'sport = :8021'
fs_cli -x 'status' esl-lab
在 ss 的监听表里核对本地地址是 127.0.0.1:8021,再看 status 是否返回 FreeSWITCH 的运行状态。端口能连时,认证仍可能失败,这两项分开验。连接成功后,用 fs_cli esl-lab 打开交互终端,输入以下命令。斜线是 fs_cli 接收这些命令的方式。
/nolog
/event plain CHANNEL_ANSWER CHANNEL_BRIDGE CHANNEL_HANGUP_COMPLETE
/nolog 关掉当前终端的服务器日志流,保留事件输出。订阅用 plain 格式,事件头一行一个键值。应用程序也可按需要选 JSON 或 XML。自己写客户端时,先读完外层头部,再按 Content-Length 的字节数读完整正文。TCP 提供连续字节流,一次读取可能只拿到半条,也可能包含多条。使用现成 ESL 库可以把这部分交给库。
拿 7101 和 7102 的事件对一遍
订阅返回成功后再拨号。让 7102 接起,等两边都说过话再挂断。先看 CHANNEL_ANSWER 对应哪个 Unique-ID,再在 CHANNEL_BRIDGE 里对照两条腿的 UUID,可以看 Bridge-A-Unique-ID、Bridge-B-Unique-ID 或存在时的 Other-Leg-Unique-ID。一条腿的接听和两条腿形成桥接是两个观察点。再到 CHANNEL_HANGUP_COMPLETE 按 UUID 找该腿的 Hangup-Cause。给事件排序时,Event-Date-Timestamp 是 Unix 纪元以来的微秒。
另打一通,7102 响铃时让 7101 取消。按实际建出的通道核对挂断事件,正常的简单直拨取消不应出现两条腿已经桥接的证据。如果入口先经 IVR 接听,仍可能出现入口腿的应答事件。7101 和 7102 是 SIP 分机,队列的 agent、tier、派单结果另查 callcenter::info 等队列事件。开始收集时可以先按三种事件筛,拿到需要的 UUID 再用 /filter Unique-ID <通道UUID> 缩小范围。想比较两条腿时,先去掉这个单腿过滤。
订阅只覆盖建立订阅之后收到的实时事件。采集进程掉线后,重新连接并重订阅,缺口用当前通道查询和落盘话单补查。用单一事件数推算话务量时,还要处理同一通电话的多条腿。以上是验收预期,配置和命令已核对公开模板与源码,未在 FreeSWITCH 实例试跑。
连接失败或没有事件时怎么查
- 连接直接拒绝。用
ss确认模块是否真的监听,检查端口冲突和服务日志。监听地址是回环时,从宿主机连容器或从另一台主机连都到不了这个地址。 - 连接后被拒绝。先区分 ACL 拒绝与认证失败。前者查来源地址和 ACL,后者查是否选中了
esl-lab以及两边密码是否一致。 - 能执行 status,订阅后没输出。确认用了交互会话,订阅有成功应答,再发起新电话。之前加过单腿过滤时,清掉过滤或新开终端复测。
- 事件多,找不到对应话单。先用挂断完成事件的通道 UUID 对上上一期 CSV 的
uuid列,再按业务 ID 汇总。只留排障所需字段,转交日志前脱敏。
收尾时在交互终端取消事件订阅并退出。若要恢复测试节点的监听配置,在无通话时恢复备份文件和原客户端 profile,再重启并确认旧连接恢复。其他 ESL 应用如果需要恢复连接,还要看它们有没有重新订阅。
/noevents
/exit