mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-22 11:19:52 +00:00
freetdm: fix hangup race
This commit is contained in:
parent
910729b5dd
commit
438c93e83f
libs/freetdm/src
@ -1899,15 +1899,27 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char
|
|||||||
|
|
||||||
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
|
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
|
||||||
{
|
{
|
||||||
|
ftdm_status_t status = FTDM_SUCCESS;
|
||||||
|
|
||||||
ftdm_channel_lock(ftdmchan);
|
ftdm_channel_lock(ftdmchan);
|
||||||
|
|
||||||
|
if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
|
||||||
|
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call is already terminating\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_ANSWERED);
|
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_ANSWERED);
|
||||||
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
|
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
|
||||||
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_MEDIA);
|
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_MEDIA);
|
||||||
|
|
||||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
|
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
|
||||||
ftdm_channel_unlock(ftdmchan);
|
goto done;
|
||||||
return FTDM_SUCCESS;
|
}
|
||||||
|
|
||||||
|
if (ftdmchan->state >= FTDM_CHANNEL_STATE_UP) {
|
||||||
|
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Ignoring answer because the call state is (%d/%s)\n", ftdmchan->state, ftdm_channel_state2str(ftdmchan->state));
|
||||||
|
status = FTDM_FAIL;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) {
|
if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) {
|
||||||
@ -1920,14 +1932,33 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char
|
|||||||
|
|
||||||
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1);
|
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1);
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
ftdm_channel_unlock(ftdmchan);
|
ftdm_channel_unlock(ftdmchan);
|
||||||
return FTDM_SUCCESS;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* lock must be acquired by the caller! */
|
/* lock must be acquired by the caller! */
|
||||||
static ftdm_status_t call_hangup(ftdm_channel_t *chan, const char *file, const char *func, int line)
|
static ftdm_status_t call_hangup(ftdm_channel_t *chan, const char *file, const char *func, int line)
|
||||||
{
|
{
|
||||||
if (chan->state != FTDM_CHANNEL_STATE_DOWN) {
|
if (chan->state != FTDM_CHANNEL_STATE_DOWN) {
|
||||||
|
if (chan->state == FTDM_CHANNEL_STATE_HANGUP) {
|
||||||
|
/* make user's life easier, and just ignore double hangup requests */
|
||||||
|
return FTDM_SUCCESS;
|
||||||
|
}
|
||||||
|
if (chan->state == FTDM_CHANNEL_STATE_TERMINATING && ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) {
|
||||||
|
/* the signaling stack is already terminating the call but has not yet notified the user about it
|
||||||
|
* with SIGEVENT_STOP, we must flag this channel as hangup and wait for the SIGEVENT_STOP before
|
||||||
|
* proceeding, at that point we will move the channel to hangup, but the SIGEVENT_STOP will not
|
||||||
|
* be sent to the user since they already made clear they want to hangup!
|
||||||
|
* */
|
||||||
|
ftdm_set_flag(chan, FTDM_CHANNEL_USER_HANGUP);
|
||||||
|
ftdm_wait_for_flag_cleared(chan, FTDM_CHANNEL_STATE_CHANGE, 5000);
|
||||||
|
if (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) {
|
||||||
|
ftdm_log_chan(chan, FTDM_LOG_CRIT, "Failed to hangup, state change for %d/%s is still pending!\n", chan->state, ftdm_channel_state2str(chan->state));
|
||||||
|
return FTDM_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1);
|
ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1);
|
||||||
} else {
|
} else {
|
||||||
/* the signaling stack did not touch the state,
|
/* the signaling stack did not touch the state,
|
||||||
@ -2163,6 +2194,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
|
|||||||
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
|
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
|
||||||
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_MEDIA);
|
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_MEDIA);
|
||||||
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_ANSWERED);
|
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_ANSWERED);
|
||||||
|
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USER_HANGUP);
|
||||||
ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
|
ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
|
||||||
ftdm_buffer_destroy(&ftdmchan->pre_buffer);
|
ftdm_buffer_destroy(&ftdmchan->pre_buffer);
|
||||||
ftdmchan->pre_buffer_size = 0;
|
ftdmchan->pre_buffer_size = 0;
|
||||||
@ -4214,6 +4246,13 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
|
|||||||
ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_HOLD);
|
ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_HOLD);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FTDM_SIGEVENT_STOP:
|
||||||
|
if (ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_USER_HANGUP)) {
|
||||||
|
ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user already requested hangup\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -4224,6 +4263,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
|
|||||||
status = span->signal_cb(sigmsg);
|
status = span->signal_cb(sigmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
if (sigmsg->channel) {
|
if (sigmsg->channel) {
|
||||||
ftdm_mutex_unlock(sigmsg->channel->mutex);
|
ftdm_mutex_unlock(sigmsg->channel->mutex);
|
||||||
}
|
}
|
||||||
|
@ -250,6 +250,7 @@ typedef enum {
|
|||||||
FTDM_CHANNEL_USE_TX_GAIN = (1 << 26),
|
FTDM_CHANNEL_USE_TX_GAIN = (1 << 26),
|
||||||
FTDM_CHANNEL_IN_ALARM = (1 << 27),
|
FTDM_CHANNEL_IN_ALARM = (1 << 27),
|
||||||
FTDM_CHANNEL_SIG_UP = (1 << 28),
|
FTDM_CHANNEL_SIG_UP = (1 << 28),
|
||||||
|
FTDM_CHANNEL_USER_HANGUP = (1 << 29),
|
||||||
} ftdm_channel_flag_t;
|
} ftdm_channel_flag_t;
|
||||||
#if defined(__cplusplus) && defined(WIN32)
|
#if defined(__cplusplus) && defined(WIN32)
|
||||||
// fix C2676
|
// fix C2676
|
||||||
|
Loading…
x
Reference in New Issue
Block a user