Q/CT XXXX.1-2008
在transaction的匹配中,根据RFC3261的最新sip协议的描述,由topvia的branch_id是否相同来匹配,如果相同,就是同一个transaction的请求和应答及ACK,为兼容旧版本的transaction的匹配规则,同时支持根据call_id, cseq, from_tag, to_tag来匹配transaction。如下图,为便于管理的transaction,所有的transaction保持在osip_t结构的四条链表中,按照处理流程的不同分为发送出去的INVITE类型请求和应答、其它类型请求和应答,接收到的INVITE请求和应答、其它请求和应答。
struct osip {
void *application_context; /**< User defined Pointer */
/* list of transactions for ict, ist, nict, nist */
osip_list_t osip_ict_transactions; /**< list of ict transactions */ osip_list_t osip_ist_transactions; /**< list of ist transactions */ osip_list_t osip_nict_transactions; /**< list of nict transactions */ osip_list_t osip_nist_transactions; /**< list of nist transactions */ ……
#if defined(HAVE_DICT_DICT_H)
dict *osip_ict_hastable; /**< htable of ict transactions */ dict *osip_ist_hastable; /**< htable of ist transactions */ dict *osip_nict_hastable; /**< htable of nict transactions */ dict *osip_nist_hastable; /**< htable of nist transactions */ #endif };
osip_find_transaction_and_add_eventosip_find_transaction__osip_find_transaction根据message的cseq中的method和status确定在osip的哪条transaction链表中进行匹配osip_transaction_find是否添加event到transaction队列no退出Yes添加event到transaction队列 中国IMS网络SIP协议规范总体技术要求 - 17 -
Q/CT XXXX.1-2008
在transaction的匹配过程中,如果是发出的请求,因为本地的transaction都会分配一个不重复的transaction_id,所以只需要比配transaction_id即可;对于incoming的message,如果是request,则匹配branch_id或者为兼容前面版本进行transaction的比配,按照协议RFC3261的17-2-3节的方式进行匹配;如果incoming的message是response,则匹配branch_id或根据RFC3261的17-1-3节的规则进行匹配。
osip_transaction_findEVT_IS_INCOMINGREQYesnoHAVE_DICT_DICT_HYesEVT_IS_INCOMINGRSPYesno__osip_transaction_matching_request_osip_to_xist_17_2_3遍历transaction匹配transactionidnoTop_via中有branch_idHAVE_DICT_DICT_HnoyesInvite or ACKno__osip_transaction_matching_response_osip_to_xict_17_1_3YesnoTop_via中有branch_idyesInvitenoyesdict_search(osip->osip_ist_hastable,...)dict_search(osip->osip_nist_hastable,...)yesnodict_search(osip->osip_nist_hastable,...)dict_search(osip->osip_ist_hastable,...)
3.5
osip中dialog的管理
dialog的相关的管理操作包括dialog的初始化建立过程,dialog的销毁free过程,以及dialog的匹配。此外dialog中保存了相关的路由信息和cseq信息。
Dialog结构如下,由call_id、local_tag和remote_tag唯一确定一个dialog:
struct osip_dialog {
char *call_id; /**< Call-ID*/ char *local_tag; /**< local tag */ char *remote_tag; /**< remote tag */ osip_list_t route_set; /**< route set */
中国IMS网络SIP协议规范总体技术要求 - 18 -
Q/CT XXXX.1-2008
int local_cseq; /**< last local cseq */ int remote_cseq; /**< last remote cseq*/ osip_to_t *remote_uri; /**< remote_uri */ osip_from_t *local_uri; /**< local_uri */ osip_contact_t *remote_contact_uri; /**< remote contact_uri */
int secure; /**< use secure transport layer */
osip_dialog_type_t type; /**< type of dialog (CALLEE or CALLER) */
state_t state; /**< DIALOG_EARLY || DIALOG_CONFIRMED || DIALOG_CLOSED */ void *your_instance; /**< for application data reference */ };
在dialog的初始化时,需要根据是client端或server端来确定dialog结构中的call_id、local_tag和remote_tag的值。根据是client端或server端来确定dialog的type,并且设置dialog的状态。当做为client端,并且是在接收到发出的request的response时,调用osip_dialog_init_as_uac进行初始化dialog;如果是接收到server端发送过来的request,则调用osip_dialog_init_as_uac_with_remote_request进行dialog的初始化。如果是server端,调用osip_dialog_init_as_uas进行初始化dialog。
在dialog的匹配时,当是client端时,调用osip_dialog_match_as_uac进行匹配。检查接收到的response和dialog中的call_id,to_tag和from_tag是否匹配,如果全部匹配,则匹配到了该dialog。为兼容前面的版本,在dialog的to或者接收到的message的to header没有tag的情况下,比较dialog和message的from_uri, to_uri。如果匹配,则同样匹配的dialog。
当是server端时,调用osip_dialog_match_as_uas进行匹配。其匹配方法与client端的匹配方法相同。
对from_tag和to_tag的匹配处理,在transaction的匹配过程中同样使用到。 4
Exosip包的源代码框架解析
在exosip源代码包中包含了提供给上层管理软件调用的关于call、message、option、refer、register、subscription、publish和insubscription的API,这些API的实现都在ex开头的c文件中。
中国IMS网络SIP协议规范总体技术要求 - 19 -
Q/CT XXXX.1-2008
为这些接口进行服务的函数,包括和osip lib库进行通信的部分的实现在以j开头的源文件中如jcall.c,其中jrequest.c和jresponse.c实现了request和response的message的通用构造实现。
同时exosip实现了传输层的四种不同的传输方式供上层的sip协议栈进行选择,分别为extl_dtls.c、extl_tcp.c、extl_tls.c和extl_udp.c,它们以注册的方式在Lib库启动的时候注册到lib库的钩子中。
为了支持多线程间的通信,在两个线程间采用pipe的方式进行实现,如果没有使用多线程,这部分源代码在编译时会被屏蔽掉。
对接收到的message进行的逻辑处理在文件udp.c中,这部分是整个协议栈逻辑比较复杂的地方。需要根据sip协议栈的标识描述和代码实现框架进行整理的把握。 4.1
Lib库的初始化和销毁
整个sip 的lib库有一个总的管理结构struct exosip_t eXosip,该全局变量在lib库被使用之前需要初始化,初始化函数为exconf.c文件的eXosip_init函数。Exosip_t结构如下:
struct eXosip_tt {
struct eXtl_protocol *eXtl; char transport[10]; char *user_agent;
eXosip_call_t *j_calls; /* my calls */ #ifndef MINISIZE
eXosip_subscribe_t *j_subscribes; /* my friends */ eXosip_notify_t *j_notifies; /* my susbscribers */ #endif
osip_list_t j_transactions;
eXosip_reg_t *j_reg; /* my registrations */ #ifndef MINISIZE
eXosip_pub_t *j_pub; /* my publications */ #endif
#ifdef OSIP_MT void *j_cond; void *j_mutexlock; #endif
osip_t *j_osip; int j_stop_ua; #ifdef OSIP_MT
中国IMS网络SIP协议规范总体技术要求 - 20 -