码农怎么做SIP测试

Published on

最近,在测试一个比较复杂的FreeSWITCH功能和应用场景,这个场景是我们自己开发的,在远程服务器上开发,实验环境也不容易在本地重现,关键的问题是必须有一个远方的分机配合测试。

有时在服务器上改代码,有时是在本地改了传上去,在服务器上编译,如果改了FreeSWITCH核心代码,还得重编核心。比较费时。最关键的问题是,每一次改动,都需要N种不同的测试,测试的场景是主叫呼叫被叫,被叫有两个或多个分机注册在不同的网络上,码农需要进远端配合测试的同事在微信上沟通—被叫是否振铃,谁先接?接通后是否有声音?效律非常低下。

这不,说着说着就过了夜半了。

一觉醒一来,还得接着测,不好意思叫醒远端的同事,寻思着怎么构建测试场景,忽然就想起了一年多前我们自己搭建的SIP服务

SIPSIP是一个自动的测试服务,你只需要向它发起一个SIP呼叫,呼叫180,它就回复180,呼叫183,就回复183 SIP消息,甚至,还能指定振铃的时长,如呼叫1805000,则SIPSIP会在回复180后,等5秒后再回200 OK消息。

这个服务其实我们经常用,只,由于我们的测试场景比较复杂,一时没想起来。但仔细一想,其实还是可以做的。

首先,我们的被叫使用的是FreeSWITCH里的多注册模式,如果有呼叫进来,多个话机就同时振铃,呼个话机先接听(或先回媒体,如183),则胜了,其它分机自动挂机。

说是“同时”,但实际在FreeSWITCH内部还是顺序发起呼叫的,只不过看起来几乎是同时而已。在实验中,我们发现,我们遇到的问题跟FreeSWITCH找到多个分机的顺序不同,以及哪个分机先接听都有关。对于后者,我们还可以决定谁先接听,但对于前者,其实很难确定FreeSWITCH返回的顺序。所以,测试有很多不确定性。好在,有了SIPSIP,我们设计了如下Dialplan:

<extension name="fork">
 <condition field="destination_number"expression="^f1(.*)$">
  <action application="bridge" data="user/$1,sofia/inernal/1805000@sip1.sipsip.cn:5080"/>
  </condition>
 </extension>

<extension name="fork">
 <condition field="destination_number" expression="^f2(.*)$">
   <action application="bridge" data="sofia/internal/1805000@sip1.sipsip.cn:5080,user/$1"/>
  </condition>
 </extension>

<extension name="fork">
 <condition field="destination_number" expression="^f3(.*)$">
  <action application="answer" data=""/>
    <action application="bridge" data="user/$1,sofia/internal/1805000@sip1.sipsip.cn:5080"/>
  </condition>
 </extension>

<extension name="fork">
  <condition field="destination_number" expression="^f4(.*)$">
    <action application="answer" data=""/>
    <action application="bridge" data="sofia/internal/1805000@sip1.sipsip.cn:5080,user/$1"/>
  </condition>
</extension>
 
<extension name="fork">
  <condition field="destination_number" expression="^f5(.*)$">
    <action application="set" data="ringback=$${uk-ring}"/>
    <action application="bridge" data="user/$1,sofia/internal/1805000@sip1.sipsip.cn:5080"/>
  </condition>
</extension>
 
<extension name="fork">
  <condition field="destination_number" expression="^f6(.*)$">
    <action application="set" data="ringback=$${uk-ring}"/>
    <action application="bridge" data="sofia/internal/1805000@sip1.sipsip.cn:5080,user/$1"/>
  </condition>
 </extension>
 
<extension name="fork">
  <condition field="destination_number" expression="^f7(.*)$">
    <action application="bridge" data="user/$1,sofia/internal/183@sip1.sipsip.cn:5080"/>
  </condition>
</extension>

<extension name="fork">
   <condition field="destination_number" expression="^f8(.*)$">
     <action application="bridge" data="sofia/internal/183@sip1.sipsip.cn:5080,user/$1"/>
  </condition>
</extension>

其中,每两个是一组。f1,f2,直接bridge,只是参数顺序不同。SIPSIP会在5秒后自动接听,如果有分机呼叫f11006,则本地分机1006和SIPSIP会同时振铃,要么在5秒钟内接听1006,要么等5秒后SIPSIP自动接听,1006自动挂机。呼f21006则改变参数顺序,又是两种接听情况,这样,一组Dialplan就解决了4个测试场景。

我们一共有4组。

f3f4,先answer,测试如果外线呼入,先进入IVR之类的场景,这种场下aleg先接听了。

f5f6则测试有ringback的场景,如果收到被叫回的180消息,则给主叫回183。对此不明白的同学可以看一看以前的文章:180还是183。眼尖的读者可以看出,我们用到了uk-ring,因为默认的振铃声都是美国的,换成英国的铃音,我们一下就能听出来区别。

f7f8则测试对方返回183的情况。

当然,其实还有更多的组合,不过,上述案例基本覆盖了我们的测试。我在编好这些案例时,我同事还在睡觉。

借助这些测试,我只需要每次改变代码后,打几个电话。接听或者不接听,Bug就在那里。

当然,我很快就就找到了问题并修复了。

SIPSIP是一个免费、开放的服务,如果你觉得SIPSIP有用,欢迎赞助,以便我们把它做的更好。另外,SIPSIP可以放语音广告,各位老板需要有需要,也欢迎与小编联系。

注:SIPSIP服务已下线(2020)。