[asterisk-commits] rmudgett: branch rmudgett/hangup_handlers r369062 - in /team/rmudgett/hangup_...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Jun 18 18:11:17 CDT 2012


Author: rmudgett
Date: Mon Jun 18 18:11:13 2012
New Revision: 369062

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=369062
Log:
Commit current hangup handler work.

* Fixed AMI action Bridge not disconnecting AMI connection on failure.
* Fix Bridge application to fail more gracefully.
* Call parking, DTMF attended transfers, AMI action Bridge, and the Bridge
application now support hangup handlers.

Needs more testing and bridge peer calling hangup handlers where needed.

Modified:
    team/rmudgett/hangup_handlers/apps/app_followme.c
    team/rmudgett/hangup_handlers/apps/app_queue.c
    team/rmudgett/hangup_handlers/main/features.c
    team/rmudgett/hangup_handlers/main/pbx.c

Modified: team/rmudgett/hangup_handlers/apps/app_followme.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/hangup_handlers/apps/app_followme.c?view=diff&rev=369062&r1=369061&r2=369062
==============================================================================
--- team/rmudgett/hangup_handlers/apps/app_followme.c (original)
+++ team/rmudgett/hangup_handlers/apps/app_followme.c Mon Jun 18 18:11:13 2012
@@ -1512,6 +1512,7 @@
 			}
 		}
 
+/* BUGBUG Update ast_bridge_call() here to see about calling ast_pbx_hangup_handler_run(). */
 		res = ast_bridge_call(caller, outbound, &config);
 		ast_hangup(outbound);
 	}

Modified: team/rmudgett/hangup_handlers/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/hangup_handlers/apps/app_queue.c?view=diff&rev=369062&r1=369061&r2=369062
==============================================================================
--- team/rmudgett/hangup_handlers/apps/app_queue.c (original)
+++ team/rmudgett/hangup_handlers/apps/app_queue.c Mon Jun 18 18:11:13 2012
@@ -5432,6 +5432,7 @@
 
 		time(&callstart);
 		transfer_ds = setup_transfer_datastore(qe, member, callstart, callcompletedinsl);
+/* BUGBUG Update ast_bridge_call() here to see about calling ast_pbx_hangup_handler_run(). */
 		bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
 
 		/* If the queue member did an attended transfer, then the TRANSFER already was logged in the queue_log

Modified: team/rmudgett/hangup_handlers/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/hangup_handlers/main/features.c?view=diff&rev=369062&r1=369061&r2=369062
==============================================================================
--- team/rmudgett/hangup_handlers/main/features.c (original)
+++ team/rmudgett/hangup_handlers/main/features.c Mon Jun 18 18:11:13 2012
@@ -1035,8 +1035,10 @@
 	ast_clear_flag(ast_channel_flags(xferchan), AST_FLAGS_ALL);
 	ast_channel_clear_softhangup(xferchan, AST_SOFTHANGUP_ALL);
 
-	if (ast_do_masquerade(xferchan) || ast_pbx_start(xferchan)) {
-		/* Failed to do masquerade or could not start PBX. */
+	ast_do_masquerade(xferchan);
+	if (ast_pbx_start(xferchan)) {
+		/* Failed to start PBX. */
+		ast_pbx_hangup_handler_run(xferchan);
 		ast_hangup(xferchan);
 	}
 }
