diff options
-rw-r--r-- | main/bridge_basic.c | 13 |
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; } |