概述
这篇文章主要小结的是lua中freeswitch.Session在发起呼叫时,针对不同目标的应答结果。
测试由两个freeswitch组成,一个负责外呼,一个负责模拟线路(测试桩)。
主要结论如下:
- 在通过sofia/internal/xxx@xxx呼叫外部用户的时候,需要收到180/183,freeswitch.Session才会结束阻塞状态,返回结果
- 在通过user/1007呼叫内部用户的时候,需要收到200,freeswitch.Session才会结束阻塞状态,返回结果
- 只有在收到180/183之后,session才会被真正初始化。如果直接收到挂断,会有报错“session is not initalized”
- 在通过sofia/internal/xxx@xxx外呼时,session:ready与session:mediaReady()在收到180/183后会变为true
- 呼叫外部用户时,只有对端ip不属于当前网络,并且无法ping通时,才会触发fs的30秒呼叫超时,报错:408 RECOVERY_ON_TIMER_EXPIRE
- 呼叫外部用户时,只有对端ip属于当前网络,但是无法ping通时,会触发fs的立即报错,报错:503 NORMAL_TEMPORARY_FAILUR
测试环境
呼叫方:lua测试代码
```lua local dp_hangup=”sofia/internal/18652005000@172.26.178.70:54601” local dp_hangup1=”sofia/internal/18652004000@172.26.178.70:54601” local dp_keep_ring=”sofia/internal/18652003000@172.26.178.70:54601” local dp_answer=”sofia/internal/18652002000@172.26.178.70:54601” local dp_not_exist_sipserver=”sofia/internal/18652002000@172.26.178.70:54400” local dp_not_exist_ip=”sofia/internal/18652002000@162.26.178.11:54400” local dp_localuser=”user/1007”
function log(content, level) level = level or “debug”; freeswitch.consoleLog(level, argv[0] .. “:” .. content .. “\n”); end
—session= freeswitch.Session(dp_keep_ring) session= freeswitch.Session(dp_not_exist_ip) state = session:getState() hangupState = session:hangupState() or “” log(“>>>>>>>>session:ready() —>(“ .. tostring(session:ready()) .. “)”,”info”) log(“>>>>>>>>session:mediaReady() —>(“ .. tostring(session:mediaReady()) .. “)”,”info”) log(“>>>>>>>>session:hangupState() —>(“ .. (session:hangupState() or “”) .. “)”,”info”) log(“>>>>>>>>session:getState() —>(“ .. (session:getState() or “”) .. “)”,”info”) log(“>>>>>>>>session:hangupCause()—>(“ .. (session:hangupCause() or “”) .. “)”,”info”)
freeswitch.msleep(5000)
<a name="KcGPA"></a>
## 测试桩:呼入拨号规则
```xml
<extension name="hangup_immediately">
<condition field="destination_number" expression="^186520050\d\d$">
<aciton application="hangup"/>
</condition>
</extension>
<extension name="hangup_delay_1_seconds">
<condition field="destination_number" expression="^186520040\d\d$">
<action application="set" data="ringback=${us-ring}"/>
<action application="sleep" data="1000" />
<aciton application="hangup"/>
</condition>
</extension>
<extension name="keep_rings_no_answer">
<condition field="destination_number" expression="^186520030\d\d$">
<action application="sleep" data="8000" />
<action application="set" data="early_use_180=true"/>
<action application="pre_answer" />
<action application="sleep" data="4000" />
</condition>
</extension>
<extension name="keep_rings_no_answer">
<condition field="destination_number" expression="^186520030\d\d$">
<action application="sleep" data="8000" />
<action application="set" data="ringback=${us-ring}"/>
<action application="playback" data="/home/in_call.wav" />
</condition>
</extension>
<extension name="answer_calls">
<condition field="destination_number" expression="^186520020\d\d$">
<action application="set" data="early_use_180=true"/>
<action application="pre_answer" />
<action application="sleep" data="2000" />
<action application="answer"/>
<action application="sleep" data="1000" />
<action application="lua" data="callintest.lua" />
</condition>
</extension>
<extension name="answer_no_ring">
<condition field="destination_number" expression="^186520010\d\d$">
<action application="answer"/>
<action application="sleep" data="1000" />
<action application="lua" data="callintest.lua" />
</condition>
</extension>
拨打本地用户
本地用户指的是注册到本地freeswitch上面的sip用户,一般使用user/1007这样的形式进行呼叫。
在使用user/1008的形式拨打时,freeswitch.Session收到200 ok后才返回。
也就是在接听之前,一直处于阻塞状态。
而呼叫外部用户则收到180/183就会返回,应该是某个通道变量引发的不同。
判断应该跟ignore_early_media有关,还需要进一步的研究,这个后面有机会再搞一下。
拨打外部用户
对端不振铃直接接通
接收端规则
<extension name="answer_no_ring">
<condition field="destination_number" expression="^186520010\d\d$">
<action application="answer"/>
<action application="sleep" data="1000" />
<action application="lua" data="callintest.lua" />
</condition>
</extension>
控制台日志
2020-10-14 14:43:49.040890 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:ready() —>(true)
2020-10-14 14:43:49.040890 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:mediaReady() —>(true)
2020-10-14 14:43:49.040890 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:answered() —>(true)
2020-10-14 14:43:49.040890 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:hangupState() —>()
2020-10-14 14:43:49.040890 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:getState() —>(CS_SOFT_EXECUTE)
2020-10-14 14:43:49.040890 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:hangupCause()—>(SUCCESS)
对端先振铃后挂断
接收端规则
<extension name="keep_rings_no_answer">
<condition field="destination_number" expression="^186520030\d\d$">
<action application="sleep" data="8000" />
<action application="set" data="early_use_180=true"/>
<action application="pre_answer" />
<action application="sleep" data="4000" />
</condition>
</extension>
控制台日志
2020-10-14 12:03:40.200912 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:ready() —>(true)
2020-10-14 12:03:40.200912 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:mediaReady() —>(true)
2020-10-14 12:03:40.200912 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:hangupState() —>()
2020-10-14 12:03:40.200912 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:getState() —>(CS_SOFT_EXECUTE)
2020-10-14 12:03:40.200912 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:hangupCause()—>(SUCCESS)
一直到振铃过来,freeswitch:Session才返回结果,输出上面的日志。
对端直接挂断
接收端规则
<extension name="hangup_delay_1_seconds">
<condition field="destination_number" expression="^186520040\d\d$">
<action application="set" data="ringback=${us-ring}"/>
<action application="sleep" data="1000" />
<aciton application="hangup"/>
</condition>
</extension>
控制台日志
拨打后对方直接回480,挂机原因是:NORMAL_CLEARING
session:getState()返回结果为ERROR
session:getHangupState返回结果为空
从err日志可以看出,此时session还未被初始化。
具体如下:
2020-10-14 12:04:23.601003 [DEBUG] sofia.c:7084 Channel sofia/internal/18652004000@172.26.178.70:54601 entering state [terminated][480] 2020-10-14 12:04:23.620989 [DEBUG] switch_ivr_originate.c:3848 Originate Resulted in Error Cause: 16 [NORMAL_CLEARING] 2020-10-14 12:04:23.620989 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:ready() —>(false) 2020-10-14 12:04:23.620989 [ERR] switch_cpp.cpp:1080 session is not initalized 2020-10-14 12:04:23.620989 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:mediaReady() —>(false) 2020-10-14 12:04:23.620989 [ERR] switch_cpp.cpp:709 session is not initalized 2020-10-14 12:04:23.620989 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:hangupState() —>()
2020-10-14 12:04:23.620989 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:getState() —>(ERROR)
2020-10-14 12:04:23.620989 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:hangupCause()—>(NORMAL_CLEARING)
对端sip服务器不存在(ip存在,端口不存在)
控制台日志
2020-10-14 13:49:38.980914 [DEBUG] sofia.c:7084 Channel sofia/internal/18652002000@172.26.178.70:54400 entering state [terminated][503] 2020-10-14 13:49:38.980914 [NOTICE] sofia.c:8273 Hangup sofia/internal/18652002000@172.26.178.70:54400 [CS_CONSUME_MEDIA] [NORMAL_TEMPORARY_FAILURE] 2020-10-14 13:49:39.000921 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:ready() —>(false)
2020-10-14 13:49:39.000921 [ERR] switch_cpp.cpp:1080 session is not initalized 2020-10-14 13:49:39.000921 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:mediaReady() —>(false) 2020-10-14 13:49:39.000921 [ERR] switch_cpp.cpp:709 session is not initalized 2020-10-14 13:49:39.000921 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:hangupState() —>()
2020-10-14 13:49:39.000921 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:getState() —>(ERROR)
2020-10-14 13:49:39.000921 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:hangupCause()—>(NORMAL_TEMPORARY_FAILURE)
从日志可以看出,freeswitch直接503报错(对端不存在,该错误是由本地发起者freeswitch产生),错误码是NORMAL_TEMPORARY_FAILURE。
除了报错码不一致外,session的状态结果与上面的对端直接挂断保持一致。
对端sip服务器不存在(ip不存在,本地ip)
随机构建了一个本地局域网的ip,路由器会返回目的主叫不可达,如下:
root@looook:~/docker/fstest/conf/dialplan/default# ping 172.26.178.11
PING 172.26.178.11 (172.26.178.11) 56(84) bytes of data.
From 172.26.178.70 icmp_seq=1 Destination Host Unreachable
From 172.26.178.70 icmp_seq=2 Destination Host Unreachable
From 172.26.178.70 icmp_seq=5 Destination Host Unreachable
From 172.26.178.70 icmp_seq=8 Destination Host Unreachable
From 172.26.178.70 icmp_seq=11 Destination Host Unreachable
From 172.26.178.70 icmp_seq=12 Destination Host Unreachable
From 172.26.178.70 icmp_seq=13 Destination Host Unreachable
From 172.26.178.70 icmp_seq=14 Destination Host Unreachable
From 172.26.178.70 icmp_seq=15 Destination Host Unreachable
控制台日志
下面是freeswitch的返回日志:
2020-10-14 14:01:21.360998 [NOTICE] switch_channel.c:1104 New Channel sofia/internal/18652002000@172.26.178.11:54400 [aef1b9a0-0de2-11eb-907a-037d6e4bd613] 2020-10-14 14:01:24.501007 [DEBUG] sofia.c:7084 Channel sofia/internal/18652002000@172.26.178.11:54400 entering state [terminated][503] 2020-10-14 14:01:24.501007 [NOTICE] sofia.c:8273 Hangup sofia/internal/18652002000@172.26.178.11:54400 [CS_CONSUME_MEDIA] [NORMAL_TEMPORARY_FAILURE] 2020-10-14 14:01:24.520951 [DEBUG] switch_ivr_originate.c:3848 Originate Resulted in Error Cause: 41 [NORMAL_TEMPORARY_FAILURE] 2020-10-14 14:01:24.520951 [ERR] switch_cpp.cpp:709 session is not initalized 2020-10-14 14:01:24.520951 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:ready() —>(false) 2020-10-14 14:01:24.520951 [ERR] switch_cpp.cpp:1080 session is not initalized 2020-10-14 14:01:24.520951 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:mediaReady() —>(false) 2020-10-14 14:01:24.520951 [ERR] switch_cpp.cpp:709 session is not initalized 2020-10-14 14:01:24.520951 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:hangupState() —>()
2020-10-14 14:01:24.520951 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:getState() —>(ERROR)
2020-10-14 14:01:24.520951 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:hangupCause()—>(NORMAL_TEMPORARY_FAILURE)
从日志可以看出:
- 即使ip不存在,因为是本地ip,所以路由器直接告诉我们目的主机不可达,fs收到类似消息后,也直接返回结果。
- fs返回的结果为503,NORMAL_TEMPORARY_FAILURE
- session未建立,所以仍提示session is not initalized
对端服务器不存在(ip不存在,非本地ip)
随机构建了一个非本地局域网的ip,ping的时候,直接卡死在这边。
root@looook:~/docker/fstest/conf/dialplan/default# ping 162.26.178.11
PING 162.26.178.11 (162.26.178.11) 56(84) bytes of data.
控制台日志
2020-10-14 14:02:42.800938 [NOTICE] switch_channel.c:1104 New Channel sofia/internal/18652002000@162.26.178.11:54400 [df7c6f8e-0de2-11eb-907d-037d6e4bd613] 2020-10-14 14:03:14.800980 [DEBUG] sofia.c:7084 Channel sofia/internal/18652002000@162.26.178.11:54400 entering state [terminated][408] 2020-10-14 14:03:14.800980 [NOTICE] sofia.c:8273 Hangup sofia/internal/18652002000@162.26.178.11:54400 [CS_CONSUME_MEDIA] [RECOVERY_ON_TIMER_EXPIRE] 2020-10-14 14:03:14.820958 [DEBUG] switch_ivr_originate.c:3848 Originate Resulted in Error Cause: 102 [RECOVERY_ON_TIMER_EXPIRE] 2020-10-14 14:03:14.820958 [ERR] switch_cpp.cpp:709 session is not initalized 2020-10-14 14:03:14.820958 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:ready() —>(false) 2020-10-14 14:03:14.820958 [ERR] switch_cpp.cpp:1080 session is not initalized 2020-10-14 14:03:14.820958 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:mediaReady() —>(false) 2020-10-14 14:03:14.820958 [ERR] switch_cpp.cpp:709 session is not initalized 2020-10-14 14:03:14.820958 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:hangupState() —>() 2020-10-14 14:03:14.820958 [NOTICE] switch_core_session.c:1683 Session 20 (sofia/internal/18652002000@162.26.178.11:54400) Ended 2020-10-14 14:03:14.820958 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:getState() —>(ERROR) 2020-10-14 14:03:14.820958 [NOTICE] switch_core_session.c:1687 Close Channel sofia/internal/18652002000@162.26.178.11:54400 [CS_DESTROY] 2020-10-14 14:03:14.820958 [INFO] switch_cpp.cpp:1365 test.lua:>>>>>>>>session:hangupCause()—>(RECOVERY_ON_TIMER_EXPIRE)
从日志可以看出:
- 发起呼叫后,32秒超时,才返回结果
- fs返回的结果是408,RECOVERY_ON_TIMER_EXPIRE
- session的状态处于未建立状态,和上面相同