-
exosip2
协议栈学习总结
1
、
exosip2
协议栈
介绍
eXosip
是
Osip2
的一个扩展协议集,
它部分封装了
Osip2
协议栈,
使得它更容易被使用。
使用
sip
协议建立多媒体会话是一个复杂的过程,
exosip
库开发的目的在于隐藏这种复杂
性。正如它的名称所表示的,
eXosip2 - the eXtended osip
Library
,它扩展了
osip
库,
实现了一个简单的高层
API
。通
过使用
exosip
,我们可以避免直接使用
< br>osip
带来的困难。
需要注意,
exosip
并不是对
osip
的简单封装包裹,
而是扩展。
Osip
专注于
sip
消息的解
析,
事务状态机的实现,
而
exosip
则基于
osip
实现
了
call
、
options
、
register
、
publish
等更倾向于功能性的接口。当然,这些实现都是依赖于底层
osip
库已有的功能的。
2
、
exo
sip
的模块构成
2.1
底层连接管理
extl.c
、
extl_udp.c
、
extl_tcp.c
、
extl_dtls.c
、
extl_tls.c
是与网络连接有关的
文件。
实现了连接的建立,数据的接收以及发送等相关的接口。其中,
< br>extl_udp.c
为使用
UDP
连
接的实现,
extl_tcp.c
为使用
TCP
连接的实现。
Extl_dtls.c
以及
extl_tls.c
都是使用安
全
socket
连接的实现。
2.2
内部功能模块实现
Jauth.c<
/p>
、
jcall.c
、
jdialog.c
、
jevents.c
、
jnotify.c
、
jp
ublish.c
、
jreg.c
、<
/p>
jrequest.c
、
jrespon
se.c
、
jsubscribe.c
等文件实现了内部对一些模块的管理,
这些模块正如其文件名
所表示的,
jauth.c
主要是认证,
jcall.c
则是通话等等。
2.3
上层
API
封装实现
Excall_api.c
、
exinsubsription_api.c
、
exmessag_api.c
、
exoptions_api.c
、
expublis
h_api.c
、
exrefer_api.c
、
exregister_api.c
、
exsubsribtion_api.c
这几个以
api
为后缀的文件,
p>
实现各个子模块的管理。
应用程序可以调用这里提供的接口,
方便的构造或
者发送
sip
消息。
2.4
其他
Inet_ntop.c
实现
ip
地址的点分十进制与十六进制表示之间的转换。
Jcallback.c
实现一堆回调函数,
这些回调函数就是用来注册到
osip
库的。
我们使用
exosip
库,就是避免直接使用
osip
库,
因为一些工作
exosip
p>
已经帮我们做了,
所以这样一来,
可
以简化上层的实现。
Udp.c
文件主要用来对通过
UDP
连接接收到的消息进行分类处理。
Exutilis.c
文件实现一些杂项的函数。
有
ip <
/p>
地址到字符串之间的转换,
域名的解析等一些
辅助的功能函数。
Exconf.c
文件实现了
exosip
的初始化相关的接口,包括后台任务的实现。实际上是
“
configuration
api
”的实现。
Exosip.c
文件实现了与
exconf.c
文件相似的功能。比如管道的使用,
exosip
上事务的创
建和查找,
register
和
subscribe
的更新,认证信息的处理等。
p>
3
、
exosip
关键数据结构及其说明
1
3.1 eXtl_protocol
eXtl_protocol <
/p>
是为实现网络通信专门定义的一个
数据结构,包括了变量和方法两
部分。其中,变量包
括了建立网络连接过程中使用的
ip
p>
地址、端口等;
方法部分封装了网络
soc
ket
编程常用的系统调用接
口。
<
/p>
代码中定义了四个该数据结构体的全局变量:
eXtl_udp<
/p>
、
eXtl_tcp
、
< br>eXtl_tls
以及
eXtl_dtls
。
分别针对使用
UDP
、
TCP
以及安全加密连接进行了实
现。
3.2 eXosip_call_t
Exosip_call_t
定义了
call
相关的信息,
包括
call
的
id
,
call <
/p>
的
dialogs
,
call
上
incoming
的
事务和
outgoing
的事务。
另
外,
还包括了前向和后向指针,所以,所有的
call
可以通过该结构
体串接起来。
3.3
eXosip_dialog_t
exosip_dialog_t
包含了
dialog
相关的信息。
2
3.4 eXosip_reg_t
用来管理
Register
模块
3.5 eXosip_subscribe_t
用来管理
subscribe
模块
3.6
eXosip_pub_t
用来管
理
publish
模块
3.7
eXosip_notify_t
用来管
理
notify
模块
3.8
jinfo_t
这个结构体关联了
dialog
、
call
、
subscribe
以及
notify
几个结构体
3
3.9
eXosip_event_t
与
event
< br>有关的结构体。这个结构体主要用来在应用
层和
exos
ip
之间通信。
Exosip
在处
理事务的过程中,如果
需要将结果反馈给上层应用,则会生成如上结构类型的事
件,并将其放到
exosip
的事件队列中。
应用层会不断循环
从事件队列中读取事件,然后进行应用层的处理。
3.10 eXosip_t
exosip_t
是
exosip
中最重要的结构体之一。从图可以看出,
这个结构体比较大,其
中包含了
exosip
中用到的各个子模块
< br>的结构。比如
call
、
reg
、
pub
等等。代码中定义了一个该
结构类型的全局变量,通过该全局变量,就可以对
exosip
前
的状态进行掌控
(许多相关的信息要
么包含在该结构上,
要么
可以通过该结构找到)。
Extl
是
eXtl_protocol
类型的指针,保存了网络接口类。
J_osip
保存了
osip
初始化时返回的
osip
结构体。
J_transactions
一般是等待释放的事务。
p>
在事务经过
osip
处
< br>理完后,
不再需要时,
exosip
会将其放在
j_transactions
上,
等待释放。
p>
4
、
exosip
的初始化
Exosip
的初始化有两部分组成,这主要是从使用
exosip
的角度看。
4.1
对
exosip
全局结构体变量的配置
这步通过调用接口
eXosip_init
完成。主要完成工作如下:
4.1.1
初始化条件变量和互斥信号量。
4.1.2
调用
osip_init
初始化
osip
库,并将生成
osip
结构体给
p>
exosip
,同时也让
osip
的
4
application_contexgt
指针指向
exosip
,也就是二者相互指向。
4.1.3
调用
eXosip_set_callbacks
设置
osip
的回调函数,所以回调函数都是
exosip
自己实
现。
4.1.4
调用
jpipe
创建通信用的
pipe
,
之前已经说了,
对于
windows
平台,
是通过
socket
接
口模拟实现的。
4.1.5
初始化其上的事务和事件队列。主要,这不同于
osip
的事务和事件队列。
4.1.6
调用
extl
指向的结构体的
init
函数指针,初始化网络接口。
4.2
在
socket
接口上进行监听
这步通过调用
eXosip_listen_addr
接口完成。
主要完成工作如下:
4.2.1
将
eXosip
全局变量的
eXtl
指针指向
eXtl_udp
全局变量。
4.2.2
根据参数,配置
extl_protocol
和
exosip
上有关
ip
端口地址等信息。另外,
调用
extl_udp
的
tl_ope
n
函数指针,
完成在本机指定的端口上监听连接的工作。
p>
需要注意的是,
虽
然是监听,
但是使用的
UDP
来建立连接的,
所以消息的
recv
和发送在同一个
socket
上完成
。
在
osip
中设置的
out_socket
并不会起作用。
4.2.3
调用
osip_thread_create
创建
exosip
后台任务,
用于驱动
osip
的状态机。
(
在
os
ip
中,
在发送
sip
消息部分,提到将
9
个函数放到一个线程中执行,
exosip
就是这样做的)
下面展示了初始化的示例代码:
include
int i;
TRACE_INITIALIZE (6,
stdout);
i=eXosip_init();
if
(i!=0)
return -1;
i =
eXosip_listen_addr (IPPROTO_UDP, NULL, port,
AF_INET, 0);
if (i!=0)
{
eXosip_quit();
fprintf
(stderr,
return -1;
}
... then you have to send messages and
wait for eXosip events...
这样,在初始化完成后,我们
基本上完成了对内存中所用数据结构的配置,同时启动了
一个后台任务负责
osip
状态机的驱动。
5
、数据收发整体框架
5.1
接收过程
< br>在初始化过程中我们创建了一个后台任务,现在可以看看这个后台任务都做了哪些操作。
< br>
任务的执行函数为
_eXosip_thread
p>
,在该接口中,循环不断的调用
eXosip_execute
p>
。在每一次
的
eXosip_execute
执行中,完成如下的工作:
a
.
首先计算出底层
osip
离当前时间最近的超时时间。也就是查看底层所有的超时事件,
5