Osip源代码框架11--eXosip工作流程简介

eXosip时序图

在这里插入图片描述
eXosip 是 OSIP 的 “上层封装”,eXosip 管 “业务交互”:你直接调用 eXosip_call_invite()、eXosip_register() 等 API,不用关心 OSIP 底层事务。

OSIP 管 “协议细节”:定时器、事务(Transaction)、消息解析等逻辑,eXosip 内部通过 OSIP 库实现。比如 eXosip_execute 里的 osip_timers_*_execute,就是 OSIP 的核心逻辑。

eXosip主要流程

在这里插入图片描述

1. 配置基础参数

操作:设置 exosip 包容量、网关 IP(v4/v6)、UA 标识等(对应 设置 exosip 中的几个常量…)。

作用:
给 SIP 协议栈 “定规矩”:比如包容量决定能处理多大的 SIP 消息(避免溢出)。
user_agent 是客户端标识(服务端靠它识别你的设备 / 程序,类似 HTTP 的 User-Agent)

2. 激活 eXosip 状态

操作:eXosip_stop = 0(标记为 “允许运行” 状态)。

作用:

  • 相当于给 eXosip “开机”,让后续流程(定时器、消息处理)能正常执行。
  • 如果设为 1,eXosip 会进入 “停止待销毁” 状态,拒绝处理新逻辑。
3. 初始化进程间通信

操作:用 pipe 初始化多线程通信的信号 / 信号线程(对应 初始化多线程使用的信号和信号线程通信方式 pipe)

作用:定时器线程触发事件后,通过 pipe 通知业务线程处理。

4. 绑定 OSIP 核心库

操作:初始化 exosip 中的 osip(对应 初始化 exosip 中的 osip,用于管理 osip lib 库)

作用:
eXosip 是 OSIP 的 “上层封装”,这一步把两者绑定,让 eXosip 能调用 OSIP 的核心功能(事务管理、协议解析等)。
简单说:OSIP 是 “发动机”,eXosip 是 “方向盘 + 仪表盘”,这步就是把发动机装到车上。

5.注册回调函数

操作:初始化 osip 的 callback 函数(对应 初始化 osip 的 callback 回调函数)。

作用:让 OSIP 事件能 “通知” 到你的业务代码:比如收到 INVITE 时,触发你写的 on_invite_received 函数。
常见回调:呼叫事件、注册事件、消息收发事件(业务逻辑和协议栈解耦的关键)

6.初始化传输层

操作:配置 4 种传输方式(UDP/TCP/TLS/WS 等,对应 初始化传输层的 4 种不同的传输方式)。

作用:决定 SIP 消息怎么发:比如 UDP 适合低延迟(但不可靠),TCP 适合可靠传输(但稍慢)。

eXosip_execute 流程拆解

在这里插入图片描述
把大流程拆成 「消息监听 → 定时器 / 事务处理 → 资源清理 → 保活」 四个核心阶段,梳理每个环节的作用:

  1. 消息监听阶段:eXosip_read_message
  2. 定时器与事务处理阶段(OSIP 核心逻辑)
  3. 资源释放清理阶段
  4. UDP 保活(可选):_eXosip_keep_alive
1. 消息监听阶段:eXosip_read_message

作用:线程持续监听 “是否有新消息到达客户端”,是整个流程的 “入口触发器”。
特殊点
接收消息是 “被动监听”,但发送消息由管理程序主动调用接口触发(比如业务层调用 eXosip_message_send 这类接口)。
收到消息后,可能触发
新建 call、transaction(事务)
生成 transaction 事件、exosip 事件(最终上报给管理程序处理)。
事件定义:所有事件类型在 exosip.h 的 eXosip_event_type 枚举里,业务层根据枚举做不同逻辑(比如 EXOSIP_CALL_INVITE 处理呼叫邀请)。

2.定时器与事务处理阶段(OSIP 核心逻辑)

消息预处理后(或无新消息时),进入 OSIP 事务定时器 + 事件执行 环节,分两步:
在这里插入图片描述

  • osip_timers_*_execute:遍历 4 类事务链表(_ict/_nict/_ist/_nist)的定时器,超时则生成新定时器事件,丢进事务的事件队列。
  • osip_*_execute:遍历事务链表,执行队列里的事件(比如消息后半段处理、状态变更)。
  1. 资源释放清理阶段
    处理完事务后,开始 “收尾工作”,释放已结束的 call、registration、publication:
    在这里插入图片描述
    registration/publication 释放时,不会直接销毁事务,而是把事务从自身结构中移除,丢到 exosip 全局的 j_transaction 链表。
    真正的事务销毁在 eXosip_release_terminated_calls 里统一处理(延迟释放,保证流程完整性)