@@ -1057,7 +1059,6 @@
 static void *bridge_call_thread(void *data)
 {
 	struct ast_bridge_thread_obj *tobj = data;
-	int res;
 
 	if (tobj->callid) {
 		ast_callid_threadassoc_add(tobj->callid);
@@ -1075,26 +1076,28 @@
 	if (tobj->return_to_pbx) {
 		if (!ast_check_hangup(tobj->peer)) {
 			ast_log(LOG_VERBOSE, "putting peer %s into PBX again\n", ast_channel_name(tobj->peer));
-			res = ast_pbx_start(tobj->peer);
-			if (res != AST_PBX_SUCCESS) {
+			if (ast_pbx_start(tobj->peer)) {
 				ast_log(LOG_WARNING, "FAILED continuing PBX on peer %s\n", ast_channel_name(tobj->peer));
-				ast_hangup(tobj->peer);
+				ast_autoservice_chan_hangup_peer(tobj->chan, tobj->peer);
 			}
 		} else {
-			ast_hangup(tobj->peer);
+			ast_autoservice_chan_hangup_peer(tobj->chan, tobj->peer);
 		}
 		if (!ast_check_hangup(tobj->chan)) {
 			ast_log(LOG_VERBOSE, "putting chan %s into PBX again\n", ast_channel_name(tobj->chan));
-			res = ast_pbx_start(tobj->chan);
-			if (res != AST_PBX_SUCCESS) {
+			if (ast_pbx_start(tobj->chan)) {
 				ast_log(LOG_WARNING, "FAILED continuing PBX on chan %s\n", ast_channel_name(tobj->chan));
+				ast_pbx_hangup_handler_run(tobj->chan);
 				ast_hangup(tobj->chan);
 			}
 		} else {
+			ast_pbx_hangup_handler_run(tobj->chan);
 			ast_hangup(tobj->chan);
 		}
 	} else {
+		ast_pbx_hangup_handler_run(tobj->chan);
 		ast_hangup(tobj->chan);
+		ast_pbx_hangup_handler_run(tobj->peer);
 		ast_hangup(tobj->peer);
 	}
 
@@ -1123,6 +1126,10 @@
 	if (ast_pthread_create(&thread, &attr, bridge_call_thread, data)) {
 		/* Failed to create thread. Ditch the reference to callid. */
 		ast_callid_unref(data->callid);
+		ast_pbx_hangup_handler_run(data->chan);
+		ast_hangup(data->chan);
+		ast_pbx_hangup_handler_run(data->peer);
+		ast_hangup(data->peer);
 		ast_log(LOG_ERROR, "Failed to create bridge_call_thread.\n");
 		return;
 	}
@@ -2526,7 +2533,7 @@
 	if (ast_channel_make_compatible(c, newchan) < 0) {
 		ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
 			ast_channel_name(c), ast_channel_name(newchan));
-		ast_hangup(newchan);
+		ast_autoservice_chan_hangup_peer(c, newchan);
 		return -1;
 	}
 	return 0;
@@ -2762,7 +2769,7 @@
 		}
 
 		if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
-			ast_hangup(newchan);
+			ast_autoservice_chan_hangup_peer(transferer, newchan);
 			if (ast_stream_and_wait(transferer, xfersound, "")) {
 				ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
 			}
@@ -2783,6 +2790,7 @@
 			|| (ast_waitfordigit(newchan, 100) < 0)
 			|| ast_check_hangup(transferee)
 			|| ast_check_hangup(newchan)) {
+			ast_pbx_hangup_handler_run(newchan);
 			ast_hangup(newchan);
 			ast_party_connected_line_free(&connected_line);
 			return -1;
@@ -2882,7 +2890,7 @@
 
 		/* newchan is up, we should prepare transferee and bridge them */
 		if (ast_check_hangup(newchan)) {
-			ast_hangup(newchan);
+			ast_autoservice_chan_hangup_peer(transferee, newchan);
 			ast_party_connected_line_free(&connected_line);
 			return -1;
 		}
@@ -2897,6 +2905,7 @@
 		 */
 		ast_debug(1, "Everyone is hungup.\n");
 		if (newchan) {
+			ast_pbx_hangup_handler_run(newchan);
 			ast_hangup(newchan);
 		}
 		ast_party_connected_line_free(&connected_line);
@@ -2908,7 +2917,7 @@
 
 	xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", ast_channel_linkedid(transferee), 0, "Transfered/%s", ast_channel_name(transferee));
 	if (!xferchan) {
-		ast_hangup(newchan);
+		ast_autoservice_chan_hangup_peer(transferee, newchan);
 		ast_party_connected_line_free(&connected_line);
 		return -1;
 	}
@@ -2920,7 +2929,12 @@
 	ast_format_copy(ast_channel_readformat(xferchan), ast_channel_readformat(transferee));
 	ast_format_copy(ast_channel_writeformat(xferchan), ast_channel_writeformat(transferee));
 
-	ast_channel_masquerade(xferchan, transferee);
+	if (ast_channel_masquerade(xferchan, transferee)) {
+		ast_hangup(xferchan);
+		ast_autoservice_chan_hangup_peer(transferee, newchan);
+		ast_party_connected_line_free(&connected_line);
+		return -1;
+	}
 	ast_explicit_goto(xferchan, ast_channel_context(transferee), ast_channel_exten(transferee), ast_channel_priority(transferee));
 	ast_channel_state_set(xferchan, AST_STATE_UP);
 	ast_clear_flag(ast_channel_flags(xferchan), AST_FLAGS_ALL);
@@ -2932,7 +2946,9 @@
 	ast_clear_flag(ast_channel_flags(newchan), AST_FLAGS_ALL);
 	tobj = ast_calloc(1, sizeof(*tobj));
 	if (!tobj) {
+		ast_pbx_hangup_handler_run(xferchan);
 		ast_hangup(xferchan);
+		ast_pbx_hangup_handler_run(newchan);
 		ast_hangup(newchan);
 		ast_party_connected_line_free(&connected_line);
 		return -1;
@@ -4989,6 +5005,7 @@
 			ast_log(LOG_WARNING,
 				"Unable to restart the PBX for user on '%s', hanging them up...\n",
 				ast_channel_name(pu->chan));
+			ast_pbx_hangup_handler_run(chan);
 			ast_hangup(chan);
 		}
 
@@ -5043,6 +5060,7 @@
 
 				/* There's a problem, hang them up */
 				ast_verb(2, "%s got tired of being parked\n", ast_channel_name(chan));
+				ast_pbx_hangup_handler_run(chan);
 				ast_hangup(chan);
 
 				/* And take them out of the parking lot */
@@ -5505,7 +5523,7 @@
 				break;
 			}
 			if (res) {
-				ast_hangup(peer);
+				ast_autoservice_chan_hangup_peer(chan, peer);
 				parkinglot_unref(parkinglot);
 				return -1;
 			}
@@ -5514,7 +5532,7 @@
 		res = ast_channel_make_compatible(chan, peer);
 		if (res < 0) {
 			ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", ast_channel_name(chan), ast_channel_name(peer));
-			ast_hangup(peer);
+			ast_autoservice_chan_hangup_peer(chan, peer);
 			parkinglot_unref(parkinglot);
 			return -1;
 		}
@@ -5566,7 +5584,7 @@
 		ast_cdr_setdestchan(ast_channel_cdr(chan), ast_channel_name(peer));
 
 		/* Simulate the PBX hanging up */
-		ast_hangup(peer);
+		ast_autoservice_chan_hangup_peer(chan, peer);
 	} else {
 		if (ast_stream_and_wait(chan, "pbx-invalidpark", "")) {
 			ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", "pbx-invalidpark",
@@ -7106,8 +7124,11 @@
  *
  * Stop hold music, lock both channels, masq channels,
  * after bridge return channel to next priority.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
  */
-static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
+static int do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
 {
 	ast_moh_stop(chan);
 	ast_channel_lock_both(chan, tmpchan);
@@ -7117,13 +7138,16 @@
 	ast_channel_unlock(chan);
 	ast_channel_unlock(tmpchan);
 
-	ast_channel_masquerade(tmpchan, chan);
-
-	/* must be done without any channel locks held */
+	/* Masquerade setup and execution must be done without any channel locks held */
+	if (ast_channel_masquerade(tmpchan, chan)) {
+		return -1;
+	}
 	ast_do_masquerade(tmpchan);
 
 	/* when returning from bridge, the channel will continue at the next priority */
 	ast_explicit_goto(tmpchan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan) + 1);
+
+	return 0;
 }
 
 /*!
@@ -7137,8 +7161,7 @@
  * make the channels compatible, send error if we fail doing so
  * setup the bridge thread object and start the bridge.
  *
- * \retval 0 on success or on incorrect use.
- * \retval 1 on failure to bridge channels.
+ * \retval 0
  */
 static int action_bridge(struct mansession *s, const struct message *m)
 {
@@ -7148,6 +7171,7 @@
 	struct ast_channel *chana = NULL, *chanb = NULL, *chans[2];
 	struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
 	struct ast_bridge_thread_obj *tobj = NULL;
+	char buf[256];
 
 	/* make sure valid channels were specified */
 	if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
@@ -7157,10 +7181,7 @@
 
 	/* Start with chana */
 	chana = ast_channel_get_by_name_prefix(channela, strlen(channela));
-
-	/* send errors if any of the channels could not be found/locked */
 	if (!chana) {
-		char buf[256];
 		snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
 		astman_send_error(s, m, buf);
 		return 0;
@@ -7175,21 +7196,26 @@
 		NULL, NULL, ast_channel_linkedid(chana), 0, "Bridge/%s", ast_channel_name(chana)))) {
 		astman_send_error(s, m, "Unable to create temporary channel!");
 		chana = ast_channel_unref(chana);
-		return 1;
-	}
-
-	do_bridge_masquerade(chana, tmpchana);
+		return 0;
+	}
+
+	if (do_bridge_masquerade(chana, tmpchana)) {
+		snprintf(buf, sizeof(buf), "Unable to masquerade channel %s!", channela);
+		astman_send_error(s, m, buf);
+		ast_hangup(tmpchana);
+		chana = ast_channel_unref(chana);
+		return 0;
+	}
 
 	chana = ast_channel_unref(chana);
 
 	/* now do chanb */
 	chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb));
