FreeSWITCH is a Software Defined Telecom Stack enabling the digital transformation from proprietary telecom switches to a versatile software implementation that runs on any commodity hardware. From a Raspberry PI to a multi-core server, FreeSWITCH can unlock the telecommunications potential of any device.
This code seems to take the media flow (SWITCH_MEDIA_FLOW_SENDONY) from the orig_session.
☁️ Since “music on hold” is configured, I think that the INVITE shouldn’t rely on the orig_session, but instead send always sendrecv. This is at least what happens when a regular call is placed on hold: the callee does not receive a re-INVITE with the a=sendonly (he is not informed that the caller held the call).
Analysis (part 2)
When the call is transferred, User A is receiving a re-INVITE request, which is replied with a a=sendonly:
I traced back the function call that makes the callstate changing from HELD → UNHELD to the instruction switch_channel_mark_hold(chan_a, SWITCH_FALSE); in switch_ivr_bridge.c:
if (switch_channel_test_flag(chan_a, CF_LEG_HOLDING) || switch_channel_test_flag(chan_a, CF_HANGUP_HELD)) {
if (switch_channel_ready(chan_b) &&
switch_channel_get_state(chan_b) != CS_PARK && !data->other_leg_data->clean_exit && !switch_channel_test_flag(chan_b, CF_3P_NOMEDIA_REQUESTED)) {
const char *ext = switch_channel_get_variable(chan_a, "hold_hangup_xfer_exten");
switch_channel_stop_broadcast(chan_b);
if (zstr(ext)) {
switch_call_cause_t cause = switch_channel_get_cause(chan_b);
if (cause == SWITCH_CAUSE_NONE) {
cause = SWITCH_CAUSE_NORMAL_CLEARING;
}
switch_channel_hangup(chan_b, cause);
} else {
switch_channel_set_variable(chan_b, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE, ext);
}
}
if (switch_channel_test_flag(chan_a, CF_LEG_HOLDING)) {
switch_channel_mark_hold(chan_a, SWITCH_FALSE);
}
}
This code was added in this commit, to solve FS-6272. I couldn’t find information regarding this issue, except for this:
f862c34 fixed bug in Freeswitch core dealing with calls not hanging up
after hold
Jira: http://jira.freeswitch.org/browse/FS-6272
☁️ The strange thing here is that the channel being hanged up is the channel for User B, not User A, as shown in the log above. I also cannot understand why the channel needs to be unheld, as User A kept the call on hold.
Describe the bug When a remotely held call is transferred to another user, the music on hold is not played.
To Reproduce Steps to reproduce the behavior:
Expected behavior User C should hear the music on hold.
Package version or git hash
Trace logs Not available. However, I did some preliminary analysis of the code, which hopefully will help (please see Analysis sections below).
Analysis (part 1) When the INVITE is sent towards User C, the INVITE is sent with
a=sendonly
. I traced this back to switch_core_media.c:10374:This code seems to take the media flow (
SWITCH_MEDIA_FLOW_SENDONY
) from theorig_session
.☁️ Since “music on hold” is configured, I think that the INVITE shouldn’t rely on the
orig_session
, but instead send alwayssendrecv
. This is at least what happens when a regular call is placed on hold: the callee does not receive a re-INVITE with thea=sendonly
(he is not informed that the caller held the call).Analysis (part 2) When the call is transferred, User A is receiving a re-INVITE request, which is replied with a
a=sendonly
:I traced back the function call that makes the callstate changing from HELD → UNHELD to the instruction
switch_channel_mark_hold(chan_a, SWITCH_FALSE);
in switch_ivr_bridge.c:This code was added in this commit, to solve FS-6272. I couldn’t find information regarding this issue, except for this:
☁️ The strange thing here is that the channel being hanged up is the channel for User B, not User A, as shown in the log above. I also cannot understand why the channel needs to be unheld, as User A kept the call on hold.