Osip源代码框架16--2xx 应答重发机制

2xx 应答重发机制

根据 SIP 协议标准(RFC 3261),2xx 类响应(如 200 OK)的重传由客户端 UA(用户代理)负责控制。

1 重发触发条件:

  • 首次发送 2xx 应答:当本地 SIP 客户端发送 200 OK 等 2xx 响应后,启动定时器监控 ACK 接收情况
  • 超时未收到 ACK:在规定时间窗口内未接收到对端的 ACK 确认

2 重发时间间隔策略

  • 第 1 次重发:间隔 1 秒
  • 第 2 次重发:间隔 2 秒(1 秒 ×2)
  • 第 3-9 次重发:固定间隔 4 秒(达到上限后不再翻倍)

3 重发停止条件
在这里插入图片描述
条件一:成功匹配 ACK 应答
当收到的 ACK 与当前 dialog 匹配时,立即停止重发
释放 dialog 中保存的 2xx 响应副本
重置 dialog 中的重传状态参数

条件二:达到最大重发次数(9 次)
累计重发 9 次后仍未收到 ACK,终止当前呼叫
触发EXOSIP_CALL_CLOSED事件通知上层应用

eXosip 源码实现分析

核心控制函数:eXosip_retransmit_lost200ok

该函数在每次eXosip_execute()调用时被触发,遍历所有 dialog 检查 2xx 重发条件:

/* eXosip_dialog.c */
void eXosip_retransmit_lost200ok(eXosip_t *excontext)
{
    osip_list_t *dialogs = &excontext->j_dialog;
    osip_dialog_t *dialog;
    int i;

    for (i = 0; i < osip_list_size(dialogs); i++) {
        dialog = (osip_dialog_t *) osip_list_get(dialogs, i);
        
        /* 检查dialog是否有待重发的2xx响应 */
        if (dialog->last_2xx != NULL) {
            /* 计算距上次发送的时间差 */
            int elapsed = osip_clock_get() - dialog->last_2xx_time;
            
            /* 根据重发次数确定下一次间隔 */
            int next_interval = get_2xx_retransmit_interval(dialog->retransmit_2xx_count);
            
            if (elapsed >= next_interval) {
                /* 时间间隔满足,执行重发 */
                retransmit_2xx_response(excontext, dialog);
                
                /* 更新重发计数器和时间戳 */
                dialog->retransmit_2xx_count++;
                dialog->last_2xx_time = osip_clock_get();
                
                /* 检查是否达到最大重发次数 */
                if (dialog->retransmit_2xx_count >= MAX_2XX_RETRANSMITS) {
                    /* 终止呼叫 */
                    terminate_call(excontext, dialog);
                }
            }
        }
    }
}
时间间隔计算函数:get_2xx_retransmit_interval
static int get_2xx_retransmit_interval(int count)
{
    switch (count) {
        case 0: return 1000;  /* 第1次重发:1秒 */
        case 1: return 2000;  /* 第2次重发:2秒 */
        default: return 4000; /* 第3-9次重发:4秒 */
    }
}
ACK 匹配处理逻辑

当收到 ACK 请求时,eXosip 会调用eXosip_process_ack()进行处理:

/* eXosip_call.c */
int eXosip_process_ack(eXosip_t *excontext, osip_message_t *ack)
{
    osip_dialog_t *dialog;
    int i;
    
    /* 查找匹配的dialog */
    dialog = find_matching_dialog(excontext, ack);
    if (dialog == NULL) {
        return OSIP_NOT_FOUND;
    }
    
    /* 检查dialog中是否有待确认的2xx响应 */
    if (dialog->last_2xx != NULL) {
        /* 停止2xx重发 */
        stop_2xx_retransmissions(dialog);
        
        /* 释放保存的2xx响应资源 */
        osip_message_free(dialog->last_2xx);
        dialog->last_2xx = NULL;
    }
    
    /* 处理ACK后续逻辑... */
    return OSIP_SUCCESS;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

八月的雨季997

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值