Q/CT XXXX.1-2008
iii.
iv. v.
如果是INVITE,调用eXosip_process_new_invite处理这个新请求,如果该请求合法,则会生成一个新的call,并且在call上生成一个dialog,该dialog是服务端的dialog,因为本端是UAS。
如果是BYE请求,则和ACK一样,该BYE请求没有匹配到dialog,回复一个481的错误提示应答通知对端需要结束的dialog不存在。
如果是其它类型请求,则因为是不符合sip标准的请求方式,所以将创建的transaction添加到待删除的队列中即可。
4.2.2.2 eXosip_process_response_out_of_transaction的处理流程:
a) 因为message为应答,而且没有匹配到transaction,所以肯定是一个错误的应
答。先检查message本身的合法性,如果不合法,直接释放并返回
b) 查询所以的call的dialog,查看该response是否匹配到dialog或者是还没有建
立dialog的call
c) 如果没有匹配到某一个call,说明该response与call无关,直接释放。
d) 如果#ifndef MINISIZE,且匹配到某一个dialog,说明重复接收了200应答,
可能原因是对方还没有接收到本端发送的ACK,但是本端的transaction在接收到200应答时已经被kill了,所以没有匹配到transaction,但是匹配到了dialog。如果接收到200应答的cseq和本端发送的cseq的number相等,则重新发送ACK应答。处理完上述情况后,释放该message并返回。
e) 如果只是匹配到了call,说明dialog还没有建立,但是给200应答是一个错误
的应答,否则会匹配到call的c_out_tr transaction。则为该200应答临时建立一个dialog并发送ACK回应,然后发送一个BYE请求结束该call,因为该call已经发送错误了。
4.2.3 eXosip_automatic_action处理流程
该函数用于处理哪些认证失败的call、register、notify、publish等,在接收到认证服务器回应为401或407或需要转发的情况下,进行重新尝试。
a) 遍历所有的call: i. 如果c_id < 1则不用处理,call的id小于1的都是被删除的但是还没有被
清理出j_calls链表的call。 ii. 如果该call的dialog还没有建立起来,说明是本端发送第一个INVITE请
求建立的新call,如果是对端发送的第一个INVITE,则本端要回应一个response,在回应response的时候,dialog就被建立起来了。
1. 检查建立该call的第一个INVITE请求建立起来的transaction的状态,
如果已经终结,并且该call还没有到结束超时时间120秒,且接收到的回复的状态码为401或407,则重发送请求,并且从回复中提取认
中国IMS网络SIP协议规范总体技术要求 - 29 -
Q/CT XXXX.1-2008
证信息。重发次数最多为3次,如果3次都失败,则等待直到该call超时结束。
2. 同上,如果回复应答的status为[300, 399],则重新发送请求,并且转
换发送目的地,重复发送次数也限制为3次。这两种情况全部调用_eXosip_call_retry_request进行处理。
iii. 遍历call中所有的dialog,对于已经dialog信息存在的dialog进行处理,
处理方式同上,也是检查两类情况,一为应答status为401或407的认证失败错误提示,一为[300, 399]server端地址需要更改的转发提示。
b) 遍历所有的register,只处理r_id >=1 且有transaction的register,r_id < 1或者
没有last transaction的register是已经被删除的register,不需要处理。 i. 如果重发时间不为0,既该register需要一直重新发送注册,且注册时间
已经超时,该register从注册完到现在已经超过900秒,则调用函数eXosip_register_send_register进行重注册。 ii. 如果注册时间到现在为止 大于规定的重注册时间间隔-60秒,也发起重
注册,既如果设置了重注册时间间隔,必需在重注册时间间隔到达之前的60秒就开始发起重注册。
iii. 或者如果需要重注册,而且离上次注册时间已经超过120秒,并且没有接
收到注册服务器的应答或者应答不是成功注册的应答,则也发起重注册。
iv. 如果还未设置需要重注册,即第一次注册失败,且是因为认证失败而引起
的注册失败,则检查注册类型。如果是WPDIF注册方式,则检查回复中的认证码nonce是否和上一次注册失败时保存的nonce值相同,如果相同则发起重注册;如果注册方式不是WPDIF,则直接发起重注册。为了保证WPDIF注册方式的成功,在第一次注册失败时,需要提取当次服务器端的回复中的nonce值,以便在确定是否发起重注册的时候判断条件为真。
c) Notify、subscription、pub的处理同call。
4.3
Call的处理
在exosip lib库中除了一直在运行的处理对端发送过来的message的线程外,还提供了本端做为发送端发送各种request、ACK。
因为所有的message最终都属于某个transaction,而且对message的处理最终都放在transaction的event队列中进行处理,所以所有提供的包括call、notify、publish、register、subscription、refer等功能都是通过生成一个transaction上的event事件与一直运行的处理线程进行联系,当生成event之后,处理线程在轮询所有transaction时会处理到这些event,当某个event需要立即处理的时候,则可以手工启动event的处理线程,而不需要等到该处理线程处理到该transaction。
Exosip lib库提供了call的4类接口:第一次建立一个call的initial invite创建及发送接口;在dialog中创建及发送的其它request;在dialog中创建及发送对从对端发送过来的request的response;在invite请求中回应对端response的ACK的创建和发送。 4.3.1
创建Call的第一个INVITE
在excall_api.c文件中的eXosip_call_build_initial_invite和eXosip_call_send_initial_invite提供了本端发起一个新的call时的接口。
中国IMS网络SIP协议规范总体技术要求 - 30 -
Q/CT XXXX.1-2008
eXosip_call_build_initial_invite的流程如下:
入口参数的合法性检查,特别是发送目的端地址to的检查generating_request_out_of_dialog_eXosip_dialog_add_contactosip_message_set_subjectosip_message_set_expires
在创建一个新的INVITE时,而且该INVITE是call的第一个INVITE,则需要检查必要参数目的端地址to的合法性。生成一个INVITE message需要使用到的信息大部分在exosip lib库启动的时候就设定了,包括sip协议的版本,from tag 的产生机制等。需要特别指定的只有发送目的端to。
在检查合法性之后,调用通用的请求构造函数generating_request_out_of_dialog构造生成一个request message,在构造参数中指定要构建的是一个INVITE。因为是在dialog创建之前构建INVITE 请求,所以调用的接口为out_of_dialog的,即不需要从dialog中获取信息;如果是dialog内构造的新的请求,则根据sip协议,其新的request的 local cseq number必须大于dialog中的local cseq number,并且因为属于一个dialog,所以其call_id, from tag, to tag 必须同dialog相同。同时如果不是dialog中的新的INVITE请求用于更改route set,则还要使用dialog中的route set用于该请求中。
在创建成功通用的dialog外的请求后,添加INVITE相关部分字段,包括contact,subject和超时时间expires。其中contact之间使用本端内部设置的IP地址。
eXosip_call_send_initial_invite的流程:
中国IMS网络SIP协议规范总体技术要求 - 31 -
Q/CT XXXX.1-2008
eXosip_call_init_eXosip_transaction_initosip_new_outgoing_sipmessageosip_transaction_add_event 首先initial invite是用于创建一个新的call的,所以在发送一个initial invite时,创建一个new call,并且为该invite创建一个新的transaction,该transaction类型为ICT,同时将该transaction做为这个new call的c_out_tr,因为整个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时才会进行。 4.3.2
INVITE的ACK应答的创建和发送
eXosip_update对端发送过来的INVITE等请求的处理在 exosip_read_message中已经进行了处理,对request的应答是sip协议栈自动完成的,同时对非2xx的应答也自动完成。当接收到的是2xx的应答,在transaction层的处理会上报一个EXOSIP_CALL_ANSWERED事件给UAC层,此时需要管理程序处理该事件,创建一个ACK应答并发送该ACK应答,同时如果在超时时间内继续接收到该2xx应答,只需要重新发送该ACK应答即可。
客户端接收到2xx应答的处理参见Jcallbakck.c文件的cb_rcv2xx函数。
eXosip_call_build_ack的处理流程:
a) 根据所属的dialog,查询得到所属的call 和dialog的结构。
b) 获取该dialog中还未处理完的transaction,如果该transaction不是INVITE的
transaction则返回错误,因为ACK只会出现在INVITE的请求transaction中。
中国IMS网络SIP协议规范总体技术要求 - 32 -