diff options
author | Richard Mudgett <rmudgett@digium.com> | 2013-10-01 21:19:13 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2013-10-01 21:19:13 +0000 |
commit | 7d17d5fb0470c4fa1ececbd133c4d0785ad94f96 (patch) | |
tree | 6bdb61fd6f866ffdd6f377dac2ac61066a591908 /channels | |
parent | a0db5275ed82ce64ea4b39c1da555dd92b7ff92c (diff) |
chan_dahdi: Fix analog parking using flash-hook.
Transferring an analog call using a flash-hook to parking would fail to
park the call and result in an invalid ao2 object unref.
* Park the correct bridged channel.
........
Merged revisions 400236 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400237 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_dahdi.c | 38 | ||||
-rw-r--r-- | channels/sig_analog.c | 37 |
2 files changed, 55 insertions, 20 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index f7cfa8cd7..853c5f4e7 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -9722,16 +9722,34 @@ static void *analog_ss_thread(void *data) getforward = 0; memset(exten, 0, sizeof(exten)); len = 0; - } else if ((p->transfer || p->canpark) && is_exten_parking && - p->subs[SUB_THREEWAY].owner) { - RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup); - /* This is a three way call, the main call being a real channel, - and we're parking the first call. */ - ast_channel_lock(chan); - bridge_channel = ast_channel_get_bridge_channel(chan); - ast_channel_unlock(chan); - if (bridge_channel && !ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten)) { - ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan)); + } else if ((p->transfer || p->canpark) && is_exten_parking + && p->subs[SUB_THREEWAY].owner) { + struct ast_bridge_channel *bridge_channel; + + /* + * This is a three way call, the main call being a real channel, + * and we're parking the first call. + */ + ast_channel_lock(p->subs[SUB_THREEWAY].owner); + bridge_channel = ast_channel_get_bridge_channel(p->subs[SUB_THREEWAY].owner); + ast_channel_unlock(p->subs[SUB_THREEWAY].owner); + if (bridge_channel) { + if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten)) { + /* + * Swap things around between the three-way and real call so we + * can hear where the channel got parked. + */ + ast_mutex_lock(&p->lock); + p->owner = p->subs[SUB_THREEWAY].owner; + swap_subs(p, SUB_THREEWAY, SUB_REAL); + ast_mutex_unlock(&p->lock); + + ast_verb(3, "%s: Parked call\n", ast_channel_name(chan)); + ast_hangup(chan); + ao2_ref(bridge_channel, -1); + goto quit; + } + ao2_ref(bridge_channel, -1); } break; } else if (p->hidecallerid && !strcmp(exten, "*82")) { diff --git a/channels/sig_analog.c b/channels/sig_analog.c index d1ed67378..bbf7a3c8c 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -2245,18 +2245,35 @@ static void *__analog_ss_thread(void *data) getforward = 0; memset(exten, 0, sizeof(exten)); len = 0; - } else if ((p->transfer || p->canpark) && is_exten_parking && - p->subs[ANALOG_SUB_THREEWAY].owner) { + } else if ((p->transfer || p->canpark) && is_exten_parking + && p->subs[ANALOG_SUB_THREEWAY].owner) { struct ast_bridge_channel *bridge_channel; - /* This is a three way call, the main call being a real channel, - and we're parking the first call. */ - ast_channel_lock(chan); - bridge_channel = ast_channel_get_bridge_channel(chan); - ast_channel_unlock(chan); - if (bridge_channel && !ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten)) { - ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan)); + + /* + * This is a three way call, the main call being a real channel, + * and we're parking the first call. + */ + ast_channel_lock(p->subs[ANALOG_SUB_THREEWAY].owner); + bridge_channel = ast_channel_get_bridge_channel(p->subs[ANALOG_SUB_THREEWAY].owner); + ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner); + if (bridge_channel) { + if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten)) { + /* + * Swap things around between the three-way and real call so we + * can hear where the channel got parked. + */ + analog_lock_private(p); + analog_set_new_owner(p, p->subs[ANALOG_SUB_THREEWAY].owner); + analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL); + analog_unlock_private(p); + + ast_verb(3, "%s: Parked call\n", ast_channel_name(chan)); + ast_hangup(chan); + ao2_ref(bridge_channel, -1); + goto quit; + } + ao2_ref(bridge_channel, -1); } - ao2_ref(bridge_channel, -1); break; } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { ast_verb(3, "Blacklisting number %s\n", p->lastcid_num); |