Freeswitch配网关,本域主叫上级号码,主叫听不到被叫声音

问题描述:Freeswitch配置外呼网关,主叫外呼,存在被叫单通,主叫听不到被叫声音的现象。


估计大部分同学都是参照下面的步骤添加的外部网关,然后上面的这个现象估计就跑不掉了。

1、配置外部网关,在FreeSwitch目录在conf\sip_profiles\external 目录下,创建一个my_gate.xml, 内容如下:

[root@lyz-VirtualBox external]# ls
my_gate.xml  example.xml
[root@lyz-VirtualBox external]# cat my_gate.xml
<include>
 
   <gateway name="my_gate">//gateway 网关定义,name 是网关配置名称,在拨号时用到
     <param name="proxy" value="192.168.23.71:5060"/>
     <param name="register" value="false"/>//表示不注册//
     <param name="caller-id-in-from" value="true"/> <!--Most gateways seem to want this-->
     <param name="username" value="freeswitch_123"/>
     <param name="password" value="1234"/>
   </gateway>



2、配置拨号规则:所有0开头的号码都转给上级网关。(注明,这个拨号规则太简单了,fs默认走了代理模式,会出现单通现象。

<include>
 <extension name="mycall">
   <condition field="destination_number" expression="^0(\d+)$">
  <action application="bridge" data="sofia/gateway/my_gate/$1"/> 
   </condition>
 </extension>
</include>



3、问题现象:主叫外呼到上级网关,通过主叫端和Freeswitch端抓包分析:

抓主叫端dump,发现主叫端只有发出包,没有收到包;

抓服务器日志,有收到对端网关转发过来的包,但没有给主叫端转包;

打开fs的rtp debug日志开关,发现fs收到对端网关的rtp包之后,因为主叫端的media_flow 为4,

呱牛笔记


代码:

SWITCH_DECLARE(switch_status_t) switch_core_media_write_frame(switch_core_session_t *session,
												  switch_frame_t *frame, switch_io_flag_t flags, int stream_id, switch_media_type_t type)
{
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	int bytes = 0, samples = 0, frames = 0;
	switch_rtp_engine_t *engine;
	switch_media_handle_t *smh;

	switch_assert(session);

	if (!(smh = session->media_handle)) {
		return SWITCH_STATUS_FALSE;
	}

	if (!smh->media_flags[SCMF_RUNNING]) {
		return SWITCH_STATUS_FALSE;
	}

	engine = &smh->engines[type];

	if (type == SWITCH_MEDIA_TYPE_VIDEO) {
		if (engine->thread_write_lock && engine->thread_write_lock != switch_thread_self()) {
			return SWITCH_STATUS_SUCCESS;
		}
	}

	if (type == SWITCH_MEDIA_TYPE_AUDIO) {
		switch_media_flow_t audio_flow = switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_AUDIO);

		if (audio_flow != SWITCH_MEDIA_FLOW_SENDRECV && audio_flow != SWITCH_MEDIA_FLOW_SENDONLY) {
		        //从这里退出了
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, " switch_core_session_
			media_flow audio_flow %d.\n",  audio_flow);
			return SWITCH_STATUS_SUCCESS;
		}
	}


通过增加日志发现,只给被叫端添加了media_flow的读写模式,默认则是4:SWITCH_MEDIA_FLOW_DISABLED

2024-04-07 10:38:08.490172 99.77% [DEBUG] switch_core_media.c:4719  sofia/external/8009 switch_core_media_set_smode 
type:0 smode:0, old_smode:4.
2024-04-07 10:38:08.490172 99.77% [DEBUG] switch_core_media.c:4719  sofia/external/8009 switch_core_media_set_smode 
type:1 smode:0, old_smode:4.

代码

SWITCH_DECLARE(void) switch_core_media_set_smode(switch_core_session_t *session, switch_media_type_t type, switch_media_flow_t smode, switch_sdp_type_t sdp_type)
{
	switch_media_handle_t *smh;
	switch_rtp_engine_t *engine;
	const char *varname = NULL, *smode_str = NULL;
	switch_media_flow_t old_smode, opp_smode = smode;
	switch_core_session_t *other_session;
	int pass_codecs = 0;
	
	if (!(smh = session->media_handle)) {
		return;
	}

	engine = &smh->engines[type];

	varname = media_flow_varname(type);
	
	media_flow_get_mode(smode, &smode_str, &opp_smode);

	old_smode = engine->smode;

	engine->smode = smode;
  
        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "engine:%08x, %s switch_core_media_set_smode smode:%d, old_smode:%d.\n", engine, switch_channel_get_name(session->channel), 
	   	smode, old_smode);


那问题可能出在,被叫回200OK之后,没有走sdp协商流程,所以主叫端的smode一直都是disable。


怎么修改呢?只能继续分析,为什么通过外呼回来的session为什么没有走协商流程了。


通过分析日志,外呼时,freeswitch处于PROXY模式,代理模式下freeswitch只转包,不参与中间协商,不转码,协商由客户端自动完成,但是这个过程中freeswitch又没有把上级网关转发的包转给主叫端,这就是很奇怪了。

呱牛笔记


通过日志和调试确定,sofia_handle_sip_i_state 接到对方的200 OK后,由于是代理模式,并没有走sdp协商过程。



修改方法1:

switch_core_media_patch_sdp方法,增加判断主叫端的smode是否为DISABLE,如果是则修改为SENDRECV.

	#if 1//代理模式下设置为sendrecv
	if (a_engine->smode == SWITCH_MEDIA_FLOW_DISABLED) {
		switch_core_media_set_smode(smh->session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_MEDIA_FLOW_SENDRECV, SDP_TYPE_RESPONSE);
	}
	if (v_engine->smode == SWITCH_MEDIA_FLOW_DISABLED) {
		switch_core_media_set_smode(smh->session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_MEDIA_FLOW_SENDRECV, SDP_TYPE_RESPONSE);
	}
	if (t_engine->smode == SWITCH_MEDIA_FLOW_DISABLED) {
		switch_core_media_set_smode(smh->session, SWITCH_MEDIA_TYPE_TEXT, SWITCH_MEDIA_FLOW_SENDRECV, SDP_TYPE_RESPONSE);
	}
	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "[proxy ]a_engine->smode:%d, mode2:%d, mode3:%d\n",
					 a_engine->smode, v_engine->smode, t_engine->smode);
	#endif//add end.


方法2:

修改拨号规则

呱牛笔记呱牛笔记

知乎上也有同学提到相同的问题:

呱牛笔记

本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com

请先登录后发表评论
  • 最新评论
  • 总共0条评论