使用 Twilio 的中继服务,Asterisk SIP 呼叫在 2 分钟后结束

使用 Twilio 的中继服务,Asterisk SIP 呼叫在 2 分钟后结束

我在 DigitalOcean 上托管了一个 Asterisk 服务器,使用 Twilio 的中继服务后,通话在 120 秒后中断。值得注意的是,直接连接的软件电话不会中断通话。防火墙上的端口 5060 是开放的,这是理所当然的。

有一个自动接线员接收呼叫并将其传递给脚本,但使用 SIP 软件电话,它可以完全正常工作,而无需挂断呼叫。我给 Twilio 发了电子邮件,他们说问题可能是因为 Asterisk 没有发送 180 振铃,我可以理解,因为我没有拨打电话,只是立即接听。

真正切断通话的是什麽?

配置文件

[twilio]
type=peer
secret=secret
username=user
host=host.domain.com
dtmfmode=rfc2833
canreinvite=no
disallow=all
allow=ulaw
insecure=port,invite
fromuser=+15555555555
fromdomain=from-domain.domain.com
context=incoming
deny=0.0.0.0/0
permit=x.x.x.x/32
permit=x.x.x.x/32
permit=x.x.x.x/32
permit=x.x.x.x/32

extensions.ael 上下文

+15555555555 => {
        Answer();
        EAGI(tincan.js);
        AGI(agi://127.0.0.1/saytext,"Goodbye.");
        Hangup();
}

开始通话数据包捕获

21  4.827782    (Them)  (Us)    SIP/SDP 1341    Request: INVITE sip:[email protected] | 
22  4.831487    (Us)    (Them)  SIP 819 Status: 100 Trying | 
23  4.833205    (Us)    (Them)  SIP/SDP 1112    Status: 200 OK | 

通话结束数据包捕获

16066   124.821787  (Them)  (Us)    SIP 650 Request: BYE sip:[email protected]:5060 | 
16067   124.822736  (Us)    (Them(  SIP 700 Status: 200 OK |

答案1

Twilio 报告称,问题是由于我们的服务器长时间未发送任何 RTP 数据,因此连接超时。我使用的拨号方案运行了一个自定义 EAGI 脚本,该脚本会无限期地记录通话人。这个过程在另一端超时了。

我的解决方案如下:

  1. 我没有使用 RECORD FILE 命令,而是使用了 GET OPTION 命令来播放 10 秒的静音,等待井号 (#) 键。
  2. 我使用 EAGI stderr+1 fd 通过我的脚本手动将音频捕获到文件中。
  3. 我使用 STREAM FILE 命令播放录音给用户确认。

反复发送 10 秒的静音可防止服务器超时。我可以想象发送 1 秒的静音可达到相同的效果并节省带宽,但您的情况可能有所不同。

我的 Node.js 脚本函数取代了 WAIT FOR DIGIT 或 RECORD FILE 函数:

/**
 * Loop playing silence until interrupted
 * @param done =function( timedout ) Callback when the silence has been interrupted
 * @param maxRecordTime Length of time to be able to record max. Leave blank for no timeout.
 * @param stopTime Timestamp when the recording should be stopped
 */
Index.prototype.loopSilenceUntilInterrupted = function( done, maxRecordTime, stopTime ) {
    var that = this;

    // Set the stopTime?
    if( maxRecordTime!==undefined && stopTime===undefined )
        stopTime = Date.now()+maxRecordTime;

    this.context.getOption( "silence/10", "#", 10, function( error, response ) {
        if( response.result==35 )
            done( false ); // We have been diggery
        else if( stopTime!==undefined && Date.now()>=stopTime )
            done( true ); // We have timed out!
        else
            that.loopSilenceUntilInterrupted( done, maxRecordTime, stopTime ); // Do it again
    },
    0 ); // No cooldown
};

相关内容