复旦光华之osip协议栈使用入门

上传人:j****9 文档编号:44955683 上传时间:2018-06-14 格式:DOC 页数:4 大小:27.50KB
返回 下载 相关 举报
复旦光华之osip协议栈使用入门_第1页
第1页 / 共4页
复旦光华之osip协议栈使用入门_第2页
第2页 / 共4页
复旦光华之osip协议栈使用入门_第3页
第3页 / 共4页
复旦光华之osip协议栈使用入门_第4页
第4页 / 共4页
亲,该文档总共4页,全部预览完了,如果喜欢就下载吧!
资源描述

《复旦光华之osip协议栈使用入门》由会员分享,可在线阅读,更多相关《复旦光华之osip协议栈使用入门(4页珍藏版)》请在金锄头文库上搜索。

1、OSIP 协议栈使用入门(续一:纯协议栈逻辑分析) (注:下文假设阅读者已经大概了解 SIP 协议的简单呼叫流程,会使用 Ethereal 等抓包工具分析 SIP 消息结构,对 C 语言的指针、链表、内存控制及状态机等概念有足够的认识。 )要应用 Osip 到我们的程序中去,首先要看官方文档,文档中对 Osip 协议栈提供的各 个功能部件如何使用都有比较详细的描述,但未进行整体性的分析,某些中文的指导文档 也都停留在对其简单的翻译,不能为不熟悉该协议栈使用的用户快速参考使用,本文档不 按照 Osip 的代码进行按功能分块说明,而是根据实际使用时的代码使用顺序来对主要逻辑 流程进行分析,并适当对

2、流程中使用到的功能部件进行说明,具体更详细的功能说明或疑 问可直接查看官方文档对应部分的解释或直接查看功能函数源代码即可解决。准备工作准备工作先认识几个结构体:osip_t,osip_message_t,osip_dialog_t,osip_transaction_t;osip_t 是一个全局变量,所有要使用 Osip 协议栈的事务处理能力的程序都要第一 步就初始化它(相对应于只使用 osipparser 库进行 SIP 消息字段解析的应用来说,如 果只使用 parser 库到自己的程序中,想必对 SIP 协议栈已经很熟悉了,不需再往下看 了_) ,它内部主要是定义了 Osip 协议栈的四个主

3、要事务链表、消息实际发送函数及 状态机各状态事件下的回调函数等;osip_message_t 是 SIP 消息的 C 语言结构体存储空间,收到 SIP 消息解析后存在 该结构中方便程序使用接收到的消息中的指定的字段,发送消息前为方便设置要发送 的字段值,将要发送的内容存在该结构中等发送时转为字符串;osip_dialog_t 则是 SIP RFC 中的 dialog 或叫 call leg 的定义,它标识了 uac 和 uas 的一对关系,并一直保持到会话(session)结束,一个完整的 dialog 主要包括 from,to,callid,fromtag,totag,state 等(可查看

4、源码) ,其中 fromtag,totag,callid 在一个 dialog 成功建立后才完整,体现在 SIP 消息中,就是 From、To 的 tag,Call-id 字段的 值相同时,这些消息是属于它们对应的一个 Dialog 的,例如将要发起 invite 时,只有 fromtag,callid 填充有值,在收到 to 远端的响应时,收到 totag 填充到 dialog 中,建立 成功一个 dialog,后继的逻辑均是使用这个 dialog 进行处理(如 transaction 事务处理) , state 表示本 dialog 的状态,与 transaction 的 state 有很

5、大的关联,共用由 Enum 结构 state_t 定义;osip_transaction_t 则是 RFC 中的事务的定义,它表示的是一个会话的某个 Dialog 之间的某一次消息发送及其完整的响应,例如 invite-100-180-200-ack 这是一个完整的 事务,bye-200这也是一个完整的事务,体现在 SIP 消息中,就是 Via 中的 branch 的值 相同表示属于一个事务的消息(当然,事务是在 Dialog 中的,所以 From、To 的 tag,Call-id 值也是相同的) ,事务对于 UAC,UAS 的终端类型不同及消息的不同,分 为四类,前面说的 invite 的事

6、务,主叫 uac 中会关联一个 ict 事务,被叫 uas 会关联一 个 ist 事务,而除了 invite 之外,都归类定义主叫 nict,被叫 nist,在 Osip 中,它是靠 有限状态机来实现的上述四种事务(osip_fsm_type_t 中定义)的,它的主要属性值有 callid,transactionid,分别来标识 dialog 和 transaction,其中还有一个时间戳 birth_time 标识事务创建时间,可由超时处理函数用来判断和决定超时情况下的事务的进行和销 毁,而它的 state 属性是非常重要的,根据上述的事务类型不同,其值也不同,它是前 面提到的状态机的“状态

7、”,在实际状态机的逻辑执行中是一个关键值; Osip 初始化初始化提到 osip 的初始化,可能大家都看过官方文档里第一页的代码,首先就是 osip_init(&osip)初始化了全局的 osip_t 结构体,然后对它的回调函数进行设置,很多 人估计就是一看到这密密麻麻的一页多的 call_back 设置被吓到了,但结合前面分析的 三个结构体的含义,这里的含义就很清晰了:osip_t 中有一个 cb_send_message 函数指针,它是 Osip 最终与外界网络交互的接 口,它的参数有( osip_transaction_t * trn, osip_message_t * sipmsg,c

8、har *dest_socket_str, int32_t dest_port, int32_t send_sock) 其中 trn 传入主要是为了方便获取事务的上下文数据,它有一个 void 指针 your_instance,可以用来传入更多数据方便发送消息时参考,例如将该事务所属的 dialog 指针传入;而 sipmsg 则是我们要发送的 SIP 消息的 C 结构体,使用 osip_message_to_str 将其 按 RFC 文档格式转换为一个字符串(osip 中的 parser 模块的主要功能) ,再通过任意 你自己的网络数据发送函数使用 send_sock 发送给 dest_so

