osip的一些知识

当需要创建新的ICT的transaction时,TIMEOUT_B被启动,时长为64*DEFAULT_T1(DEFAULT_T1为500ms),TIMEOUT_B为整个transaction的生命周期时长,如果超过这个时间,transaction会被结束。

如果传输层是没有传输保证的UDP,则设置TIMEOUT_A、TIMEOUT_D的间隔时间为DEAULT_T1和64*DEFAULT_T1;

如果传输层使用的是面向连接的TCP,则直接使用TCP内部的重传机制,不在SIP层提供传输的保护机制,不启动TIMEOUT_A、TIMEOUT_D

TIMEOUT_A管理Invite的发送,发送时启动TIMEOUT_A,如果超时还没收到response,则重发该Invite;
TIMEOUT_D管理ACK

每个header都是起新行,且新行的头一个字符不为空格或\t
header和body之间的分界为‘\r\n\r\n’ ,message是以‘\0’为结束标志

header内部分割符 ‘:’ 取出header的hname和hvalue

Subject只允许一个值 , 而Router允许多个值,每个值之间以“,”进行分割

osip中对于header的解析采用注册函数的方式实现,能够方便的在后续版本中添加新的header,而不影响整个源代码的框架流程。

SIP协议栈规定header的表示分为header’s name header’s value 和header’s parameter,其中name和value之间用“:”分隔,value与parameter之间用“;”分隔,parameter之间也使用“;”相分隔。

url分为三部分 :url的基本信息,url的header头部分和url的参数部分。开始部分与header头部分用个“?”分隔,
header头之间用“&”进行分割,header头部分与参数部分用“;”分割,参数之间有使用“;”分隔

如果url中包含parameter,则整个url必须使用“<” “>” 括起来,以表示一个完整的url部分。所以解析from等包含url的header时需要检查是否包含“<” 字符

根据sip协议描述 一个transaction由5个必要部分组成:from、 to、 topvia、 call-id 和 cseq,整个5个部分一起识别某一个transaction,缺少然和一部分,该transaction就会设置失败。

每个部分都有一个设置函数,对于发送端topvia为自己的via,对于接收端topvia为将messags转发到自己的最后一个sip-proxy服务器
_osip_transaction_set_call_id用于设置一个dialog的标识值,改值是随机生成的,算法保证很长一段时间内生成的call_id不同;
_osip_transaction_set_cseq用于设置cseq值,该值在同一个dialog内部是一直保持增长的,即同一个dialog的后面的transaction的cseq会比前面的transaction的值大,按照sip协议其初始值可以是随机数,代码实现中如果是register请求,从1开始,如果是非Register请求的dialog,从20开始。

transaction的初始化发生在接收到一个新的请求或者发送一个请求的时候,该请求经过解析成为一个可以直接使用请求信息的结构osip_message_t。初始化在设置完from、 to、 topvia、 call-id 和 cseq5个部分后(都有自己的设置函数),还需要初始化event队列,根据osip_message_t的type初始化用到的定时器结构,入ICT的ict_context. 其他部分的初始化都在exOsip源代码中实现。

transaction匹配是根据topvia的branch_id是否相同,如果相同就是同一个transaction的请求和应答及ACK。同时,为了兼容旧版本,也支持call_id、cseq,from_tag, to_tag 来匹配transaction。

transaction匹配过程中,如果是发出的请求,因为本地的transaction都会分配一个不重复的transaction_id,所以只需要匹配transaction即可;对于incoming的message按照上边的匹配

dialog保存了相关的路由信息和cseq信息;
dialog由call_id、local_tag和remote_tag唯一确定一个dialog

exOsip
为支持多线程间的通信,在两个线程间采用pipe的方式进行实现

message中的状态码,如果是0说明是一个请求,如果不为0,则是一个response

在处理接收到的message时可能会创建新的call、新的transaction、生成新的transaction的event,还有exosip的event。

匹配dialog比匹配transaction条件简单,多个transaction可以属于同一个dialog。

eXosip_automatic_action用于处理那些认证失败的call、register、notify、publish等,

所有的message最终都属于某一个transaction,而且对message的处理最终都放在transaction的event队列中进行处理,所以所有提供的包括call、notify、publish、register、subscription、refer等功能都是通过生成一个transaction上的event事件与一直运行的处理线程进行呢联系,当生成event之后,处理线程在轮询所有transaction时会处理到这些event,当某个event需要立即处理的时候,则可以手工启动event的处理线程,而不需要等到该处理线程处理到该transaction。

在dialog创建之前构建INVITE请求,调用的接口为out_of_dialog,即不需要从dialog中获取信息;
如果是在dialog中构造新的请求,其新的request的local cseq number必须大于dialog中的local cseq number,并且因为属于同一个dialog,所以其call_id,from_tag,to_tag必须与dialog相同。

initial invite用于创建一个新call时,在发送initial Invite时,创建一个new call,并且为该Invite创建一个新的transaction,应为整个call是由该transaction创建的,当该transaction到complete状态时该call就建立起来了,但此时并不建立dialog,因为dialog是两段通信协商后的结果,只有收到对端的非100的1xx应答或>200的应答才会建立一个dialog。
在创建完call和transaction之后,根据要发送的INVITE生成一个transaction上的event,将该event添加到该transaction的event队列中,并将call添加到exosip管理的call链表中,然后给call分配一个call_id,最后唤醒处理线程对transaction上的event进行处理。
两个线程的交互式通过transaction的event队列来完成的,eXosip_call_send_initial_invite只是将要发送的invite生成一个event添加到event队列中,真正的发送在处理线程处理该event时才会进行。。

对request的应答时sip协议栈自动完成的,同时对非2xx的应答也自动完成。

ACK只会出现在INVITE的请求transaction中。
eXosip_call_send_ack,直接发送该ack,不作为一个event添加到transaction是防止中间的消耗时间过长,导致对端的2xx应答重发。 保存该ACK,在对端重发2xx应答时重发该ACK。

dialog内的请求的创建和发送:
如果dialog已经建立完成,创建新的dialog内的请求只需要知道request的类型即可,其他的信息在dialog内部已经保存;
在创建一个新的请求的时候,需要检查是否有未处理的请求存在,应为一个call’内的请求是按照顺序进行处理的,即上一个请求没有处理完,下一个请求不应该发送出去。 其中INVITE请求比较特殊,只要没有INVITE请求没有处理完,就可以发送下一个INVITE请求,而不需要等待像notify、option等的请求。

根据transaction id查询得到call、dialog、transaction的结构

只保存最近一个register的transaction,因为注册必须是串行的,再上一个注册还没有处理完毕的情况下,不允许在同一个注册服务器上发送新的注册请求。

你可能感兴趣的:(sip协议)