From fe6bedf1ab7d9c06fbe6f0ab4cb6841ac47b29f2 Mon Sep 17 00:00:00 2001 From: Yalu Zhang <yalu.zhang@iopsys.eu> Date: Tue, 10 Dec 2024 15:10:16 +0000 Subject: [PATCH] Fix a bug that call clearing tones are not started when two other call parties hangup Call scenario - DUT calls A and the call is answered - B calls DUT - Press R to accept B - A hangs up and then B hangs up There are no call clearing tones after a brief beep. Cause handle_dialtone_timeout() calls chan_voicemngr_get_active_subchannel() to get the sub-channel and the sub[0] is returned and its state is ONHOOK. So the call clearing procedure is not started by handle_dialtone_timeout(). Solution Let chan_voicemngr_get_active_subchannel() select the sub-channel with state CALLENDED over ONHOOK. Also remove the unused call state ANSWER. --- src/channels/chan_voicemngr.c | 20 +++++++++++++------- src/channels/chan_voicemngr.h | 1 - 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/channels/chan_voicemngr.c b/src/channels/chan_voicemngr.c index 25024c1..0ce404c 100644 --- a/src/channels/chan_voicemngr.c +++ b/src/channels/chan_voicemngr.c @@ -1341,7 +1341,6 @@ static int chan_voicemngr_devicestate(const char *device_number) case DIALING: return AST_DEVICE_INUSE; case CALLING: return AST_DEVICE_INUSE; case INCALL: return AST_DEVICE_INUSE; - case ANSWER: return AST_DEVICE_INUSE; case CALLENDED: return AST_DEVICE_NOT_INUSE; case RINGING: return AST_DEVICE_RINGINUSE; case CALLWAITING: return AST_DEVICE_INUSE; @@ -1893,7 +1892,6 @@ static char *state2str(enum chan_voicemngr_channel_state state) case DIALING: return "DIALING"; case CALLING: return "CALLING"; case INCALL: return "INCALL"; - case ANSWER: return "ANSWER"; case CALLENDED: return "CALLENDED"; case RINGING: return "RINGING"; case CALLWAITING: return "CALLWAITING"; @@ -2100,17 +2098,25 @@ struct chan_voicemngr_subchannel* chan_voicemngr_get_active_subchannel(const str case TRANSFERING: case RINGBACK: sub = p->sub[i]; - return sub; + return sub; // Select this sub-channel and return right away without checking the next one + case CALLWAITING: case ONHOLD: break; + case ONHOOK: - case ANSWER: - case CALLENDED: + // This is the least active state and will be selected as the last choice if (!sub) { sub = p->sub[i]; } break; + + case CALLENDED: + /* Select this sub-channel and override the sub-channel with ONHOOK state because + * CALLENDED is more active than ONHOOK */ + sub = p->sub[i]; + break; + default: ast_log(LOG_WARNING, "Unhandled channel state %s\n", state2str(p->sub[i]->channel_state)); break; @@ -2499,7 +2505,6 @@ static int handle_dialtone_timeout(const void *data) pvt_lock(p, "dialtone timeout"); strncpy(p->extensionCallStatus, "Disconnected", CALL_STATUS_MAX_LEN); p->dialtone_timeout_timer_id = -1; - struct chan_voicemngr_subchannel *sub = chan_voicemngr_get_active_subchannel(p); ast_debug(9, "Dialtone timeout, sub->channel_state: %s\n", state2str(sub->channel_state)); @@ -3223,7 +3228,8 @@ static void audio_packet_handler(pe_packet_t *p) pvt = chan_voicemngr_get_pvt_from_lineid(iflist, ap->line); sub = chan_voicemngr_get_active_subchannel(pvt); if (!pvt || !sub) { - ast_log(LOG_ERROR, "Failed to find subchannel for %s/%d/%d\n", frame.src, ap->line, ap->connection_id); + ast_log(LOG_DEBUG, "Failed to find sub-channel for %s/%d/%d. Maybe the call has been ended\n", + frame.src, ap->line, ap->connection_id); endpt_connection(ap->line, ap->connection_id, "destroy"); // Request line close return; } diff --git a/src/channels/chan_voicemngr.h b/src/channels/chan_voicemngr.h index db486cd..9e25ce8 100644 --- a/src/channels/chan_voicemngr.h +++ b/src/channels/chan_voicemngr.h @@ -45,7 +45,6 @@ enum chan_voicemngr_channel_state { DIALING, CALLING, INCALL, - ANSWER, CALLENDED, RINGING, CALLWAITING, -- GitLab