自研H323协议栈设计

一、 研制背景

当前MCU、终端所用的协议栈为开源H323Plus(原OpenH323)以及Opal(Open Phone Abstract Layer),这两种协议栈有以下弊端:
1. 协议栈代码较庞大,70万行代码,很难在短时间内全部了解清楚;
2. 协议栈基于面向对象的技术设计实现,如C++的模板、设计模式在其中,反而对协议理解产生障碍,且调试起来也较复杂;
3. 协议栈大量使用动态内存分配,在使用过程中,由于多线程析构不当或是插件调用不当,经常出现线程死锁、空指针异常、内存泄漏三类现象;
4. 协议栈中信令处理、媒体处理(包含媒体采集与显示回放)、业务逻辑绑定非常紧,无法实现信令媒体的完全解耦。
体现在产品中,问题如下:
1. MCU在H.225正常链接挂断时,H.245的TCP连接仍处于半连接状态,资源没有回收,增加了程序出错的风险;
2. MCU偶尔会出现断会、切换卡顿、结束会议慢三种异常现象,初步分析与线程死锁、空指针异常、内存泄漏有关;
3. 终端的协议栈应用程序(CallCore)发生过无故退出,且该进程所绑定的媒体处理(包含采集编码发送与接收解码显示)一旦发生异常,协议栈应用程序会死锁成为僵尸进程,错误复现率低,很难排查出故障。
为了解决以上问题,准备自己模仿编写H323协议栈。

二、 研制需求

为了规避之前开源协议栈的各种问题,自研H323协议栈在设计上需求如下:
1. 协议栈代码预估在10000行左右,除了引用ITU-T的定义类文件及asn1的parser程序外,代码大部分是学习asterisk的ooh323实现,代码照抄的部分经过剪裁,且最后使用的代码每行每句都进行理解与消化,并在函数名后注释函数流程;
2. 协议栈用C语言编写,不再基于面向对象技术,信令过程本质上是握手协商交互过程,面向过程即可满足需求;C语言实现的另一个好处是可以大概估算出内存占用大小,从而在程序初始化时就把内存分配好,C++由于其编译模型在不同平台上(Windows、Linux)的差异,较难估算内存占用情况(如虚函数表的内存占用);
3. 协议栈实现尽量用静态变量、栈内存或是其他事先分配好内存,少用动态分配的堆内存,避免分配释放带来的程序异常;
4. 协议栈实现上仅实现信令,并给媒体处理、外围控制提供回调接口,其中媒体处理回调函数的内部实现建议用父子进程的IPC方式,从而实现信令、媒体处理的完全解耦;外围控制回调函数的内部实现建议用socket的IPC方式,从而实现信令、业务逻辑的完全解耦。代码编写上尽量避免循环依赖,A模块被B模块调用,B模块被C模块调用,C模块则不能被A再调用,否则ABC就应该设计在一个模块中实现。

三、 设计思路

(一)、功能描述
从功能上来说,信令协议在多媒体通信处理框架中位置如下黄色部分所示:
图1 各协议所占层级

多媒体通信处理框架中每个部分说明如下:
(1). Socket,多媒体通信都是基于IP的TCP或UDP协议实现,所以最后都是通过Socket完成收发;
(2). Encrypt/Unencrypt,对信令的加密,如H.235、TLS;
(3). Encrypt/Unencrypt,对媒体的加密,如SRTP、ZRTP;
(4). Pack/Unpack,对信令的传输适配格式化,如ASN.1、XML;
(5). Pack/Unpack,对媒体的打包封装,如RTP\RTCP 、RFC3984、RFC7798;
(6). Signal Protocol,信令协议,如H.323、SIP;
(7). Media Codec,媒体编码协议,如H.264、H.265;
(8). Call Session,对呼叫链路、逻辑信道、媒体能力等抽象数据的封装;
(9). Call Application,基于呼叫的多媒体应用程序。
自研协议栈目前仅实现1\4\6\8部分。
(二)、设计想法
信令协议栈本质上是一个网络程序,从网络程序设计角度考虑分为网络层和业务逻辑层。
网络层是由2个tcp listen socket以及多个读写tcp socket组成(目前暂没考虑RAS),如下表所示:
H323所使用socket
业务逻辑层即是H.323协议本身,就是根据当前状态来发消息,或者收消息改变当前状态。
H.323协议栈的业务逻辑层与网络层

