OpenSIPS处理200OK的ACK和RE-INVITE的时序问题

问题描述:

FreeSWITCH发起外呼(通过OpenSIPS forward到运营商),在receive_message收到SWITCH_MESSAGE_INDICATE_BRIDGE时(SIP receive 183 Session Progress SDP),再发起RE-INVITE,这时其实还没有收到运营商返回的200OK。FS会保证在收到200OK后,将ACK和RE-INVITE依次发送出去。

OpenSIPS上先收到ACK再收到RE-INVITE,但是OpenSIPS在处理ACK和RE-INVITE时,很有可能会先将RE-INVITE发送出去,这时运营商还没有收到上次的ACK,会返回500 Overlapping Requests。

这种case可以参考 https://datatracker.ietf.org/doc/html/rfc5407#page-17 (Call Flows of Race Conditions) 中的3.1.4章节。

示例流程图:

深入分析:

后面有空的话会写下OpenSIPS tm模块的处理流程。

解决方法:

1. 使用tcp,一通通话的connection中消息是保证顺序的。

2. 运营商返回200OK,并启动定时器等待ACK,一段时间等不到再发送BYE。 

3. 运营商不处理RE-INVITE,这样OpenSIPS会重发,直到运营商收到ACK,进入正常逻辑。

4. OpenSIPS tm模块保证INVITE发送在ACK之前。

5. FS发送RE-INVITE要delay一些。

6. OpenSIPS路由脚本中,在判断RE-INVITE后,添加 'usleep(400000);'。

7. OpenSIPS可以在自己的模块中注册回调函数到tm模块,监听TMCB_PRE_SEND_BUFFER事件,并在回调函数中判断是否为RE-INVITE,然后sleep任意时间。

首先排除了2、3,运营商那边的处理策略我们不好影响;1的话因为没有基于tcp使用sip的经验,担心引入其它问题;4需要改动大量OpenSIPS代码,而且即使保证INVITE发送在ACK之前,也不能保证运营商是这个接收顺序,不如选择5、6、7。

其中6最简单,这里sleep 400ms是因为transaction里消息的超时时间默认是500ms,如果sleep太长时间的话FS会因为收不到 '100 Giving it a try' 而重发RE-INVITE(当然OpenSIPS是能hold住这种case的)。效果如下:

其中10.18.2.18为OpenSIPS,10.18.2.206为FS。可以看到OpenSIPS收到INVITE后delay了400ms(18:57:12.978724 -> 18:57:13.379533)。

第7个方法比6要好,因为是在发送 '100 Giving it a try' 之后才delay的,不像6中 send 100也delay。效果如下:

可以看到,send 100之后delay了600ms,不会导致6中sleep超过500ms而导致的重发问题。

附部分代码如下:

void sendcb(struct cell* t, int type, struct tmcb_params* param)
{
    struct dlg_cell* dlg;
    int tp = param->req->REQ_METHOD;
    if (tp == TMCB_REQUEST_IN) {
        usleep(600000);
    }
}

void incb(struct cell* t, int type, struct tmcb_params* param)
{
    struct dlg_cell* dlg;
    if (type == TMCB_REQUEST_IN && has_to_tag(&param->req->to->body)) {
        if (tmb.register_tmcb(NULL, t, TMCB_PRE_SEND_BUFFER, sendcb, 0, 0) <= 0) {
            LM_ERR("cannot register TMCB_REQUEST_IN callback\n");
            return -1;
        }
    }
}

static int mod_init(void)
{
/*****************/
    if (tmb.register_tmcb(0, 0, TMCB_REQUEST_IN, incb, 0, 0) <= 0) {
        LM_ERR("cannot register TMCB_REQUEST_IN callback\n");
        return -1;
    }
/*****************/
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值