UDP 保活(可选)

触发条件:如果传输层用 UDP,必须调用它!
作用:给 registration 发心跳报文,维持 UDP 端口活性(防止系统因超时空闲关闭端口,导致后续消息收不到)

eXosip_read_message 处理流程

流程总览:
传层读消息 → 解析 + 回调 → 事务 / 请求判断 → 分类型处理(INVITE/ACK 等)

1. 传输层读消息

目标:
根据传输层协议(UDP/TCP 等),从协议栈底层读取 SIP 消息。

核心逻辑:
eXosip_read_message 会调用传输层的 tl_read_message(如 exTL_udp_tl_read_message、exTL_tcp_tl_read_message)。
不同传输层走不同分支(UDP/TCP 逻辑分离)。

2.消息预处理

目标:解析消息、回调业务函数、做基础校验。
在这里插入图片描述

3. 事务匹配与合法性检查

在这里插入图片描述
目标:判断消息属于已有事务 / 对话,还是新请求 / 非法响应。

事务匹配:用 Call-ID、CSeq、Via branch 等字段,找已有事务(Transaction)。
请求 / 响应判断:SIP 请求的 Status 为 0,响应则带具体状态码(200、404 等)

4. 业务逻辑分发

目标:根据消息类型(INVITE/ACK/BYE 等),走不同业务流程。
核心分支(以 eXosip_process_newrequest 为例):
在这里插入图片描述
INVITE 细分逻辑(最复杂,需处理对话 / 事务创建):
在这里插入图片描述

5.关键点
  1. 事务 vs 对话的关联
    事务:单次请求 - 响应(如 INVITE-200-ACK 是两个事务:INVITE 事务 + ACK 事务)。
    对话:多个事务的持续会话(Call-ID 关联,维护媒体协商、CSeq 等状态)。
    核心判断:先匹配对话(条件更松,Call-ID 即可),再匹配事务(需 CSeq、Via branch 精确匹配)。
  2. 非法消息处理
    ACK 无对话:直接释放(ACK 必须关联已有对话,否则非法)。
    响应无事务:走 eXosip_process_response_out_of_transaction(协议错误,可能是旧响应重传)。
    请求类型非法:如 INFO 无对话时回复 481,直接拒绝。
  3. 协议合规性(SIP RFC 3261 映射)
    100 Trying 触发:INVITE 处理时,默认先发 100(除非显式关闭)。
    CSeq 校验:新请求的 CSeq 必须大于对话中保存的,否则视为重复请求。
    对话状态校验:已结束的对话(收到 BYE 后)再收请求,回复 481。

eXosip_process_response_out_of_transaction 处理流程

把处理流程拆成 「合法性校验 → 对话 / 呼叫匹配 → 分场景处理 → 资源清理」,每个阶段聚焦核心动作
在这里插入图片描述

1 应答合法性校验(阶段 A)
  • 目标:过滤非法应答(格式错误、关键头域缺失等)。
  • 核心逻辑:
    检查 SIP 应答的基础格式:Status-Line 是否合法(如 SIP/2.0 200 OK 格式)。
  • 校验关键头域:Call-ID、CSeq、Via 是否存在且格式正确。
  • 协议依据:SIP RFC 3261 第 7 节(消息格式)、第 17 节(事务处理)。
2 查询关联 Call/Dialog(阶段 B)
  • 目标:找到应答所属的呼叫(Call)或对话(Dialog)。
    核心动作:
  • 遍历所有 Call,检查应答的 Call-ID 是否匹配。
    对匹配的 Call,进一步检查 Dialog(已建立 Dialog 则校验 To/From Tag、Route 等)。
  • 协议逻辑:Call 是对话的容器,Dialog 是 Call 内的会话上下文(关联多次事务)
3 无匹配处理(阶段 C→D)
  • 场景:应答的 Call-ID 与任何 Call 都不匹配。
  • 处理:直接释放 SIP 消息(非法应答,与当前系统无关)。
4 分场景处理(阶段 C→E)

