osip源代码框架详解 下载本文

Q/CT XXXX.1-2008

TIMEOUT_A、TIMEOUT_B和TIMEOUT_D。

在client端发送Invite而需要创建新的ICT的transaction时,TIMEOUT_B被启动,时长为64*DEFAULT_T1(DEFAULT_TI为500ms),TIMEOUT_B为整个transaction的生命周期时长,如果超过这个时间,transaction会被结束。如同传输层使用的是没有传输保证的UDP,则设置TIMEOUT_A,TIMEOUT_D的间隔时间为DEFAULT_T1和64* DEFAULT_T1。如果传输层使用的是面向连接的TCP及相关协议,则直接使用TCP内部的重传机制,不在SIP协议层提供传输的保护机制,所以不启动TIMEOUT_A和TIMEOUT_D。TIMEOUT_A管理Invite的传送,在Invite被发送时,启动定时器TIMEOUT_A,并且在超时时间内还没接收到response的时候,重发该Invite。TIMEOUT_D用于管理ACK,当接收到的response不是>=300时,client端发送ACK,当重复接收到该invite的response时,重发该ACK,确保server端在kill tranction前能接收到ACK。 3.2.2

IST的处理流程

同ICT的处理流程,处理osip中的osip_ist_transaction链表。IST的相关event的注册处理函数在ist_fsm.c文件和ist.c文件。

IST使用了定时器TIMEOUT_G、TIMEOUT_H和TIMEOUT_I。使用方式与ICTL类似,详细见协议栈说明。 3.2.3

NICT的处理流程

同ICT的处理流程,处理osip中的osip_nict_transaction链表。NICT的相关event的注册处理函数在nict_fsm.c文件和nict.c文件。

NICT使用了定时器TIMEOUT_E、TIMEOUT_F和TIMEOUT_K。 3.2.4

NIST的处理流程

同ICT的处理流程,处理osip中的osip_nist_transaction链表。NIST的相关event的注册处

中国IMS网络SIP协议规范总体技术要求 - 9 -

Q/CT XXXX.1-2008

理函数在nist_fsm.c文件和nist.c文件。

NIST使用了定时器TIMEOUT_J。 3.3 Osip报文的解析 3.3.1

sip协议报文的解析整理流程

当接收到一个message的时候,需要解析该message,生成一个代码能够处理的数据结构,该结构定义为struct osip_message,该结构定义的一个message的全部相关信息,这些信息主要是供transaction和dialog及dialog的更上一层如call,notify等的使用。

对一个message的解析流程如下图所示:

osip_message_parse_osip_message_parseosip_util_replace_all_lws__osip_message_startline_parsemsg_headers_parsemsg_osip_body_parse 在接收到一个message时,调用函数osip_message_parse进行message的解析。首先调用函数osip_util_replace_all_lws替换掉message中的连续出现的 ‘\\r\\n\\t’、‘\\r\\t’、‘\\n\\t’、‘\\r\\n ’、‘\\r ’、‘\\n ’为空格,message是以‘\\0’为结束标志的,message的headers和body之间的分界是以’\\r\\n\\r\\n’为标志的,替换只替换到’\\r\\n\\r\\n’为止,即只替换headers部分出现的\\t、\\r、\\n。由于sip协议栈规定,每个headers都是起新行,而且新行的头一个字符不为空格或\\t,所以两个header之间的\\r\\n不会被替换掉,替换的只是一个允许multi合并项的header的内部多个值之间的“\\r\\n\\t”或“\\r\\n ”。

中国IMS网络SIP协议规范总体技术要求 - 10 -

Q/CT XXXX.1-2008

举例如下:有两个header,其中Subject只允许单个值出现, Route允许有多个值出现,而且允许分行,但是分行必须以空格或\\t开头,而Subject和Route行必需顶格开始,前面是没有空格或\\t的,osip_util_replace_all_lws函数将Route header value中的两行间的\\r\\n\\t转化为空格,即在逻辑上就成为一行了。

Subject: Lunch

Route: ,

一个message由三部分组成,首先是message的startline部分,该行指明这是一个sip的message,包括sip标志,请求或应答说明,状态值,然后以\\r\\n做为和headers的分隔符。该\\r\\n不会被osip_util_replace_all_lws替换为空格,如请求的INVITE sip:bob@biloxi.com SIP/2.0或应答的SIP/2.0 200 OK,在三个属性之间有且仅有一个空格。起始行的解析由__osip_message_startline_parse进行解析,解析得到message的类型,message的sipversion以及message的status_code,当status_code为初始化值0时,该message

为一个请求,否则为应答。请求的

startline

__osip_message_startline_parsereq进行解析,得到请求的request_uri;应答的startline由__osip_message_startline_parseresp进行解析。Startline部分的解析是严格安装出现的三个属性的顺序进行解析的,并将解析结果保存在osip_message的结构成员变量中。

然后解析messge的headers部分,调用函数 msg_headers_parse。说明见osip的header报文头解析。

如果message中在headers之后不是结束符’\\0’,则继续解析message的负载部分,调用函数msg_osip_body_parse进行解析。Message的body解析首先查询headers头解析中保存

中国IMS网络SIP协议规范总体技术要求 - 11 -

Q/CT XXXX.1-2008

的content——即body――的属性:content_type,如果content_type中的type不为multipart,即不支持多种mime方式的content,说明body中就一个编码方式,直接将整个body解析为一个内容;如果type为multitype,说明有多个编码方式的body组合在一起形成一个整体的body,则以”--”为分隔符解析body,将body分为多个mime编码方式的字符串,每个解析后的body内容保存在osip_message结构中的bodies结构成员中。 3.3.2

Osip报文头的解析

msg_headers_parseYes,解析下一个headerheader解析成功,body为NULL返回成功,body=start_of_headerStart_of_header[0]为0NoYes__osip_find_next_crlf获取下一个\\r\\n,保存位置到end_of_headerSuccessYes,解析下一个headerStart_of_header为\\r或\\nnoosip_message_set_multiple_headerYesfail返回errorheader解析success, start_of_header = end_of_headerno

在解析message的header的时候,因为前面的osip_util_replace_all_lws已经转化了单个header内部出现的\\r、\\n和\\t为空格,所以每个header之间可以使用\\r\\n做为分隔符进行分隔。如果字符串开头start_of_header已经到达结束符”\\0”,则全部header解析完毕,返回成功;调用__osip_find_next_crlf找到这个header的结束字符并保存在end_of_header中;如果start_of_header为\\r或\\n,则已经解析到\\r\\n\\r\\n即headers的结束字符串,则返回成功,并且保存start_of_header到body中,即body是从\\r\\n字符串开始解析的,所以在body解析时,需要跳过\\r\\n及之后的空格部分;根据header内部分隔符“:”,取出header的hname和hvalue,其中

hvalue

在某些

hname

的情况下是允许为空的,然后调用

中国IMS网络SIP协议规范总体技术要求 - 12 -