-	/* send errors if any of the channels could not be found/locked */
 	if (!chanb) {
-		char buf[256];
 		snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
+		astman_send_error(s, m, buf);
+		ast_pbx_hangup_handler_run(tmpchana);
 		ast_hangup(tmpchana);
-		astman_send_error(s, m, buf);
 		return 0;
 	}
 
@@ -7201,12 +7227,21 @@
 	if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
 		NULL, NULL, ast_channel_linkedid(chanb), 0, "Bridge/%s", ast_channel_name(chanb)))) {
 		astman_send_error(s, m, "Unable to create temporary channels!");
+		ast_pbx_hangup_handler_run(tmpchana);
 		ast_hangup(tmpchana);
 		chanb = ast_channel_unref(chanb);
-		return 1;
-	}
-
-	do_bridge_masquerade(chanb, tmpchanb);
+		return 0;
+	}
+
+	if (do_bridge_masquerade(chanb, tmpchanb)) {
+		snprintf(buf, sizeof(buf), "Unable to masquerade channel %s!", channelb);
+		astman_send_error(s, m, buf);
+		ast_pbx_hangup_handler_run(tmpchana);
+		ast_hangup(tmpchana);
+		ast_hangup(tmpchanb);
+		chanb = ast_channel_unref(chanb);
+		return 0;
+	}
 
 	chanb = ast_channel_unref(chanb);
 
