Osip2
是一个开放源代码的
sip
协议栈,是开源代码中不多使用
C
语言写的协议栈之一,它具有短小简洁的特点,专注于
sip
底层解析使得它的效率比较高。
eXosip是Osip2的一个扩展协议集,它部分封装了Osip2协议栈,使得它更容易被使用。
一、
介绍
Osip2
是一个开放源代码的
sip
协议栈,是开源代码中不多使用
C
语言写的协议栈之一,它具有短小简洁的特点,专注于
sip
底层解析使得它的效率比较高。但缺点也很明显,首先就是可用性差,没有很好的
api
封装,使得上层应用在调用协议栈时很破碎;其次,只做到了
transaction
层次的协议过程解析,缺少
call
、
session
、
dialog
等过程的解析,这也增加了使用的难度;再次,缺少线程并发处理的机制,使得它的处理能力有限。
eXosip
是
Osip2
的一个扩展协议集,它部分封装了
Osip2
协议栈,使得它更容易被使用。
eXosip
增加了
call
、
dialog
、
registration
、
subscription
等过程的解析,使得实用性更强。但是
eXosip
局限于
UA
的实现,使得它用于
registrar
、
sip server
等应用时极其不容易。另外,它并没有增加线程并发处理的机制。而且只实现了音频支持,缺少对视频和其它数据格式的支持。
综合来说,
Osip2
加上
eXosip
协议栈仍然是个实现
Sip
协议不错的选择。当然需要根据不同的需求来增加更多的内容。
二、
Osip2
协议栈的组成
Osip2
协议栈大致可以分为三部分:
sip
协议的语法分析、
sip
协议的过程分析和协议栈框架。
1、Sip
协议的语法分析:
主要是
osipparser2
部分,目前支持
RFC3261
和
RFC3265
定义的
sip
协议消息,包括
INVITE
、
ACK
、
OPTIONS
、
CANCEL
、
BYE
、
SUBSCRIBE
、
NOTIFY
、
MESSAGE
、
REFER
和
INFO
。不支持
RFC3262
定义的
PRACK
。
遵循
RFC3264
关于
SDP
的
offer/answer
模式。带有
SDP
的语法分析。
支持
MD5
加解密算法。支持
Authorization
、
www_authenticate
和
proxy_authenticate
。
2、Sip
协议的过程分析:
主要是
osip2
部分,基于
RFC3261
、
RFC3264
和
RFC3265
的
sip
协议描述过程,围绕
transaction
这一层来实现
sip
的解析。
Transaction
是指一个发送方和接收方的交互过程,由请求和应答组成。请求分为
Invite
类型和
Non-Invite
类型。应答分为响应型的应答和确认型的应答。响应型的应答是指这个应答仅代表对方收到请求。请求经过处理后都必须返回确认型的应答。响应型的应答有
1xx
,确认型的应答包括
2xx
、
3xx
、
4xx
、
5xx
和
6xx
。一个
transaction
由一个请求和一个或多个响应型应答、一个确认型应答组成。
Transaction
根据请求的不同和发送
/
接收的不同可以分为四类:
ict
、
nict
、
ist
和
nist
。
Ict
是指
Invite client transaction
,就是会话邀请的发起方。
Nict
是指
Non-Invite client transaction
,是指非邀请会话的发起方。
Ist
是指
Invite server tranaction
,是指会话邀请的接收方。
Nist
是指
Non-Invite server transaction
,是指非邀请会话的接收方。
每种类型的
transaction
都有自己相应的状态机,
Osip2
协议栈根据状态机来处理所有的
sip
事件,所以这部分就是整个协议栈的核心。但是因为
Osip2
只做到
transaction
这一层,所以它可以忽略掉
call
、
registration
等应用的复杂性,显得相当简单,这就使得需要使用它的应用必须要自己处理应用的逻辑。必须注意的一点是,
transaction
的资源在
Osip
里是由协议栈负责释放的,但是在
Osip2
里改成由使用的应用负责释放。
下面简单的用时序图来描述四种
transaction
的状态机,只着重于描述状态间的转换,忽略了调用的处理函数,也简化了很多没有状态变换的事件。也就是说,每个状态下定义的事件并没有完整的表现在图中,不要以为这些事件没定义或在该状态下没有处理。
图中方框里的是状态名,箭头线上的是触发状态变换的事件名称。同一个状态下的事件并没有时序关系。
Ict
的状态机如下:
(图略)
Nict
的状态机如下:
(图略)
Ist
的状态机如下:
(图略)
Nist
的状态机如下:
(图略)
3、协议栈框架:
框架并不是指代码的某一部分,而是指它的构成形式。主要有三部分:底层套接字接收
/
发送,模块间通信管道,上层调用
api
接口。
Osip2
并不实现底层套接字的接收
/
发送,由
eXosip
实现,现在只支持
UDP
的链路连接。
模块间的通信管道包括:
transaction
的消息管道、
jevent
的消息管道。
Transaction
的消息管道是驱动其状态机的部件,通过不断的接收来自底层套接字的远端信令,或者来自上层调用的指令,根据上述的状态机制来驱动这个
transaction
的运转。
Jevent
的消息管道是
eXosip
实现的,用于汇报底层事件,使得调用程序能处理感兴趣的事件。
上层调用的api接口大致有两类:sip协议的调用接口和sdp协议的调用接口。EXosip封装了大部分的sip协议调用接口,一般来说都不需要直接调用osip2的接口函数。接口函数很多,在这里就不详述了,函数定义请参照源代码部分的注释。
三、
eXosip
协议栈的分析
eXosip
是
Osip2
协议栈的封装和调用。它实现了作为单个
sip
终端的大部分功能,如
register
、
call
、
subscription
等。
EXosip
使用
UDP socket
套接字实现底层
sip
协议的接收
/
发送。并且封装了
sip
消息的解释器。
EXosip
使用定时轮循的方式调用
Osip2
的
transaction
处理函数,这部分是协议栈运转的核心。透过添加
/
读取
transaction
消息管道的方式,驱动
transaction
的状态机,使得来自远端的
sip
信令能汇报给调用程序,来自调用程序的反馈能通过
sip
信令回传给远端。
EXosip
增加了对各个类型
transaction
的超时处理,确保所有资源都能循环使用,不会被耗用殆尽。
EXosip
使用
jevent
消息管道来向上通知调用程序底层发生的事件,调用程序只要读取该消息管道,就能获得感兴趣的事件,进行相关的处理。
EXosip
里比较重要的应用有
j_calls
、
j_subscribes
、
j_notifies
、
j_reg
、
j_pub
、
osip_negotiation
和
authinfos
。
J_calls
对应呼叫链表,记录所有当前活动的呼叫。
J_reg
对应注册链表,记录所有当前活动的注册信息。
Osip_negotiation
记录本地的能力集,用于能力交换。
Authinfos
记录需要的认证信息。
四、
总结
本文是从使用的角度去阐述分析Osip2和eXosip协议栈,并不涉及很多的细节,需要进一步了解协议栈的结构和实现,可参考《osip》一文。