四、 程序实现

(一)、 模块设计
自研H323协议栈按照c语言.h/.c的同名称文件为一个模块,v0.1版本模块划分如下:
(1).ASN模块,实现ASN1的格式转译;
(2).Trace模块,实现基本的日志功能;
(3).Type模块,定义基本枚举类型,如主从确定、能力交换、挂断原因、呼叫模式,抽象定义呼叫选项结构体,抽象定义并实现定时器结构体以及定时器相关操作;
(4).Socket模块,跨平台封装Windows和Linux在Socket的的API;
(5).Capability模块,抽象定义能力、优先级、能力参数(Generic\H264)、H323端点能力集,接收通道发送通道的回调函数,并实现能力集添加/删除/合并/检验等功能;
(6).LogicalChannel模块,抽象定义逻辑通道结构体,并实现逻辑通道的增加/删除/查找/清除等功能;
(7).Channels模块,实现H225、H245以及消息通道Channel在Socket层的功能,实现了消息处理引擎,且全局定时器列表也在消息处理引擎维护;
(8).CallSession模块,定义并实现呼叫会话的全部相关信息,具体包括抽象定义呼叫状态、信道状态(H245)、媒体信息、呼叫通道、呼叫参数、会话的回调接口,并实现呼叫在创建/结束/清除过程中会话参数的设置、会话的Alias/e164/h323id的设置、会话的能力集的添加等功能;
(9).H323Endpoint模块,定义并实现一个H323端点的相关信息,具体包括抽象定义端点的数据结构,实现了H323端点初始化、销毁、端口范围设置、日志级别设置、端点的Alias/e164/h323id的设置、H225回调函数、H323回调函数、端点的呼叫能力集添加等功能,端点的作用域要大于会话的作用域,即端点的Alias/e164/h323id和能力集会包含会话的Alias/e164/h323id和能力集;
(10).H323Protocol模块,定义并实现RAS、Q931、H245的消息结构体、H225与H245消息处理回调接口,并实现所有H225、H245呼叫流程的协议交互;
(11).StackCmds模块,定义并实现外围控制消息结构体,实现外部消息的封装以及与消息处理引擎的交互。
(二)、 主要结构体设计
(1). CHRH323EndPoint
一个进程对应一个H323Endpoint实体,该实体可以表征MCU、终端、网守等等,结构体设计如下:

OOCTXT ctxt; /**内存上下文 */
OOCTXT msgctxt; /**消息相关的内存上下文*/
CHRH323Ports tcpPorts; /**tcp端口范围*/
CHRH323Ports udpPorts; /**udp端口范围*/
CHRH323Ports rtpPorts; /**rtp端口范围*/
int termType; /* 实体类型,50 终端,60 GK,70 带MC的终端, 120 MCU*/
int callType; /**呼叫类型 incoming/outgoing*/
struct chrH323EpCapability *myCaps; /**能力集*/
CHRH225MsgCallbacks h225Callbacks; /**H225回调函数*/
CHRH323CALLBACKS h323Callbacks;  /** H323回调函数*/
CHRSOCKET *listener; /** 1720 */
CHRH323CallData *callList; /**呼叫列表*/
CHRCallMode callMode; /**呼叫模式audio/audiorx/audiotx/video */
ASN1UINT callEstablishmentTimeout; /**呼叫建立定时器超时时间*/
ASN1UINT msdTimeout; /**主从确定定时器超时时间*/
ASN1UINT tcsTimeout; /**能力交换定时器超时时间*/
ASN1UINT logicalChannelTimeout; /**逻辑通道建立超时时间*/
ASN1UINT sessionTimeout; /**会话定时器超时时间*/
struct chrGkClient *gkClient; /**gk相关参数*/
CHRSOCKET cmdListener; /**命令字监听socket*/
CHRSOCKET cmdSock; /**新命令字连接socket*/
int cmdPort; /** 命令字监听端口 */
enum Q931InformationTransferCapability bearercap;/**Q931能力集*/

(2). CHRH323CallData
一个呼叫对应一个呼叫参数,一个进程可以有多个呼叫,由结构体本身的双向链表来增删遍历,结构体设计如下:

    OOCTXT               *pctxt; /** 上下文指针*/
    
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值