@@ -7214,18 +7249,22 @@
 	if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
 		ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", ast_channel_name(tmpchana), ast_channel_name(tmpchanb));
 		astman_send_error(s, m, "Could not make channels compatible for manager bridge");
+		ast_pbx_hangup_handler_run(tmpchana);
 		ast_hangup(tmpchana);
+		ast_pbx_hangup_handler_run(tmpchanb);
 		ast_hangup(tmpchanb);
-		return 1;
+		return 0;
 	}
 
 	/* setup the bridge thread object and start the bridge */
 	if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
 		ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", ast_channel_name(tmpchana), ast_channel_name(tmpchanb), strerror(errno));
 		astman_send_error(s, m, "Unable to spawn a new bridge thread");
+		ast_pbx_hangup_handler_run(tmpchana);
 		ast_hangup(tmpchana);
+		ast_pbx_hangup_handler_run(tmpchanb);
 		ast_hangup(tmpchanb);
-		return 1;
+		return 0;
 	}
 
 	tobj->chan = tmpchana;
@@ -7876,11 +7915,11 @@
 	if (!strcmp(ast_channel_name(chan), args.dest_chan)) {
 		ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", ast_channel_name(chan));
 		ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
-					"Response: Failed\r\n"
-					"Reason: Unable to bridge channel to itself\r\n"
-					"Channel1: %s\r\n"
-					"Channel2: %s\r\n",
-					ast_channel_name(chan), args.dest_chan);
+			"Response: Failed\r\n"
+			"Reason: Unable to bridge channel to itself\r\n"
+			"Channel1: %s\r\n"
+			"Channel2: %s\r\n",
+			ast_channel_name(chan), args.dest_chan);
 		pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP");
 		return 0;
 	}
