diff options
author | mmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-11-18 18:31:08 +0000 |
---|---|---|
committer | mmichelson <mmichelson@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-11-18 18:31:08 +0000 |
commit | 135ce4759840347f4965be0cf9684fb4d965e2da (patch) | |
tree | 9d7c49be024ce0c889bfbb0d0299794cb862daec | |
parent | fe4ad3a4a2cd255ecbd3dc8cf3e425e5ed5d9c72 (diff) |
Merged revisions 157305 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r157305 | mmichelson | 2008-11-18 12:25:55 -0600 (Tue, 18 Nov 2008) | 12 lines
Fix a crash in the end_bridge_callback of app_dial and
app_followme which would occur at the end of an attended
transfer. The error occurred because we initially stored
a pointer to an ast_channel which then was hung up due
to a masquerade.
This commit adds a "fixup" callback to the bridge_config
structure to allow for end_bridge_callback_data to be
changed in the case that a new channel pointer is needed
for the end_bridge_callback.
........
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@157306 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | apps/app_dial.c | 7 | ||||
-rw-r--r-- | apps/app_followme.c | 6 | ||||
-rw-r--r-- | channels/chan_local.c | 8 | ||||
-rw-r--r-- | include/asterisk/channel.h | 4 | ||||
-rw-r--r-- | main/features.c | 8 |
5 files changed, 31 insertions, 2 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c index e2e50f90e..38d2bbd28 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -1490,6 +1490,10 @@ static void end_bridge_callback(void *data) ast_channel_unlock(chan); } +static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator) { + bconfig->end_bridge_callback_data = originator; +} + static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags64 *peerflags, int *continue_exec) { int res = -1; /* default: error */ @@ -2170,7 +2174,8 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags config.end_bridge_callback = end_bridge_callback; config.end_bridge_callback_data = chan; - + config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup; + if (moh) { moh = 0; ast_moh_stop(chan); diff --git a/apps/app_followme.c b/apps/app_followme.c index 1d324bdc2..454a64203 100644 --- a/apps/app_followme.c +++ b/apps/app_followme.c @@ -992,6 +992,11 @@ static void end_bridge_callback(void *data) ast_channel_unlock(chan); } +static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator) +{ + bconfig->end_bridge_callback_data = originator; +} + static int app_exec(struct ast_channel *chan, void *data) { struct fm_args targs; @@ -1116,6 +1121,7 @@ static int app_exec(struct ast_channel *chan, void *data) ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON); config.end_bridge_callback = end_bridge_callback; config.end_bridge_callback_data = chan; + config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup; ast_moh_stop(caller); /* Be sure no generators are left on it */ diff --git a/channels/chan_local.c b/channels/chan_local.c index d83be6da3..4187dd876 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -287,7 +287,7 @@ static void check_bridge(struct local_pvt *p, int isoutbound) if (!ast_check_hangup(p->chan->_bridge)) { if (!ast_channel_trylock(p->owner)) { if (!ast_check_hangup(p->owner)) { - if(p->owner->monitor && !p->chan->_bridge->monitor) { + if (p->owner->monitor && !p->chan->_bridge->monitor) { /* If a local channel is being monitored, we don't want a masquerade * to cause the monitor to go away. Since the masquerade swaps the monitors, * pre-swapping the monitors before the masquerade will ensure that the monitor @@ -297,6 +297,12 @@ static void check_bridge(struct local_pvt *p, int isoutbound) p->owner->monitor = p->chan->_bridge->monitor; p->chan->_bridge->monitor = tmp; } + if (p->chan->audiohooks) { + struct ast_audiohook_list *audiohooks_swapper; + audiohooks_swapper = p->chan->audiohooks; + p->chan->audiohooks = p->owner->audiohooks; + p->owner->audiohooks = audiohooks_swapper; + } ast_channel_masquerade(p->owner, p->chan->_bridge); ast_set_flag(p, LOCAL_ALREADY_MASQED); } diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 64aaca069..2c2cad6cf 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -586,6 +586,10 @@ struct ast_bridge_config { unsigned int flags; void (* end_bridge_callback)(void *); /*!< A callback that is called after a bridge attempt */ void *end_bridge_callback_data; /*!< Data passed to the callback */ + /*! If the end_bridge_callback_data refers to a channel which no longer is going to + * exist when the end_bridge_callback is called, then it needs to be fixed up properly + */ + void (*end_bridge_callback_data_fixup)(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator); }; struct chanmon; diff --git a/main/features.c b/main/features.c index 055bfa791..398cb61b1 100644 --- a/main/features.c +++ b/main/features.c @@ -1424,6 +1424,10 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st tobj->peer = xferchan; tobj->bconfig = *config; + if (tobj->bconfig.end_bridge_callback_data_fixup) { + tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan); + } + if (ast_stream_and_wait(newchan, xfersound, "")) ast_log(LOG_WARNING, "Failed to play transfer sound!\n"); ast_bridge_call_thread_launch(tobj); @@ -1521,6 +1525,10 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st tobj->peer = xferchan; tobj->bconfig = *config; + if (tobj->bconfig.end_bridge_callback_data_fixup) { + tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan); + } + if (ast_stream_and_wait(newchan, xfersound, "")) ast_log(LOG_WARNING, "Failed to play transfer sound!\n"); ast_bridge_call_thread_launch(tobj); |