freeswitch系列32通话流程

  1. 呼叫信令流程

 

呼叫的信令交互是比较复杂的,大概分3个阶段:

阶段1:

  1. A发送invate请求给服务器,服务器发现未认证,回复407;
  2. A再次发送invite,带上认证信息,服务器通过。

阶段2:

  1. 服务器向另一方B发送invite请求,B回复180。
  2. 服务器向A回复180,A开始响铃。

阶段3:

  1. B接起电话,发送200OK给服务器
  2. 服务器发送200OK给A
  1. 阶段1

sip协议栈通知应用是通过回调sofia_event_callback,和注册一样,这里会创建session和channel,然后入消息队列。

 

  1. void sofia_event_callback(nua_event_t event,  
  2.                           int status,  
  3.                           char const *phrase,  
  4.                           nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,  
  5.                           tagi_t tags[])  
  6. {  
  7.     sofia_dispatch_event_t *de;  
  8.   
  9.     //sip消息是一系列nua_开头的,nua_i表示Indications消息,还有一类nua_r表示Responses消息  
  10.     switch(event) {  
  11.     case nua_i_terminated:  
  12.     case nua_i_invite:  
  13.     case nua_i_register:  
  14.     case nua_i_options:  
  15.     case nua_i_notify:  
  16.     case nua_i_info:  
  17.         ...  
  18.     }  
  19.   
  20.     //invite消息,则要创建session,同时也是创建channel  
  21.     if (event == nua_i_invite && !sofia_private) {  
  22.         session = switch_core_session_request_uuid(sofia_endpoint_interface,...);  
  23.         switch_core_session_thread_launch(session)  
  24.     }  
  25.       
  26.     //最后把sip消息投入到消息队列mod_sofia_globals.msg_queue  
  27.     sofia_queue_message(de);  

 

消息处理线程调用sofia_process_dispatch_event去处理,这个函数里面又调用our_sofia_event_callback。

 

  1. case nua_i_invite:  
  2.     if (session && sofia_private) {  
  3.         if (sofia_private->is_call > 1) {  
  4.             sofia_handle_sip_i_reinvite(session, nua, profile, nh, sofia_private, sip, de, tags);  
  5.         } else {  
  6.             sofia_private->is_call++;  
  7.             sofia_handle_sip_i_invite(session, nua, profile, nh, sofia_private, sip, de, tags);  
  8.         }  
  9.     }  
  10.     break

 

 

sofia_handle_sip_i_invite内部调用注册函数,然后就跟注册一样的流程,在sofia_reg_auth_challenge回复407给A。

 

  1. if (sofia_reg_handle_register(nua, profile, nh, sip, de, REG_INVITE, key, sizeof(key), &v_event, NULL, NULL, &x_user)) {  
  2.     if (v_event) {  
  3.         switch_event_destroy(&v_event);  
  4.     }  
  5.     if (x_user) {  
  6.         switch_xml_free(x_user);  
  7.     }  
  8.   
  9.     if (sip->sip_authorization || sip->sip_proxy_authorization) {  
  10.         goto fail;  

 

  1. if (regtype == REG_REGISTER) {  
  2.     nua_respond(nh, SIP_401_UNAUTHORIZED, TAG_IF(msg, NUTAG_WITH_THIS_MSG(msg)), SIPTAG_WWW_AUTHENTICATE_STR(auth_str), TAG_END());  
  3. else if (regtype == REG_INVITE) {  
  4.     nua_respond(nh, SIP_407_PROXY_AUTH_REQUIRED,   
  5.                 TAG_IF(msg, NUTAG_WITH_THIS_MSG(msg)),   
  6.                 SIPTAG_PROXY_AUTHENTICATE_STR(auth_str), TAG_END());  
  7. }  

 

然后A带上认证信息,重新发起invite请求,基本上也是这个流程,只是到最后没有回复40X。接着sip协议层的状态会改变,然后通知应用。状态改变即nua_i_state,在our_sofia_event_callback中,找到如下代码。

 

  1. case nua_i_state:  
  2.     sofia_handle_sip_i_state(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);  
  3.     break;  

 

从日志看,这里会改变channel状态,cs_new->cs_init->cs_route->cs_execute,总的来说就是解析拨号规则,整理出action,然后去执行。

 

这里根据日志去跟踪代码即可,就不再列出代码。

  1. 阶段2

 

执行action的时候,会调用app中的bridge,这个在mod_dptools.c中定义。

SWITCH_STANDARD_APP(audio_bridge_function)

 

bridge会桥接两个leg,所以会先使用originate发起和B的呼叫。

 

  1. status = switch_ivr_originate(NULL, &peer_session,   
  2.                               &cause, camp_data, campon_timeout, NULL, NULL, NULL, NULL, NULL, SOF_NONE,   
  3.                               switch_channel_get_cause_ptr(caller_channel)); 

 

这个函数很长,只需要知道,会创建新的一路的session。如果B返回响铃180,则originate函数就返回,这样就可以获取新b-leg的session和channel。

 

switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);

 

两个leg都有了,就可以进行桥接。

 

switch_ivr_multi_threaded_bridge(session, peer_session, func, a_key, b_key);

这时候,A和服务器会进行媒体通信,服务器给A发送回铃音。

从日志可以看出来这个流程,注意最后一行的early media。

  1. 阶段3

B接起来后,会进行媒体的协商。完成后,A会停掉和服务器的回铃音,和B进行通话。

 

这部分通过日志跟代码就行了。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值