9、cket_str 和 dest_port 指定的 目标,当然,要记得使用 osip_free 释放刚才发送出去的字符串占用的内存,Osip 中很 多 osipparser 提供的消息解析处理函数都是动态内存分配的,使用完毕后需要及时释 放;使用 osip_set_cb_send_message 成功设置回调函数,我们的 SIP 消息就有了出口了, 下面继续分析(当然,了解到了上面的流程,也可以手工指定了) 。下面的回调函数分为三类,分别是普通事务消息(osip_message_callback_type_t 中定义)的处理回调函数、事务销毁事件(osip_kill_callback_type_

10、t 中定义)的清理 回调函数以及事务执行过程中的错误事件(osip_transport_error_callback_type_t 中定义) 处理回调函数:先说简单的,事务销毁事件,事务正常结束(成功完成状态机流程)或由超时处 理函数强制终结等情况下均调用了这些回调函数,一般就是释放事务结构体,为 ICT,NICT,IST,NIST 各设置或共用一个回调函数均可,只要正确释放不再使用的内存 即可;错误处理函数则是在整个状态机执行过程中发生的任何错误的出口,一般用来安 插 log 函数方便调试,也可以直接设为空函数;而最关键的就是正常消息的处理回调函数了,其量是非常大的,但仔细分下类, 也和上面

11、的回调函数一样,也是分为四类,我们可有根据实际程序的需要来进行设置, 例如,SIP 电话机就不需要处理 OSIP_NIST_REGISTER_RECEIVED 这个 SIP 注册服 务器才需要处理的 Register 消息事件了,精简一下,如果只是要做一个只需要实现主 叫功能且不考虑错误情况的 UAC 的 Demo 软电话程序,则只需要设置如下几个事件 的回调函数:OSIP_ICT_INVITE_SENT 发出 Invite 开始呼叫OSIP_ICT_STATUS_1XX_RECEIVED 收到180OSIP_ICT_STATUS_2XX_RECEIVED 收到200OSIP_ICT_ACK_

12、SENT 发出 ack 确定呼叫OSIP_NICT_BYE_SENT 发出 bye 结束呼叫OSIP_NICT_STATUS_2XX_RECEIVED 收到200确认结束呼叫OSIP_NIST_BYE_RECEIVED 收到 bye 结束呼叫OSIP_NIST_STATUS_2XX_SENT 发出 200确定结束呼叫 而要增加接受呼叫的被叫 UAS 功能,则只需要增加如下事件:OSIP_IST_INVITE_RECEIVED 收到 invite 开始呼叫OSIP_IST_STATUS_1XX_SENT 发出180OSIP_IST_STATUS_2XX_SENT 发出200OSIP_IST_AC

13、K_RECEIVED 收到 ack 确认呼叫 具体的函数定义,则直接参考 osip_message_cb_t,osip_kill_transaction_cb_t,osip_transport_error_cb_t 即可,回调函 数的设置同上可以手工设置,也可以使用 Osip 提供的对应的 osip_set_xxx_callback 函 数; 发出发出 SIP 消息消息要发送 SIP 消息,从上面的分析可知有几个必要的条件,osip_messag_t 结构的待 发送消息,osip_dialog_t 结构体的 dialog 以及 osip_transaction_t 的事务;首先 osip_ma

14、lloc 新分配一个 dialog,使用 osip_to_init,osip_to_parse,osip_to_free 这类 parser 函数功能函数按 RFC 设置 call- id,from,to,local_cseq 等必要字段(原则是:后面生成实际 SIP 消息结构体要用到的字 段就需要设置) ,使用 osip_message_init 初始化一个 sipmsg,根据 dialog 来填充该结 构体(不同的消息填充的数据是不同的,没有捷径可走,只能看 RFC 根据需要填充字 段) ,如果要给 SIP 消息添加 Body 例如 SDP 段,需要使用 osip_message_set_

15、body,osip_message_set_content_type 函数,设置的值是纯文本,如 果是 SDP,Osip 有提供简单的解析和生成便捷函数例如 sdp_message_to_str,sdp_message_a_attribute_add,但只是简单的字符操作,要填充合法 的字段需要自己参考 SDP 的 RFC 文档,同样没捷径可走。现在我们有了两个必要条件了,还有最后一个也是最关键的部件,就是事务的创 建和触发, int osip_transaction_init(osip_transaction_t * transaction, osip_fsm_type_t ctx_type

16、,osip_t * osip, osip_message_t * request) 创建了一个新的事务,并自动根据事务类型、dialog 和 sipmsg 进行了初始化,最 重要的是它使用了_osip_add_ict 等函数,将本事务插入到全局的 osip_t 结构体的全局 FIFO 链表中去了,不同的事务类型对应不同的 FIFO,由前文可知,本类函数有四个, FIFO 也有四个,对应 ICT,NICT,IST,NIST,注意这个这里使用 osip_transaction_set_out_socket 把发送 sip 消息的 socket 接口配给该事务,方便自动调 用前面设置的发送消息回调函数使用它自动发送消息;前文提到了 transaction 里的 state 作为状态机的“状态”,要执行状态机,就需要有 “事件”来触发,事件结构体 osip_event_t 需要使用 osip_new_outgoing_sipmessage 来对 sipmsg 进行探测生成,设置正确的事件值,省却了我们手工设置的工作,它调用 evt_set_t

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号