Resiprocate协议栈分析
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1. SIP Stack 分析
5
1.1 Resiprocate SIP Stack 系统架构图示
6
7
8
1.2 FIFO 流的走向图
9
10
1.3 Sending datagram
11
1. 4 Process Incoming UDP
12
2. Application/DUM
设计浅析
抽象接口:CLASS HANDLED ,CLASS InviteSessionHandler(诸如此类) …… 对象之源:CLASS HANDLED(多态和控制的基础)…… 交互控制: CLASS Handle,CLASS HandleManager…… 概念封装成类典型:CLASS Dialog, CLASS DialogId, CLASS DialogSet, CLASS DialogSetId, CLASS InviteSession….. Utility 工具类:CLASS BaseCreator , CLASS DestroyUsage, CLASS Profile…… 流动之源:DialogUsageManager::process(),Dialog::dispatch(const SipMessage& msg)…… 状态机的位置:DialogUsageManager::incomingProcess,DialogSet::dispatch,Dialog::dispatch 在整个 Resiprocate 大家族中事务层概念1的体现是 TransactionUser 类, 而其真正的实 现和管理类就是 DialogUsageManager;从其: class DialogUsageManager : public HandleManager, public TransactionUser 能看出来; HandleManager 点出了 DialogUsageManager 的管理功能的本质, 并且管理各 种对象(Handle 是各类对象的句柄)。 在整个 Resiprocate 系统中不管是我们发出或者收到的 SIP Message 都是放进了先进先 出的队列然后不断轮询处理,这有点象 Windows 的消息系统,对应收发的消息 DUM 提供 事件通知的机制。 DUM 利用事件回调模型, 事件响应可以选择继承系列 XXXHandler 抽象 接口,并向 TU 注册,以实现 VISITOR 模式;我在另外的文档里也提到这是 Reactor (Dispatcher,Notifier)模式,应用程序开发者只负责实现具体事件处理程序,并在 反应器上注册它们 ----“好莱坞原则”。
1
也许是事务用户层 13
DialogUsageManager 是 sip 事务层管理类, 是一个大总管的角色; 看其 Makexxx 系列的 函数能明白它能发起一系列登陆、会话邀请的动作及其回复。
Dum 定义了很多句柄管理类,通过它我们能得到真实的对象,从而完成操作,这在事件 响应中非常有用。 在 Dum(DialogUsageManager)的类中基本上这样一条线(以 INVITE 为例): DialogUsageManager 产生 Dialog Set, Dialog Set 产生 Dialog, Dialog 产生 InviteSession; InviteSession 又分 Client InviteSession 和 Server InviteSession。 而上面的各个对象的 PROCESS 或者 DISPATCH 函数产生的各种状态的变化并触发相应事 件。 在 DUM 的 IM/PRESENSE 部分广泛使用 SUBSCRIBE/NOTIFY 的模式,目前协议的定义似乎 参照成熟的设计模式。 个人一直比较喜欢这段论述: session 有两种含义,一种是传统意义上的 RTP 会话,一种是信令意义上的会话。SIP 中的会话指后一种,在层次上它在 dialog 之上,也就是 dialog 可以看成 session 的组 成单元。二者的分别主要基于目前出现的 subscription 应用,对于 session 和 subscription 可以共享一个 dialog,dialog 由基本的会话标识组成,如 Call-ID,From-Tag,To-Tag,以及一些目的 target 等共性单元组成。而 session 除了具 备这些单元外,包含 INVITE 建立起的会话其他内容,例如 INVITE 引起的状态机处理内 容、PRACK 处理记录等内容。有一个最为重要的区别是:Session 是完成了 SDP 的 Offer-Answer 过程,也就是此时双方可以进行双向的 RTP 传输了。而 Dialog 只是双方 建立了联系,这个联系是通过 Dialog Context 来记录的。在 Dialog 状态下双方不一定 可以作双向的 RTP 传输。所以必定是 Dialog 在前,而 Session 在后,但两者可以同时 一起建立。 Session 是基于 SDP Message 的交互,没有 SDP 的交互,就没有 Session。 而 Dialog 是基于请求消息中的 Header Field 进行交互。因此两者在层次上也是不一样 的。
事务用户层(Transaction User)
事务层(Transaction )
传输层(Transport)
语法与编码层(Syntax and
Enபைடு நூலகம்oding)
1
关于 Resiprocate 设计
首先祭出这面大旗,”类是对概念的描述,面向接口编程;封装变化的概念。”---这 不是我讲的,是大师们的口水。 Resiprocate 中大部分类就是对 RFC3261 各种 SIP 元素、 组件的封装, 并且也体现了 RFC 协议设计的层次。 在面向对象的设计中我们首先就要厘清问题域的所在; SIP Stack 的设计就是要充分 考虑完整展现 RFC 定义的各种元素和概念以及让这些独立而又关联的元素互动起来成为 一个活的系统。 可以这样来考虑,比如我们知道 RFC 定义了一个 SIP MESSAGE 的概念;下面是从 RFC 文档拷贝的内容: SIP 消息 = 起始行 *消息头部 CRLF(空行) [消息体]
3
式对对象的间接管理是老外的惯用伎俩啦,关于句柄设计从大师 BS 的著作到 <<Effective C++>>的 Handle_Body 论和<<C++沉思录>>的大段描述再到<<C++ Model Design>>都有发挥和外延,感兴趣可以观之。 插播: 源码中的大量 Clone 函数是模仿大师 BS 的虚拟构造函数一说,是原型模式的体现; 源码中对同步的封装值得借鉴,其中有“资源开始即初始化”理论的体现;在 DUM 部分 回调机制所遵循的著名“好莱坞原则”;句柄和代理的一个特点就是重载了 operator->、
协议栈的层次
SIP 为应用层(Application-Layer)的协议,所以不需要改变操作系统便可以支持。SIP 已经获得 3GPP (Third GenerationPartnership Project)、3GPP2 (Third Generation Partnership ProjectNumber 2)等机构认证,成为未来第三代行动通讯 (3G) 的标准。 下面是 SIP 的分层图示,IETF 坚持分层,不同模块功能相对独立,各层之间松散耦合。
operator*等;源码中也非常注重效率如
Sip Core 部分中大量 Hash 表的建立。
T* operator->() { return get(); }
const T* operator->() const { return get(); }
T& operator-> () { return *get(); }
在整个的协议栈架构中 SipStack 处于承上启下的位置,它既面向 DUM 层(表现为向 DialogUsageManager 服务)又可以直接为外界(如 UI)所用;列举其主要面向外界的接口函数:
/**
Adds a TU to the TU selection chain. Tu's do not call receive or
const T& operator*() const { return *get(); }
Handled::Handled(HandleManager& ham) : mHam(ham), mId(Handled::npos) { mId = mHam.create(this); 4
}
Handled::Id
建议:利用 CRC 卡片的方式去记录理解 Resiprocate 中的大量的类及其关系。CRC:类、 职责、协作。
部分设计的理解
OBSERVER/VISITOR/COMMAND/ITERATOR 模式,工厂模式(大量容器的使用也是一种变体 如:DialogSet),代理类句柄类(界面实现分离,隐藏实现…),…… 大量的界面类(如 AppXXX 系列)是遵循大师 BS“界面和实现分离”的原则吧;而句柄方
/// Responsible for routing messages to the correct TU based on installed rules
TuSelector mTuSelector; 把 SipStack 中的 Transaction User 角色独立出来交与一个独立的类管理是个不错的选择。 消息的流向分向两端,一路向下直达 Transport 层而去,一路向上提交 Transaction User 直至 UI。 19
注释基本上已经讲的很清楚,我就补充其交互的细节吧。这个函数基本上能让我们看到 TU 和 SipStack 交 互间其 visitor/observer 模式的影子。
void SipStack::registerTransactionUser(TransactionUser& tu) { mTuSelector.registerTransactionUser(tu); } 回溯 SipStack 的成员变量:
HandleManager::create(Handled* handled) { mHandleMap[++mLastId] = handled;// typedef HashMap<Handled::Id, Handled*> HandleMap; //HandleMap mHandleMap; return mLastId; }
下图是 DUM 中各种对象实例间的关系表示:
14
DUM 中几个重要的类图:
15
16
17
18
3. RESIPROCATE SIP Core 重要模块的简单 介绍
SipStack 模块
SipStack 是 Sip Stack Core 的面向外界的接口; 可以说它是 Sip Stack Core 的外覆类(wrapper) 或者是界面类(以大师 BS 的观点来看),它是和外界交互的窗口和协议,具体的实现又分散到更 具体的实现类和层次。
因此 SIP Message 这个概念元素还包括了更多的元素和概念;SIP Message 中我们能抽
2
象出更通用的概念我们暂且叫它 Message; 起始行的概念 E 文 Request Line 以及 Status Line 又包括了很多消息头(这是包容的关系),SIPURL 也包括消息头,等等,还有什 么参数什么的元素呢;当我们在考虑和提炼这些概念和元素的时候,我们思考怎么抽象 他们呢,它们又有什么基本的元素及其共性呢?他们之间的关系如何组织呢? Resiprocate 的源码告诉了我们如何去设计和封装这些概念的上佳实现。 在 Resiprocate 中一些 RFC3261 中定义元素的对应:
receiveAny, the SipStack will call postToTu on the appropriate Tu. Messages not associated with a registered TU go into SipStack::mTuFifo. */ void registerTransactionUser(TransactionUser&);