@@ -7888,20 +7927,15 @@
 	/* make sure we have a valid end point */
 	if (!(current_dest_chan = ast_channel_get_by_name_prefix(args.dest_chan,
 			strlen(args.dest_chan)))) {
-		ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
-			"cannot get its lock\n", args.dest_chan);
+		ast_log(LOG_WARNING, "Bridge failed because channel %s does not exist\n",
+			args.dest_chan);
 		ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
-					"Response: Failed\r\n"
-					"Reason: Cannot grab end point\r\n"
-					"Channel1: %s\r\n"
-					"Channel2: %s\r\n", ast_channel_name(chan), args.dest_chan);
+			"Response: Failed\r\n"
+			"Reason: Channel2 does not exist\r\n"
+			"Channel1: %s\r\n"
+			"Channel2: %s\r\n", ast_channel_name(chan), args.dest_chan);
 		pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
 		return 0;
-	}
-
-	/* answer the channel if needed */
-	if (ast_channel_state(current_dest_chan) != AST_STATE_UP) {
-		ast_answer(current_dest_chan);
 	}
 
 	/* try to allocate a place holder where current_dest_chan will be placed */
@@ -7909,13 +7943,45 @@
 		NULL, NULL, ast_channel_linkedid(current_dest_chan), 0, "Bridge/%s", ast_channel_name(current_dest_chan)))) {
 		ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
 		ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
-					"Response: Failed\r\n"
-					"Reason: cannot create placeholder\r\n"
-					"Channel1: %s\r\n"
-					"Channel2: %s\r\n", ast_channel_name(chan), args.dest_chan);
-	}
-
-	do_bridge_masquerade(current_dest_chan, final_dest_chan);
+			"Response: Failed\r\n"
+			"Reason: Cannot create placeholder channel\r\n"
+			"Channel1: %s\r\n"
+			"Channel2: %s\r\n", ast_channel_name(chan), args.dest_chan);
+		pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE");
+		ast_channel_unref(current_dest_chan);
+		return 0;
+	}
+
+	if (ast_test_flag(&opts, OPT_DURATION_LIMIT)
+		&& !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])
+		&& ast_bridge_timelimit(chan, &bconfig, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit)) {
+		ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
+			"Response: Failed\r\n"
+			"Reason: Cannot setup bridge time limit\r\n"
+			"Channel1: %s\r\n"
+			"Channel2: %s\r\n", ast_channel_name(chan), args.dest_chan);
+		ast_hangup(final_dest_chan);
+		pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE");
+		current_dest_chan = ast_channel_unref(current_dest_chan);
+		goto done;
+	}
+
+	if (do_bridge_masquerade(current_dest_chan, final_dest_chan)) {
+		ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
+			"Response: Failed\r\n"
+			"Reason: Cannot masquerade channels\r\n"
+			"Channel1: %s\r\n"
+			"Channel2: %s\r\n", ast_channel_name(chan), args.dest_chan);
+		ast_hangup(final_dest_chan);
+		pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE");
+		current_dest_chan = ast_channel_unref(current_dest_chan);
+		goto done;
+	}
+
+	/* answer the channel if needed */
+	if (ast_channel_state(final_dest_chan) != AST_STATE_UP) {
+		ast_answer(final_dest_chan);
+	}
 
 	chans[0] = current_dest_chan;
 	chans[1] = final_dest_chan;
