Resiprocate协议栈分析.docx
- 文档编号:11535358
- 上传时间:2023-03-19
- 格式:DOCX
- 页数:51
- 大小:625.97KB
Resiprocate协议栈分析.docx
《Resiprocate协议栈分析.docx》由会员分享,可在线阅读,更多相关《Resiprocate协议栈分析.docx(51页珍藏版)》请在冰豆网上搜索。
Resiprocate协议栈分析
协议栈的层次
SIP为应用层(Application-Layer)的协议,所以不需要改变操作系统便可以支持。
SIP已经获得3GPP(ThirdGenerationPartnershipProject)、3GPP2(ThirdGenerationPartnershipProjectNumber2)等机构认证,成为未来第三代行动通讯(3G)的标准。
下面是SIP的分层图示,IETF坚持分层,不同模块功能相对独立,各层之间松散耦合。
关于Resiprocate设计
首先祭出这面大旗,”类是对概念的描述,面向接口编程;封装变化的概念。
”---这不是我讲的,是大师们的口水。
Resiprocate中大部分类就是对RFC3261各种SIP元素、组件的封装,并且也体现了RFC协议设计的层次。
在面向对象的设计中我们首先就要厘清问题域的所在;SIPStack的设计就是要充分考虑完整展现RFC定义的各种元素和概念以及让这些独立而又关联的元素互动起来成为一个活的系统。
可以这样来考虑,比如我们知道RFC定义了一个SIPMESSAGE的概念;下面是从
RFC文档拷贝的内容:
SIP消息=起始行
*消息头部
CRLF(空行)
[消息体]
因此SIPMessage这个概念元素还包括了更多的元素和概念;SIPMessage中我们能抽
象出更通用的概念我们暂且叫它Message;起始行的概念E文RequestLine以及StatusLine又包括了很多消息头(这是包容的关系),SIPURL也包括消息头,等等,还有什么参数什么的元素呢;当我们在考虑和提炼这些概念和元素的时候,我们思考怎么抽象他们呢,它们又有什么基本的元素及其共性呢?
他们之间的关系如何组织呢?
Resiprocate的源码告诉了我们如何去设计和封装这些概念的上佳实现。
在Resiprocate中一些RFC3261中定义元素的对应:
建议:
利用CRC卡片的方式去记录理解Resiprocate中的大量的类及其关系。
CRC:
类、职责、协作。
部分设计的理解
OBSERVER/VISITOR/COMMAND/ITERATOR模式,工厂模式(大量容器的使用也是一种变体如:
DialogSet),代理类句柄类(界面实现分离,隐藏实现…),……
大量的界面类(如AppXXX系列)是遵循大师BS“界面和实现分离”的原则吧;而句柄方式对对象的间接管理是老外的惯用伎俩啦,关于句柄设计从大师BS的著作到<
插播:
源码中的大量Clone函数是模仿大师BS的虚拟构造函数一说,是原型模式的体现;源码中对同步的封装值得借鉴,其中有“资源开始即初始化”理论的体现;在DUM部分回调机制所遵循的著名“好莱坞原则”;句柄和代理的一个特点就是重载了operator->、operator*等;源码中也非常注重效率如SipCore部分中大量Hash表的建立。
T*operator->()
{
returnget();
}
constT*operator->()const
{
returnget();
}
T&operator->()
{
return*get();
}
constT&operator*()const
{
return*get();
}
Handled:
:
Handled(HandleManager&ham):
mHam(ham),
mId(Handled:
:
npos)
{
mId=mHam.create(this);
}
Handled:
:
Id
HandleManager:
:
create(Handled*handled)
{
mHandleMap[++mLastId]=handled;//typedefHashMap : Id,Handled*>HandleMap; //HandleMapmHandleMap; returnmLastId; } 1.SIPStack分析 1.1ResiprocateSIPStack系统架构图示 1.2FIFO流的走向图 1.3Sendingdatagram 1.4ProcessIncomingUDP 2.Application/DUM 设计浅析 抽象接口: CLASSHANDLED,CLASSInviteSessionHandler(诸如此类)…… 对象之源: CLASSHANDLED(多态和控制的基础)…… 交互控制: CLASSHandle,CLASSHandleManager…… 概念封装成类典型: CLASSDialog,CLASSDialogId,CLASSDialogSet,CLASSDialogSetId,CLASSInviteSession….. Utility工具类: CLASSBaseCreator,CLASSDestroyUsage,CLASSProfile…… 流动之源: DialogUsageManager: : process(),Dialog: : dispatch(constSipMessage&msg)…… 状态机的位置: DialogUsageManager: : incomingProcess,DialogSet: : dispatch,Dialog: : dispatch 在整个Resiprocate大家族中事务层概念的体现是TransactionUser类,而其真正的实现和管理类就是DialogUsageManager;从其: classDialogUsageManager: publicHandleManager,publicTransactionUser 能看出来;HandleManager点出了DialogUsageManager的管理功能的本质,并且管理各种对象(Handle是各类对象的句柄)。 在整个Resiprocate系统中不管是我们发出或者收到的SIPMessage都是放进了先进先出的队列然后不断轮询处理,这有点象Windows的消息系统,对应收发的消息DUM提供事件通知的机制。 DUM利用事件回调模型,事件响应可以选择继承系列XXXHandler抽象接口,并向TU注册,以实现VISITOR模式;我在另外的文档里也提到这是Reactor(Dispatcher,Notifier)模式,应用程序开发者只负责实现具体事件处理程序,并在反应器上注册它们----“好莱坞原则”。 DialogUsageManager是sip事务层管理类,是一个大总管的角色;看其Makexxx系列的函数能明白它能发起一系列登陆、会话邀请的动作及其回复。 Dum定义了很多句柄管理类,通过它我们能得到真实的对象,从而完成操作,这在事件响应中非常有用。 在Dum(DialogUsageManager)的类中基本上这样一条线(以INVITE为例): DialogUsageManager产生DialogSet,DialogSet产生Dialog,Dialog产生InviteSession;InviteSession又分ClientInviteSession和ServerInviteSession。 而上面的各个对象的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只是双方建立了联系,这个联系是通过DialogContext来记录的。 在Dialog状态下双方不一定可以作双向的RTP传输。 所以必定是Dialog在前,而Session在后,但两者可以同时一起建立。 Session是基于SDP Message的交互,没有SDP的交互,就没有Session。 而Dialog是基于请求消息中的HeaderField进行交互。 因此两者在层次上也是不一样的。 下图是DUM中各种对象实例间的关系表示: DUM中几个重要的类图: 3.RESIPROCATESIPCore重要模块的简单介绍 SipStack模块 SipStack是SipStackCore的面向外界的接口;可以说它是SipStackCore的外覆类(wrapper)或者是界面类(以大师BS的观点来看),它是和外界交互的窗口和协议,具体的实现又分散到更具体的实现类和层次。 在整个的协议栈架构中SipStack处于承上启下的位置,它既面向DUM层(表现为向DialogUsageManager服务)又可以直接为外界(如UI)所用;列举其主要面向外界的接口函数: /** AddsaTUtotheTUselectionchain.Tu'sdonotcallreceiveor receiveAny,theSipStackwillcallpostToTuontheappropriate Tu.MessagesnotassociatedwitharegisteredTUgointoSipStack: : mTuFifo. */ voidregisterTransactionUser(TransactionUser&); 注释基本上已经讲的很清楚,我就补充其交互的细节吧。 这个函数基本上能让我们看到TU和SipStack交互间其visitor/observer模式的影子。 void SipStack: : registerTransactionUser(TransactionUser&tu) { mTuSelector.registerTransactionUser(tu); } 回溯SipStack的成员变量: ///ResponsibleforroutingmessagestothecorrectTUbasedoninstalledrules TuSelectormTuSelector; 把SipStack中的TransactionUser角色独立出来交与一个独立的类管理是个不错的选择。 消息的流向分向两端,一路向下直达Transport层而去,一路向上提交TransactionUser直至UI。 因此接口类Message中存在这个函数就不足为奇啦: classMessage { 。 。 。 。 。 。 voidsetTransactionUser(TransactionUser*t){tu=t;} TransactionUser*getTransactionUser(){returntu;} TransactionUser*tu; }; 正是setTransactionUser给予消息TransactionUser归属。 而在TransactionState中我们将会看到SipMessage是如何兵分两路的: staticvoidsendToTU(TransactionUser*tu,TransactionController&controller,TransactionMessage*msg); voidsendToWire(TransactionMessage*msg,boolretransmit=false); 现在我们先重点关注一下sendToTU: void TransactionState: : sendToTU(TransactionUser*tu,TransactionController&controller,TransactionMessage*msg) { msg->setTransactionUser(tu); controller.mTuSelector.add(msg,TimeLimitFifo : InternalElement); } 上面探索了一下SipStack和TU层的交互都要跑远啦,让我们再回到SipStack看看这个界面类其他的迎来送往的窗口吧。 一、发送消息的两个重载函数: /** InterfacefortheTUtosendamessage.Makesacopyofthe SipMessage.Callerisresponsiblefordeletingthememoryandmaydo soassoonasitreturns.LooseRoutingprocessingasperRFC3261must bedonebeforecallingsendbytheTU.SeeHelper: : processStrictRoute @parammsgSipMessagetosend. @paramtuTransactionUsertosendfrom. */ voidsend(constSipMessage&msg,TransactionUser*tu=0); voidsend(std: : auto_ptr 再看了一下这两个函数体的实现比较简单,还是端上来吧: void SipStack: : send(constSipMessage&msg,TransactionUser*tu) { SipMessage*toSend=newSipMessage(msg); if(tu) { toSend->setTransactionUser(tu); } toSend->setFromTU(); mTransactionController.send(toSend); checkAsyncProcessHandler(); } mTransactionController.send(toSend)这一段才是我们值得关注的地方,很显然这是消息的去向,现在我们不用管它去向哪儿,我们知道它被转交给mTransactionController去具体完成任务,就象在一条生产线上我们把消息交给了下游或者另一个直管部门去处理。 SipMessage是我们投递出的邮件,从投向邮筒的那一瞬间,开始了它向各个驿站的传递;出于职责链上的各个类和对象是任务传递驿站的抽象和实现,是代码所表现出的和谐世界,当然如果是垃圾代码的话,那就是一个混乱的世界和杂物堆放的仓库。 checkAsyncProcessHandler()这是协议栈提供的异步消息处理的一种推荐方式,协议栈源码中只是实现了个大概,具体的异步处理细节需要根据具体情况而完成其实现类,此处再次体现了“封装变化的概念”的要诀。 因为异步处理句柄是指向抽象基类的指针: AsyncProcessHandler*mAsyncProcessHandler; 二、SendTo有好几个重载函数,看看注释再和Send比较一下就可耶。 /**thisisonlyifyouwanttosendtoadestinationnotintheroute.You probablydon'twanttouseit.*/ voidsendTo(std: : auto_ptr voidsendTo(std: : auto_ptr voidsendTo(constSipMessage&msg,constUri&uri,TransactionUser*tu=0); voidsendTo(constSipMessage&msg,constTuple&tuple, TransactionUser*tu=0); 三、就如在Win32编程中有SendMessage和PostMessage一样,SipStack消息分发中也有一个Post。 /** MakesthemessageavailabletotheTUatsomelatertime-specifiedin seconds. Note: TranasactionUsersubclassescanjustposttothemselves. @parammessageApplicationMessagetopost @paramsecondsLaterNumberofsecondsbeforemessageistobeposted. @paramtuTransactionUsertopostto. */ voidpost(conststd: : auto_ptr unsignedintsecondsLater, TransactionUser*tu=0); voidpostMS(conststd: : auto_ptr unsignedintms, TransactionUser*tu=0); voidpost(constApplicationMessage&message); voidpost(constApplicationMessage&message,unsignedintsecondsLater, TransactionUser*tu=0); /** MakesthemessageavailabletotheTUatsomelatertime-specifiedin milli-seconds.MakesacopyoftheApplicationMessage.Calleris responsiblefordeletingthememoryandmaydosoassoonasitreturns. Note: TransactionUsersubclassescanjustposttothemselves. @parammessageApplicationMessagetopost @parammsNumberofmilli-secondsbeforemessageistobeposted. @paramtuTransactionUsertopostto. */ voidpostMS(constApplicationMessage&message,unsignedintms, TransactionUser*tu=0); ApplicationMesage基本上是个结点类,因此可以自定义自己的消息类,然后自己管理;因为我们可以看到Post出去的消息更多的是交给TU去处理,TU层就在应用层隔壁。 四、下面的函数,非常容易看明白。 /** RetrieveaSipMessageofftheoldTuFifo.Callernowownsthememory.Returns 0ifnothingthere.SincetheadditionofTransactionUsers,thismethod isdeprecated.ThisonlylooksintotheoldTuFifothatisnotassociated withanyTransactionUser. Note: Applicationspostingnon-sipmessagesmustusereceiveany.Ifnon SipMessagesareontheFifo,thentheyarejustdeleted. @deprecated @returnspointertoreceivedSipMessage,0ifnothingthere. */ SipMessage*receive(); /** RetrieveaMessageofftheoldTuFifo.Callernowownsthememory.Returns 0ifnothingthere.SincetheadditionofTransactionUsers,thismethod isdeprecated.ThisonlylooksintotheoldTuFifothatisnotassociated withanyTransactionUser. Note: Applicationspostingnon-sipmessagesmustusereceiveany.Ifnon SipMessagesareontheFifo,thentheyarejustdeleted. @deprecated @returnspointertoreceivedMessage,0ifnothingthere.Mayreturn TransactionTerminated*,TimerMessage*,SipMessage*orderived ApplicationMessage* */ Message*receiveAny
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Resiprocate 协议 分析