Q/CT XXXX.1-2008
5) 在osip_message_to_str.c文件中的_osip_message_to_str函数中添加该header转化为string的函数注册。
6) 如果该header不允许重复多个出现,即不允许multiple header,则在osip_message_parse.c文件的 osip_message_set_multiple_header函数中添加对该header的处理。
7) 8)
在osip_message.h的头文件中的osip_message结构中添加对该header字段的结构。 在osip_headers.h文件中添加新的header的头文件引用。
3.4 osip的transaction的管理
transaction的操作主要包括transaction的初始化、transaction的free、transaction的匹配、从transaction中获取信息和设置transaction信息。
根据sip协议描述一个transaction由5个必要部分组成:from、to、topvia、call-id和cseq,这5个部分一起识别某一个transaction,如果缺少任何一部分,该transaction就会设置失败。
所以对每个部分的设置都会有一个设置函数:__osip_transaction_set_topvia用于设置topvia,对于发送端topvia为自己的via,对于接收端topvia为将message转发到自己的最后一个sip-proxy服务器,__osip_transaction_set_from用于设置message的发送端,__osip_transaction_set_to用于设置message的接收端,__osip_transaction_set_call_id用于设置一个dialog的标识值,该值是随机生成的,算法保证很长一段时间内生成的cal_id是不相同的,__osip_transaction_set_cseq用于设置cseq值,该值在同一个dialog内部是一直保持增长的,即同一个dialog的后面的transaction的cseq会比前面的transaction的值大,按照sip协议其初始值可以是随机数,代码实现中如果是非register请求,从1开始,如果是register请求的dialog,从20开始。
Transaction的初始化发生在接收到一个新的请求或发送一个请求的时候,该请求以及经过解析成为一个可以直接使用请求信息的结构osip_message_t。其初始化具体过程如上面所述,在设置完那5个部分后,还需要初始化event的队列,以及根据osip_message_t的type初始化使用到的定时器结构,如ICT的ict_context。其它部分的初始化在exosip源代码中实现,相关的如your_instance、in_socket、out_socket和record都是未了方便exosip中对transaction的管理而设置的。
Transaction中的event的相关操作在如前面所述。
中国IMS网络SIP协议规范总体技术要求 - 16 -
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 -