@@ -7925,21 +7991,26 @@
 	if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
 		ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", ast_channel_name(chan), ast_channel_name(final_dest_chan));
 		ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
-					"Response: Failed\r\n"
-					"Reason: Could not make channels compatible for bridge\r\n"
-					"Channel1: %s\r\n"
-					"Channel2: %s\r\n", ast_channel_name(chan), ast_channel_name(final_dest_chan));
-		ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
+			"Response: Failed\r\n"
+			"Reason: Could not make channels compatible for bridge\r\n"
+			"Channel1: %s\r\n"
+			"Channel2: %s\r\n", ast_channel_name(chan), ast_channel_name(final_dest_chan));
+
+		/* Maybe we should return this channel to the PBX? */
+		ast_autoservice_chan_hangup_peer(chan, final_dest_chan);
+
 		pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
 		current_dest_chan = ast_channel_unref(current_dest_chan);
-		return 0;
+		goto done;
 	}
 
 	/* Report that the bridge will be successfull */
 	ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
-				"Response: Success\r\n"
-				"Channel1: %s\r\n"
-				"Channel2: %s\r\n", ast_channel_name(chan), ast_channel_name(final_dest_chan));
+		"Response: Success\r\n"
+		"Channel1: %s\r\n"
+		"Channel2: %s\r\n", ast_channel_name(chan), ast_channel_name(final_dest_chan));
+
+	current_dest_chan = ast_channel_unref(current_dest_chan);
 
 	/* we have 2 valid channels to bridge, now it is just a matter of setting up the bridge config and starting the bridge */
 	if (ast_test_flag(&opts, BRIDGE_OPT_PLAYTONE) && !ast_strlen_zero(xfersound)) {
@@ -7947,13 +8018,6 @@
 			if (ast_waitstream(final_dest_chan, "") < 0)
 				ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", ast_channel_name(final_dest_chan));
 		}
-	}
-
-	current_dest_chan = ast_channel_unref(current_dest_chan);
-
-	if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
-		if (ast_bridge_timelimit(chan, &bconfig, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit))
-			goto done;
 	}
 
 	if (ast_test_flag(&opts, OPT_CALLEE_TRANSFER))
@@ -7975,57 +8039,57 @@
 
 	ast_bridge_call(chan, final_dest_chan, &bconfig);
 
-	/* the bridge has ended, set BRIDGERESULT to SUCCESS. If the other channel has not been hung up, return it to the PBX */
+	/* The bridge has ended, set BRIDGERESULT to SUCCESS. */
 	pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS");
