文章目录
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;
}
373

被折叠的 条评论
为什么被折叠?



