概述

这篇文章主要小结的是lua中freeswitch.Session在发起呼叫时,针对不同目标的应答结果。
测试由两个freeswitch组成,一个负责外呼,一个负责模拟线路(测试桩)。

主要结论如下:

  1. 在通过sofia/internal/xxx@xxx呼叫外部用户的时候,需要收到180/183,freeswitch.Session才会结束阻塞状态,返回结果
  2. 在通过user/1007呼叫内部用户的时候,需要收到200,freeswitch.Session才会结束阻塞状态,返回结果
  3. 只有在收到180/183之后,session才会被真正初始化。如果直接收到挂断,会有报错“session is not initalized”
  4. 在通过sofia/internal/xxx@xxx外呼时,session:ready与session:mediaReady()在收到180/183后会变为true
  5. 呼叫外部用户时,只有对端ip不属于当前网络,并且无法ping通时,才会触发fs的30秒呼叫超时,报错:408 RECOVERY_ON_TIMER_EXPIRE
  6. 呼叫外部用户时,只有对端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)

  1. <a name="KcGPA"></a>
  2. ## 测试桩:呼入拨号规则
  3. ```xml
  4. <extension name="hangup_immediately">
  5. <condition field="destination_number" expression="^186520050\d\d$">
  6. <aciton application="hangup"/>
  7. </condition>
  8. </extension>
  9. <extension name="hangup_delay_1_seconds">
  10. <condition field="destination_number" expression="^186520040\d\d$">
  11. <action application="set" data="ringback=${us-ring}"/>
  12. <action application="sleep" data="1000" />
  13. <aciton application="hangup"/>
  14. </condition>
  15. </extension>
  16. <extension name="keep_rings_no_answer">
  17. <condition field="destination_number" expression="^186520030\d\d$">
  18. <action application="sleep" data="8000" />
  19. <action application="set" data="early_use_180=true"/>
  20. <action application="pre_answer" />
  21. <action application="sleep" data="4000" />
  22. </condition>
  23. </extension>
  24. <extension name="keep_rings_no_answer">
  25. <condition field="destination_number" expression="^186520030\d\d$">
  26. <action application="sleep" data="8000" />
  27. <action application="set" data="ringback=${us-ring}"/>
  28. <action application="playback" data="/home/in_call.wav" />
  29. </condition>
  30. </extension>
  31. <extension name="answer_calls">
  32. <condition field="destination_number" expression="^186520020\d\d$">
  33. <action application="set" data="early_use_180=true"/>
  34. <action application="pre_answer" />
  35. <action application="sleep" data="2000" />
  36. <action application="answer"/>
  37. <action application="sleep" data="1000" />
  38. <action application="lua" data="callintest.lua" />
  39. </condition>
  40. </extension>
  41. <extension name="answer_no_ring">
  42. <condition field="destination_number" expression="^186520010\d\d$">
  43. <action application="answer"/>
  44. <action application="sleep" data="1000" />
  45. <action application="lua" data="callintest.lua" />
  46. </condition>
  47. </extension>

拨打本地用户

本地用户指的是注册到本地freeswitch上面的sip用户,一般使用user/1007这样的形式进行呼叫。
在使用user/1008的形式拨打时,freeswitch.Session收到200 ok后才返回。
也就是在接听之前,一直处于阻塞状态。

而呼叫外部用户则收到180/183就会返回,应该是某个通道变量引发的不同。
判断应该跟ignore_early_media有关,还需要进一步的研究,这个后面有机会再搞一下。

拨打外部用户

对端不振铃直接接通

接收端规则

  1. <extension name="answer_no_ring">
  2. <condition field="destination_number" expression="^186520010\d\d$">
  3. <action application="answer"/>
  4. <action application="sleep" data="1000" />
  5. <action application="lua" data="callintest.lua" />
  6. </condition>
  7. </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)

对端先振铃后挂断

接收端规则

  1. <extension name="keep_rings_no_answer">
  2. <condition field="destination_number" expression="^186520030\d\d$">
  3. <action application="sleep" data="8000" />
  4. <action application="set" data="early_use_180=true"/>
  5. <action application="pre_answer" />
  6. <action application="sleep" data="4000" />
  7. </condition>
  8. </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才返回结果,输出上面的日志。

对端直接挂断

接收端规则

  1. <extension name="hangup_delay_1_seconds">
  2. <condition field="destination_number" expression="^186520040\d\d$">
  3. <action application="set" data="ringback=${us-ring}"/>
  4. <action application="sleep" data="1000" />
  5. <aciton application="hangup"/>
  6. </condition>
  7. </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)

从日志可以看出:

  1. 即使ip不存在,因为是本地ip,所以路由器直接告诉我们目的主机不可达,fs收到类似消息后,也直接返回结果。
  2. fs返回的结果为503,NORMAL_TEMPORARY_FAILURE
  3. 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)

从日志可以看出:

  1. 发起呼叫后,32秒超时,才返回结果
  2. fs返回的结果是408,RECOVERY_ON_TIMER_EXPIRE
  3. session的状态处于未建立状态,和上面相同