+
+	/* If the other channel has not been hung up, return it to the PBX */
 	if (!ast_check_hangup(final_dest_chan)) {
 		if (ast_test_flag(&opts, OPT_CALLEE_GO_ON)) {
-			char *caller_context = ast_strdupa(ast_channel_context(chan));
-			char *caller_extension = ast_strdupa(ast_channel_exten(chan));
-			int caller_priority = ast_channel_priority(chan);
+			char *caller_context;
+			char *caller_extension;
+			int caller_priority;
+			int goto_opt;
+
+			ast_channel_lock(chan);
+			caller_context = ast_strdupa(ast_channel_context(chan));
+			caller_extension = ast_strdupa(ast_channel_exten(chan));
+			caller_priority = ast_channel_priority(chan);
+			ast_channel_unlock(chan);
 
 			if (!ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {
 				ast_replace_subargument_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
 				/* Set current dialplan position to bridger dialplan position */
-				ast_goto_if_exists(final_dest_chan, caller_context, caller_extension, caller_priority);
-				/* Then perform the goto */
-				if (ast_parseable_goto(final_dest_chan, opt_args[OPT_ARG_CALLEE_GO_ON]) == AST_PBX_SUCCESS) {
-					ast_pbx_start(final_dest_chan);
-				} else {
-					ast_hangup(final_dest_chan);
-				}
+				goto_opt = ast_goto_if_exists(final_dest_chan, caller_context, caller_extension, caller_priority)
+					/* Then perform the goto */
+					|| ast_parseable_goto(final_dest_chan, opt_args[OPT_ARG_CALLEE_GO_ON]);
 			} else { /* F() */
-				if (ast_goto_if_exists(final_dest_chan, caller_context, caller_extension, caller_priority + 1) == AST_PBX_GOTO_FAILED) {
-					ast_hangup(final_dest_chan);
-				} else {
-					ast_pbx_start(final_dest_chan);
-				}
+				goto_opt = ast_goto_if_exists(final_dest_chan, caller_context, caller_extension, caller_priority + 1);
+			}
+			if (goto_opt || ast_pbx_start(final_dest_chan)) {
+				ast_autoservice_chan_hangup_peer(chan, final_dest_chan);
 			}
 		} else if (!ast_test_flag(&opts, OPT_CALLEE_KILL)) {
 			ast_debug(1, "starting new PBX in %s,%s,%d for chan %s\n",
 				ast_channel_context(final_dest_chan), ast_channel_exten(final_dest_chan),
 				ast_channel_priority(final_dest_chan), ast_channel_name(final_dest_chan));
 
-			if (ast_pbx_start(final_dest_chan) != AST_PBX_SUCCESS) {
+			if (ast_pbx_start(final_dest_chan)) {
 				ast_log(LOG_WARNING, "FAILED continuing PBX on dest chan %s\n", ast_channel_name(final_dest_chan));
-				ast_hangup(final_dest_chan);
+				ast_autoservice_chan_hangup_peer(chan, final_dest_chan);
 			} else {
 				ast_debug(1, "SUCCESS continuing PBX on chan %s\n", ast_channel_name(final_dest_chan));
 			}
+		} else {
+			ast_autoservice_chan_hangup_peer(chan, final_dest_chan);
 		}
 	} else {
-			ast_debug(1, "hangup chan %s since the other endpoint has hung up or the x flag was passed\n", ast_channel_name(final_dest_chan));
-		ast_hangup(final_dest_chan);
+		ast_debug(1, "chan %s was hungup\n", ast_channel_name(final_dest_chan));
+		ast_autoservice_chan_hangup_peer(chan, final_dest_chan);
 	}
 done:
-	if (bconfig.warning_sound) {
-		ast_free((char *)bconfig.warning_sound);
-	}
-	if (bconfig.end_sound) {
-		ast_free((char *)bconfig.end_sound);
-	}
-	if (bconfig.start_sound) {
-		ast_free((char *)bconfig.start_sound);
-	}
+	ast_free((char *) bconfig.warning_sound);
+	ast_free((char *) bconfig.end_sound);
+	ast_free((char *) bconfig.start_sound);
 
 	return 0;
 }

Modified: team/rmudgett/hangup_handlers/main/pbx.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/hangup_handlers/main/pbx.c?view=diff&rev=369062&r1=369061&r2=369062
==============================================================================
--- team/rmudgett/hangup_handlers/main/pbx.c (original)
+++ team/rmudgett/hangup_handlers/main/pbx.c Mon Jun 18 18:11:13 2012
@@ -5403,7 +5403,6 @@
 	ast_channel_unlock(chan);
 }
 
-/* BUGBUG need to examine all ast_bridge_call() to see about calling ast_pbx_hangup_handler_run(). */
 int ast_pbx_hangup_handler_run(struct ast_channel *chan)
 {
 	struct ast_hangup_handler_list *handlers;




More information about the asterisk-commits mailing list