summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main/bridge_basic.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/main/bridge_basic.c b/main/bridge_basic.c
index 48b791d9d..e3318b9f2 100644
--- a/main/bridge_basic.c
+++ b/main/bridge_basic.c
@@ -1322,7 +1322,10 @@ struct attended_transfer_properties {
struct ast_channel *transfer_target;
/*! The party that is currently being recalled. Depending on
* the current state, this may be either the party that originally
- * was the transferer or the original transfer target
+ * was the transferer or the original transfer target. This is
+ * set with reference when entering the BLOND_NONFINAL, RECALLING,
+ * and RETRANSFER states, and the reference released on state exit
+ * if continuing with recall or retransfer to avoid leak.
*/
struct ast_channel *recall_target;
/*! The absolute starting time for running timers */
@@ -2275,10 +2278,10 @@ static int blond_nonfinal_enter(struct attended_transfer_properties *props)
{
int res;
props->superstate = SUPERSTATE_RECALL;
+ /* move the transfer target to the recall target along with its reference */
props->recall_target = ast_channel_ref(props->transfer_target);
res = blond_enter(props);
- /* transfer properties holds a separate reference to transfer_target, don't set it to NULL here */
- ast_channel_unref(props->transfer_target);
+ props->transfer_target = ast_channel_unref(props->transfer_target);
return res;
}
@@ -2292,8 +2295,8 @@ static enum attended_transfer_state blond_nonfinal_exit(struct attended_transfer
return TRANSFER_RESUME;
case STIMULUS_TIMEOUT:
ast_softhangup(props->recall_target, AST_SOFTHANGUP_EXPLICIT);
- props->recall_target = ast_channel_unref(props->recall_target);
case STIMULUS_RECALL_TARGET_HANGUP:
+ props->recall_target = ast_channel_unref(props->recall_target);
return TRANSFER_RECALLING;
case STIMULUS_NONE:
case STIMULUS_DTMF_ATXFER_ABORT:
@@ -2480,6 +2483,7 @@ static enum attended_transfer_state recalling_exit(struct attended_transfer_prop
if (ast_bridge_impart(props->transferee_bridge, props->recall_target, NULL, NULL,
AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
ast_hangup(props->recall_target);
+ ast_channel_unref(props->recall_target);
return TRANSFER_FAIL;
}
return TRANSFER_RESUME;
@@ -2586,6 +2590,7 @@ static int retransfer_enter(struct attended_transfer_properties *props)
AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
ast_log(LOG_ERROR, "Unable to place recall target into bridge\n");
ast_hangup(props->recall_target);
+ ast_channel_unref(props->recall_target);
return -1;
}