zoukankan      html  css  js  c++  java
  • 【FreeSWITCH】WRONG_CALL_STATE

    WRONG_CALL_STATE

     【转自http://www.10tiao.com/html/719/201802/2664614847/1.html

    在使用FreeSWITCH的过程中,经常会看到日志中显示WRONG_CALL_STATE,如:

    2018-02-12 13:00:30.734977 [WARNING]

    switch_core_state_machine.c:687

    sofia/internal/41@1.2.3.4 Abandoned

    2018-02-12 13:00:30.734977 [NOTICE]

    switch_core_state_machine.c:690

    Hangup sofia/internal/41@1.2.3.4

    [CS_NEW] [WRONG_CALL_STATE]

    好多同学都问这个问题,不知道是什么原因。其实,要检查这个问题也很简单,只需要用sofia profile internal siptrace on打开SIP Trace,跟踪下信令就知道原因了。不过,这种事情比较麻烦的是,你不知道它什么时候会出现。

    好在,FreeSWITCH是开源软件,直接打开源代码查看日志中描述文件的687~690行就好了,大致是这样的:

    while ((state = switch_channel_get_state(session->channel)) != CS_DESTROY) {

    uint32_t new_loops = 500;

    ...

    if (endstate == CS_NEW) {

    switch_yield(20000);

    switch_ivr_parse_all_events(session);

    if (!--new_loops) {

    switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s %s Abandoned ",

    session->uuid_str, switch_core_session_get_name(session));

    switch_channel_set_flag(session->channel, CF_NO_CDR);

    switch_channel_hangup(session->channel, SWITCH_CAUSE_WRONG_CALL_STATE);

    }

    } else {

    ...

    }

    }

    从代码上看,问题发生在FreeSWITCH的核心状态机,核心状态机是一个循环,里面有个计数器,如果状态机连续有500次处于CS_NEW状态,则打印错误日志WRONG_CALL_STATE,挂机。

    switch_yield(20000)是等待20毫秒,因为循环500次的时间大约是20毫秒 x 500 = 20000毫秒 = 10秒。

    从日志中我们倒回10秒查找日志,果然能找到电话初始化时候的日志:

    2018-02-12 13:00:20.714977 [NOTICE]

    switch_channel.c:1104 New Channel sofia/...

    也就是说,从电话初始化,到释放,Channel的状态一直处于CS_NEW状态,当然至于为什么一直处于这个状态,还得进一步的看代码,那就不好找了。

    所以,最终分析该分题比较好的方法还是要配合SIP消息进行分析。

    此处省略5000字 ...

    好吧,既然我知道这个问题的原因我就不卖关子了。

    问题的原因在于SIP消息不完整,正常的SIP流程一般是:

    --> 主叫发送INVITE

    <-- FreeSWITCH回复100 Trying

    <-- 401 需要Challenge 验证

    --> ACK

    --> 主叫发送带认证信息的INVITE

    ... 继续

    而此处的问题在于,主叫在收到401后,没有回ACK,或者回了但没有继续发送INVITE消息,也就是,没有按规矩出牌,导致FreeSWITCH一直处于等待状态,10秒后FreeSWITCH超时挂机。

    如果你的FreeSWITCH服务器部署在公网上,上面的问题多半是来自坏人的攻击,小半是由于NAT问题等导致客户端发送的ACK或INVITE到不了FreeSWITCH,小概率事件是你自己写了个SIP客户端半道崩溃了。

    具体的SIP消息我这里也没有,大家不妨自己验证下。

    有的同学说了,怎么验证呢?嗯,就是不好验证所以我才没有SIP消息。因为,大家手头的SIP客户端都是按规矩出牌的,一下子想不按规矩出牌还真不容易做到。

    有没有工具能发送任意我想要的SIP呢?还真有,你直接用nc,或者sipsak,或sipp都可以发送任意的SIP消息。不过,今天我就写到这里了,有没有人接龙呢?


  • 相关阅读:
    细说 ASP.NET Cache 及其高级用法【转】
    类变量和实例变量的区别是什么?
    【转】细说Cookie
    【转】细说 Form (表单)
    PHP API中,MYSQL与MYSQLI的持久连接区别
    Extending_and_embedding_php翻译
    linux常见面试题及答案
    手机辐射查询
    php5.3 PHP5.4 PHP5.5 新特性/使用PHP5.5要注意的
    sqoop安装遇到的问题
  • 原文地址:https://www.cnblogs.com/zililita/p/10774095.html
Copyright © 2011-2022 走看看