要把 FreeSWITCH 之 chat 完全研究清楚,似乎不容易
发送,路由,接收
跟哪些模块有关
等等
咱一边查资料,一边整理,不着急
先看看 Kamalio 怎么发 MESSAGE
loadmodule "uac.so"
route[uac_send_message] {
$uac_req(method) = "MESSAGE";
$uac_req(ruri) = "sip:10.0.1.5:5060";
$uac_req(furi) = "sip:Emergency Alert";
$uac_req(turi) = "sip:thisphone";
# $uac_req(callid) =
$uac_req(hdrs) = "Subject: Emergency Alert\r\n";
$uac_req(hdrs) = $uac_req(hdrs) + "Content-Type: text/plain\r\n";
$uac_req(body) = "hi\r\n";
$uac_req(evroute) = 1; # fire 路由,成功不成功,在路由块里面可以获取到
uac_req_send();
}
event_route[uac:reply] {
xinfo("===uac reply received, callid = $uac_req(callid), tu = $uac_req(turi), code = $uac_req(evcode)\n");
}
也可以设置 outbound proxy
$uac_req(ouri) = "sip:1.2.3.4:5060";
现在来看看 FS 怎么发送 MESSAGE
当然,首先得加载 mod_sms
local event = freeswitch.Event("CUSTOM", "SMS::SEND_MESSAGE");
event:addHeader("proto", "sip");
event:addHeader("dest_proto", "sip");
event:addHeader("from", "1004@192.168.0.81");
event:addHeader("from_full", "sip:1004@192.168.0.81");
event:addHeader("to", "sip:1001@192.168.31.73:6666");
event:addHeader("subject", "12345678abcd");
event:addHeader("type", "text/plain");
event:addHeader("hint", "the hint");
event:addHeader("replying", "true");
event:addHeader("sip_profile", "internal");
event:addBody("Hi\r\n");
freeswitch.consoleLog("info", event:serialize());
event:fire();
如此就可以发送,目的地址是 sip:192.168.31.73:6666, 后者运行的是 MircoSIP, 配置文件里面设置 sourcePort=6666,会自动弹一个框出来,显示 `Hi`
fs_cli -x 'show chat'
show chat
type,name,ikey
chat,GLOBAL_SMS,mod_sms
chat,api,mod_dptools
chat,conf,mod_conference
chat,event,mod_dptools
chat,sip,mod_sofia
chat,verto,mod_verto6 total.
哈哈,很清楚了
dest_proto 如果为 sip,那么 mod_sofia 来处理 chat 发送
dest_proto 如果为 verto,那么 mod_verto 来处理 chat 发送
以此类推,可以发到 会议,会议里面可以 chat, FS 的设计好牛
发送之后怎么看结果呢,怎么看 reply ?
答案是 SMS::DELIVERY_REPORT 子类,主键应该是 subject
下面是二个事件:
RECV EVENT
Event-Subclass: SMS::SEND_MESSAGE
Event-Name: CUSTOM
Core-UUID: b98d6556-a3cb-4b2b-8cca-a83386abbcfd
FreeSWITCH-Hostname: debian12
FreeSWITCH-Switchname: debian12
FreeSWITCH-IPv4: 192.168.31.213
FreeSWITCH-IPv6: ::1
Event-Date-Local: 2025-03-09 19:36:34
Event-Date-GMT: Sun, 09 Mar 2025 11:36:34 GMT
Event-Date-Timestamp: 1741520194385173
Event-Calling-File: switch_cpp.cpp
Event-Calling-Function: Event
Event-Calling-Line-Number: 315
Event-Sequence: 940
proto: sip
dest_proto: sip
from: 1004@192.168.0.81
from_full: sip:1004@192.168.0.81
to: sip:1001@192.168.31.73:6666
subject: 12345678abcd
type: text/plain
hint: the hint
replying: true
sip_profile: internal
skip_global_process: true
dest_proto: sip
Nonblocking-Delivery: true
skip_global_process: true
Content-Length: 4
Content-Length: 4Hi
RECV EVENT
Event-Subclass: SMS::DELIVERY_REPORT
Event-Name: CUSTOM
Core-UUID: b98d6556-a3cb-4b2b-8cca-a83386abbcfd
FreeSWITCH-Hostname: debian12
FreeSWITCH-Switchname: debian12
FreeSWITCH-IPv4: 192.168.31.213
FreeSWITCH-IPv6: ::1
Event-Date-Local: 2025-03-09 19:36:34
Event-Date-GMT: Sun, 09 Mar 2025 11:36:34 GMT
Event-Date-Timestamp: 1741520194385173
Event-Calling-File: mod_sms.c
Event-Calling-Function: send_report
Event-Calling-Line-Number: 48
Event-Sequence: 941
Status: Accepted
Core-UUID: b98d6556-a3cb-4b2b-8cca-a83386abbcfd
FreeSWITCH-Hostname: debian12
FreeSWITCH-Switchname: debian12
FreeSWITCH-IPv4: 192.168.31.213
FreeSWITCH-IPv6: ::1
Event-Date-Local: 2025-03-09 19:36:34
Event-Date-GMT: Sun, 09 Mar 2025 11:36:34 GMT
Event-Date-Timestamp: 1741520194385173
Event-Calling-File: switch_cpp.cpp
Event-Calling-Function: Event
Event-Calling-Line-Number: 315
Event-Sequence: 940
proto: sip
dest_proto: sip
from: 1004@192.168.0.81
from_full: sip:1004@192.168.0.81
to: sip:1001@192.168.31.73:6666
subject: 12345678abcd
type: text/plain
hint: the hint
replying: true
sip_profile: internal
skip_global_process: true
dest_proto: sip
Nonblocking-Delivery: true
skip_global_process: true
请关注 subject 和 Status
另外,我目前测试的结果是,如果要获得准确的 Status,那么需要传 blocking 为 true,但我不确定我的测试结果是否 OK
请参考下面这段代码:
local event = freeswitch.Event("CUSTOM", "SMS::SEND_MESSAGE");
event:addHeader("proto", "sip");
event:addHeader("dest_proto", "sip");
event:addHeader("from", "1004@192.168.0.81");
event:addHeader("from_full", "sip:1004@192.168.0.81");
event:addHeader("to", "sip:1001@192.168.31.73:6666");
event:addHeader("subject", "12345678abcd");
event:addHeader("type", "text/plain");
event:addHeader("hint", "the hint");
event:addHeader("replying", "true");
event:addHeader("sip_profile", "internal");
event:addHeader("blocking", "true"); -- vip
event:addBody("Hi\r\n");
freeswitch.consoleLog("info", event:serialize());
event:fire();
把 MicroSIP 关闭掉
fs_cli
console loglevel 0
/event plain all
运行上面的 lua 程序
过一会就能收到 DELIVERY_REPORT 事件,Status 为 Failure
要怎么设置 proxy呢?
笔者查了半天资料,终于找到了答案,可参考下面这个头:
contact-uri: sip:1002@192.168.0.99:11710;fs_path=sip:192.168.207.156:5060
重点是不要加 `<>`,加了就不好使
我查的资料讲的是发送 SIP NOTIFY 消息,那么发送SIP MESSAGE是否也如此
目前我还没进行测试
或者干脆增加 to_sip_ip 和 to_sip_port 参数
如何处理 chat 接收呢?
回答是 chatplan
我的习惯是先修改 sip profile, 增加一个 auth-messages = false 的配置,不然FS在收到 SIP MESSAGE 请求时会要求SIP 挑战,很麻烦
chatplan 里面能做什么?
mod_sms 有下面几个 app:
show modules mod_sms
type,name,ikey,filename
application,final,mod_sms,/usr/local/freeswitch/mod/mod_sms.so
application,fire,mod_sms,/usr/local/freeswitch/mod/mod_sms.so
application,info,mod_sms,/usr/local/freeswitch/mod/mod_sms.so
application,reply,mod_sms,/usr/local/freeswitch/mod/mod_sms.so
application,send,mod_sms,/usr/local/freeswitch/mod/mod_sms.so
application,set,mod_sms,/usr/local/freeswitch/mod/mod_sms.so
application,stop,mod_sms,/usr/local/freeswitch/mod/mod_sms.so
application,system,mod_sms,/usr/local/freeswitch/mod/mod_sms.so
application,unset,mod_sms,/usr/local/freeswitch/mod/mod_sms.so
chat,GLOBAL_SMS,mod_sms,/usr/local/freeswitch/mod/mod_sms.so
目前我没有一个一个进行研究
这是自带的 chatplan:
<?xml version="1.0" encoding="utf-8"?>
<include>
<context name="default">
<extension name="demo">
<condition field="to" expression="^(.*)$">
<!-- <action application="lua" data="test.lua"/> -->
<action application="reply" data="Hello, you said: ${body}"/>
</condition>
</extension>
</context>
</include>
lua 要怎么写呢?
对象不再是 session, 而是 message, message 有哪些方法呢?
- chat_send
- chat_execute
- setPriority
- addBody
- fire
- getType
- getHeader
- addHeader
- merge
- serialize
- getBody
下面是一个简单的 test.lua:
message:chat_execute("info")
message:chat_execute("final")
消息落地 ,不再转发,回 202
上面讲的是发送对话外 MESSAGE
那么对话内 MESSAGE 要怎么发送呢?
要研究下,除了 uuid_chat 是否还有别的?
mod_dptools 里面有个叫 chat 的 api, 很多资料都讲过了,这里不再赘述
其实弄了半天我发现自己还是没完全搞明白,以后再研究吧