根据匹配结果(匹配到 Dialog 或仅匹配到 Call),分两种核心场景:

  • 场景 1:匹配到 Dialog(重复 200 应答处触发条件:
    应答匹配到已存在的 Dialog,但未匹配到事务(事务已销毁,但 Dialog 仍存在)。
    常见原因:对端未收到 ACK,重发 200 OK,导致本端事务已释放但 Dialog 还在。
    在这里插入图片描述
  • 场景 2:仅匹配到 Call(Dialog 未建立时的错误应答)
    触发条件:
    应答匹配到 Call,但 Dialog 未建立(如 INVITE 事务还未完成 Dialog 初始化)
    在这里插入图片描述

5 小结
「校验应答合法性 → 找关联 Call/Dialog → 无匹配则释放 → 匹配 Dialog 则补发 ACK → 仅匹配 Call 则临时 Dialog + BYE 清理
每个步骤都围绕 “修复协议异常” 和 “保证会话一致性” 设计,理解后可快速定位两类问题:

  • 重复 200 OK 导致的网络风暴(需检查 ACK 补发逻辑)。
  • 异常 200 OK 导致的会话残留(需检查临时 Dialog + BYE 清理逻辑)。

eXosip_automatic_action 处理流程

eXosip_automatic_action 函数的核心是处理认证失败和需要重定向的场景,通过自动重试机制提高通信成功率。其设计遵循 “错误恢复 + 预防性重注册” 双策略,覆盖 SIP 中的核心事务类型(Call、Register、Notify 等)

在这里插入图片描述Call 处理逻辑详解
关键步骤:

  • 过滤无效 Call:跳过 c_id < 1 的已删除 Call

  • 处理未建立 Dialog 的 Call:检查初始 INVITE 事务状态(是否终结)

  • 检查响应状态码:
    401/407:认证失败,提取认证信息重试(最多 3 次)
    300-399:重定向,更新目标地址重试(最多 3 次)

  • 处理已建立 Dialog 的 Call:遍历所有 Dialog,重复上述状态码检查逻辑

for (each call in j_calls) {
    if (call->c_id < 1) continue; // 跳过已删除Call
    
    if (dialog_not_created(call)) {
        // 处理未建立Dialog的初始INVITE
        if (transaction_terminated(call) && 
            !call_timeout(call, 120) && 
            (response_code == 401 || response_code == 407)) {
            retry_with_auth(call); // 带认证重试
        } else if (response_code >= 300 && response_code <= 399) {
            retry_with_redirect(call); // 带重定向重试
        }
    }
    
    // 遍历并处理Call中的所有Dialog
    for (each dialog in call) {
        check_and_retry_dialog(dialog); // 同上逻辑
    }
}

code

初始化上下文
// 1. 初始化 eXosip 上下文
eXosip_t *exosip = eXosip_malloc(); 
eXosip_init(exosip); 

// 2. 配置基础参数(包容量、UA、网关等)
eXosip_set_user_agent(exosip, "MySIPClient/1.0"); 
eXosip_set_gateway(exosip, "udp://192.168.1.100:5060"); 

// 3. 初始化传输层(UDP/TCP 等)
eXosip_listen_addr(exosip, IPPROTO_UDP, "0.0.0.0", 5060, 0); 
eXosip_execute 中事件循环主逻辑
while (is_running) { // is_running 由业务控制(比如用户没挂断)
    eXosip_event_t *event = eXosip_execute(exosip); // 执行一次事件循环

    if (event == NULL) {
        usleep(100000); // 无事件时休眠,避免 CPU 空转
        continue;
    }

    // 根据事件类型处理业务逻辑
    switch (event->type) {
        case EXOSIP_CALL_INVITE: 
            // 收到新呼叫邀请,处理振铃、媒体协商
            handle_invite(event); 
            break;
        case EXOSIP_CALL_ANSWER: 
            // 被叫应答,开始媒体流传输
            handle_answer(event); 
            break;
        // 其他事件类型(注册成功、消息接收等)...
    }

    eXosip_event_free(event); // 释放事件内存
}

eXosip_execute 是 “心脏”:每次执行会处理消息、定时器、资源释放,驱动 SIP 状态机前进。
回调 + 事件循环结合:事件循环拿到事件后,通过回调函数(初始化阶段注册的)通知业务层

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

八月的雨季997

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

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

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

打赏作者

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

抵扣说明:

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

余额充值