[asterisk-commits] rmudgett: branch rmudgett/bridge_phase r390089 - in /team/rmudgett/bridge_pha...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed May 29 15:39:40 CDT 2013


Author: rmudgett
Date: Wed May 29 15:39:36 2013
New Revision: 390089

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=390089
Log:
Rework attended and blind transfer hold/unhold handling.

Modified:
    team/rmudgett/bridge_phase/bridges/bridge_builtin_features.c
    team/rmudgett/bridge_phase/include/asterisk/bridging.h
    team/rmudgett/bridge_phase/include/asterisk/channel.h
    team/rmudgett/bridge_phase/main/bridging.c
    team/rmudgett/bridge_phase/main/channel.c

Modified: team/rmudgett/bridge_phase/bridges/bridge_builtin_features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/bridges/bridge_builtin_features.c?view=diff&rev=390089&r1=390088&r2=390089
==============================================================================
--- team/rmudgett/bridge_phase/bridges/bridge_builtin_features.c (original)
+++ team/rmudgett/bridge_phase/bridges/bridge_builtin_features.c Wed May 29 15:39:36 2013
@@ -185,7 +185,7 @@
 	const char *context;
 	char *goto_on_blindxfr;
 
-	ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD, NULL, 0);
+	ast_bridge_channel_write_hold(bridge_channel, NULL);
 
 	ast_channel_lock(bridge_channel->chan);
 	context = ast_strdupa(get_transfer_context(bridge_channel->chan,
@@ -196,7 +196,7 @@
 
 	/* Grab the extension to transfer to */
 	if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
-		ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
+		ast_bridge_channel_write_unhold(bridge_channel);
 		return 0;
 	}
 
@@ -205,8 +205,6 @@
 				ast_channel_name(bridge_channel->chan), goto_on_blindxfr);
 		ast_after_bridge_set_go_on(bridge_channel->chan, NULL, NULL, 0, goto_on_blindxfr);
 	}
-
-	ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
 
 	if (ast_bridge_transfer_blind(bridge_channel->chan, exten, context, blind_transfer_cb,
 			bridge_channel->chan) != AST_BRIDGE_TRANSFER_SUCCESS &&
@@ -272,7 +270,7 @@
 	const char *context;
 	enum atxfer_code transfer_code = ATXFER_INCOMPLETE;
 
-	ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD, NULL, 0);
+	ast_bridge_channel_write_hold(bridge_channel, NULL);
 
 	bridge = ast_bridge_channel_merge_inhibit(bridge_channel, +1);
 
@@ -285,7 +283,7 @@
 	if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
 		ast_bridge_merge_inhibit(bridge, -1);
 		ao2_ref(bridge, -1);
-		ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
+		ast_bridge_channel_write_unhold(bridge_channel);
 		return 0;
 	}
 
@@ -296,7 +294,7 @@
 		ao2_ref(bridge, -1);
 /* BUGBUG beeperr needs to be configurable from features.conf */
 		ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
-		ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
+		ast_bridge_channel_write_unhold(bridge_channel);
 		return 0;
 	}
 
@@ -324,7 +322,7 @@
 		ao2_ref(bridge, -1);
 /* BUGBUG beeperr needs to be configurable from features.conf */
 		ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
-		ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
+		ast_bridge_channel_write_unhold(bridge_channel);
 		return 0;
 	}
 
@@ -338,7 +336,7 @@
 		ao2_ref(bridge, -1);
 /* BUGBUG beeperr needs to be configurable from features.conf */
 		ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
-		ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
+		ast_bridge_channel_write_unhold(bridge_channel);
 		return 0;
 	}
 	ast_bridge_merge_inhibit(attended_bridge, +1);
@@ -353,7 +351,7 @@
 		ao2_ref(bridge, -1);
 /* BUGBUG beeperr needs to be configurable from features.conf */
 		ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
-		ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
+		ast_bridge_channel_write_unhold(bridge_channel);
 		return 0;
 	}
 
@@ -412,7 +410,7 @@
 		break;
 	case ATXFER_COMPLETE:
 		/* The peer takes our place in the bridge. */
-		ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
+		ast_bridge_channel_write_unhold(bridge_channel);
 		ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
 		xfer_failed = ast_bridge_impart(bridge_channel->bridge, peer, bridge_channel->chan, NULL, 1);
 		break;
@@ -423,7 +421,7 @@
 		 * Just impart the peer onto the bridge and have us return to it
 		 * as normal.
 		 */
-		ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
+		ast_bridge_channel_write_unhold(bridge_channel);
 		xfer_failed = ast_bridge_impart(bridge_channel->bridge, peer, NULL, NULL, 1);
 		break;
 	case ATXFER_ABORT:
@@ -437,7 +435,7 @@
 		if (!ast_check_hangup_locked(bridge_channel->chan)) {
 			ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
 		}
-		ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
+		ast_bridge_channel_write_unhold(bridge_channel);
 	}
 
 	return 0;

Modified: team/rmudgett/bridge_phase/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/include/asterisk/bridging.h?view=diff&rev=390089&r1=390088&r2=390089
==============================================================================
--- team/rmudgett/bridge_phase/include/asterisk/bridging.h (original)
+++ team/rmudgett/bridge_phase/include/asterisk/bridging.h Wed May 29 15:39:36 2013
@@ -1110,6 +1110,27 @@
 void ast_bridge_channel_write_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen);
 
 /*!
+ * \brief Write a hold frame into the bridge.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel is putting the hold into the bridge.
+ * \param moh_class The suggested music class for the other end to use.
+ *
+ * \return Nothing
+ */
+void ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, const char *moh_class);
+
+/*!
+ * \brief Write an unhold frame into the bridge.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel is putting the hold into the bridge.
+ *
+ * \return Nothing
+ */
+void ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel);
+
+/*!
  * \brief Run an application on the bridge channel.
  * \since 12.0.0
  *

Modified: team/rmudgett/bridge_phase/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/include/asterisk/channel.h?view=diff&rev=390089&r1=390088&r2=390089
==============================================================================
--- team/rmudgett/bridge_phase/include/asterisk/channel.h (original)
+++ team/rmudgett/bridge_phase/include/asterisk/channel.h Wed May 29 15:39:36 2013
@@ -1155,6 +1155,18 @@
  */
 struct ast_channel *ast_dummy_channel_alloc(void);
 #endif
+
+/*!
+ * \brief Publish a channel blob message.
+ * \since 12.0.0
+ *
+ * \param chan Channel publishing the blob.
+ * \param type Type of stasis message.
+ * \param blob The blob being published. (NULL if no blob)
+ *
+ * \return Nothing
+ */
+void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob);
 
 /*!
  * \brief Queue one or more frames to a channel's frame queue

Modified: team/rmudgett/bridge_phase/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/bridging.c?view=diff&rev=390089&r1=390088&r2=390089
==============================================================================
--- team/rmudgett/bridge_phase/main/bridging.c (original)
+++ team/rmudgett/bridge_phase/main/bridging.c Wed May 29 15:39:36 2013
@@ -43,6 +43,7 @@
 #include "asterisk/bridging_basic.h"
 #include "asterisk/bridging_technology.h"
 #include "asterisk/stasis_bridging.h"
+#include "asterisk/stasis_channels.h"
 #include "asterisk/app.h"
 #include "asterisk/file.h"
 #include "asterisk/module.h"
@@ -717,6 +718,32 @@
 	bridge_channel_write_frame(bridge_channel, &frame);
 }
 
+void ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, const char *moh_class)
+{
+	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+	size_t datalen;
+
+	if (!ast_strlen_zero(moh_class)) {
+		datalen = strlen(moh_class) + 1;
+
+		blob = ast_json_pack("{s: s}",
+			"musicclass", moh_class);
+	} else {
+		moh_class = NULL;
+		datalen = 0;
+	}
+
+	ast_channel_publish_blob(bridge_channel->chan, ast_channel_hold_type(), blob);
+	ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD, moh_class,
+		datalen);
+}
+
+void ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel)
+{
+	ast_channel_publish_blob(bridge_channel->chan, ast_channel_unhold_type(), NULL);
+	ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
+}
+
 static int run_app_helper(struct ast_channel *chan, const char *app_name, const char *app_args)
 {
 	int res = 0;
@@ -741,21 +768,14 @@
 void ast_bridge_channel_run_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
 {
 	if (moh_class) {
-		if (ast_strlen_zero(moh_class)) {
-			ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD,
-				NULL, 0);
-		} else {
-			ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD,
-				moh_class, strlen(moh_class) + 1);
-		}
+		ast_bridge_channel_write_hold(bridge_channel, moh_class);
 	}
 	if (run_app_helper(bridge_channel->chan, app_name, S_OR(app_args, ""))) {
 		/* Break the bridge if the app returns non-zero. */
 		bridge_handle_hangup(bridge_channel);
 	}
 	if (moh_class) {
-		ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD,
-			NULL, 0);
+		ast_bridge_channel_write_unhold(bridge_channel);
 	}
 }
 
@@ -824,13 +844,7 @@
 void ast_bridge_channel_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
 {
 	if (moh_class) {
-		if (ast_strlen_zero(moh_class)) {
-			ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD,
-				NULL, 0);
-		} else {
-			ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD,
-				moh_class, strlen(moh_class) + 1);
-		}
+		ast_bridge_channel_write_hold(bridge_channel, moh_class);
 	}
 	if (custom_play) {
 		custom_play(bridge_channel, playfile);
@@ -838,8 +852,7 @@
 		ast_stream_and_wait(bridge_channel->chan, playfile, AST_DIGIT_NONE);
 	}
 	if (moh_class) {
-		ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD,
-			NULL, 0);
+		ast_bridge_channel_write_unhold(bridge_channel);
 	}
 
 	/*
@@ -5484,24 +5497,47 @@
 	ao2_iterator_destroy(&iter);
 }
 
+static struct ast_bridge *acquire_bridge(struct ast_channel *chan)
+{
+	struct ast_bridge *bridge;
+
+	ast_channel_lock(chan);
+	bridge = ast_channel_get_bridge(chan);
+	ast_channel_unlock(chan);
+
+	if (bridge
+		&& ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY)) {
+		ao2_ref(bridge, -1);
+		bridge = NULL;
+	}
+
+	return bridge;
+}
+
 enum ast_transfer_result ast_bridge_transfer_blind(struct ast_channel *transferer,
 		const char *exten, const char *context,
 		transfer_channel_cb new_channel_cb, void *user_data)
 {
 	RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
 	RAII_VAR(struct ao2_container *, channels, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_channel *, transferee, NULL, ao2_cleanup);
 	int do_bridge_transfer;
 	int transfer_prohibited;
 	enum try_parking_result parking_result;
 
-	ast_channel_lock(transferer);
-	bridge = ast_channel_get_bridge(transferer);
-	ast_channel_unlock(transferer);
-
+	bridge = acquire_bridge(transferer);
 	if (!bridge) {
 		return AST_BRIDGE_TRANSFER_INVALID;
 	}
+	ast_channel_lock(transferer);
+	bridge_channel = ast_channel_get_bridge_channel(transferer);
+	ast_channel_unlock(transferer);
+	if (!bridge_channel) {
+		return AST_BRIDGE_TRANSFER_INVALID;
+	}
+
+	ast_bridge_channel_write_unhold(bridge_channel);
 
 	parking_result = try_parking(bridge, transferer, exten, context);
 	switch (parking_result) {
@@ -5555,23 +5591,6 @@
 
 	ast_bridge_remove(bridge, transferer);
 	return AST_BRIDGE_TRANSFER_SUCCESS;
-}
-
-static struct ast_bridge *acquire_bridge(struct ast_channel *chan)
-{
-	struct ast_bridge *bridge;
-
-	ast_channel_lock(chan);
-	bridge = ast_channel_get_bridge(chan);
-	ast_channel_unlock(chan);
-
-	if (bridge
-		&& ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY)) {
-		ao2_ref(bridge, -1);
-		bridge = NULL;
-	}
-
-	return bridge;
 }
 
 /*!
@@ -5666,9 +5685,10 @@
 {
 	RAII_VAR(struct ast_bridge *, to_transferee_bridge, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_bridge *, to_target_bridge, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_bridge_channel *, to_transferee_bridge_channel, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_bridge_channel *, to_target_bridge_channel, NULL, ao2_cleanup);
 	RAII_VAR(struct ao2_container *, channels, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_channel *, transferee, NULL, ao2_cleanup);
-	const char *target_complete_sound;
 	struct ast_bridge *the_bridge;
 	struct ast_channel *chan_bridged;
 	struct ast_channel *chan_unbridged;
@@ -5683,13 +5703,27 @@
 		return AST_BRIDGE_TRANSFER_INVALID;
 	}
 
-	/* Is there a courtesy sound to play to the target? */
-	if (to_target_bridge) {
-		struct ast_bridge_channel *to_target_bridge_channel;
-
+	ast_channel_lock(to_transferee);
+	to_transferee_bridge_channel = ast_channel_get_bridge_channel(to_transferee);
+	ast_channel_unlock(to_transferee);
+
+	ast_channel_lock(to_transfer_target);
+	to_target_bridge_channel = ast_channel_get_bridge_channel(to_transfer_target);
+	ast_channel_unlock(to_transfer_target);
+
+	if (to_transferee_bridge_channel) {
+		/* Take off hold if they are on hold. */
+		ast_bridge_channel_write_unhold(to_transferee_bridge_channel);
+	}
+
+	if (to_target_bridge_channel) {
+		const char *target_complete_sound;
+
+		/* Take off hold if they are on hold. */
+		ast_bridge_channel_write_unhold(to_target_bridge_channel);
+
+		/* Is there a courtesy sound to play to the target? */
 		ast_channel_lock(to_transfer_target);
-		to_target_bridge_channel = ast_channel_get_bridge_channel(to_transfer_target);
-
 		target_complete_sound = pbx_builtin_getvar_helper(to_transfer_target,
 			"ATTENDED_TRANSFER_COMPLETE_SOUND");
 		if (!ast_strlen_zero(target_complete_sound)) {
@@ -5698,7 +5732,6 @@
 			target_complete_sound = NULL;
 		}
 		ast_channel_unlock(to_transfer_target);
-
 		if (!target_complete_sound) {
 			ast_channel_lock(to_transferee);
 			target_complete_sound = pbx_builtin_getvar_helper(to_transferee,
@@ -5710,29 +5743,19 @@
 			}
 			ast_channel_unlock(to_transferee);
 		}
-
 		if (target_complete_sound) {
 			ast_bridge_channel_write_playfile(to_target_bridge_channel, NULL,
 				target_complete_sound, NULL);
 		}
-		ao2_cleanup(to_target_bridge_channel);
-	} else {
-		target_complete_sound = NULL;
 	}
 
 	/* Let's get the easy one out of the way first */
 	if (to_transferee_bridge && to_target_bridge) {
-		RAII_VAR(struct ast_bridge_channel *, to_transferee_bridge_channel, NULL, ao2_cleanup);
-		RAII_VAR(struct ast_bridge_channel *, to_target_bridge_channel, NULL, ao2_cleanup);
 		enum ast_transfer_result res;
 
-		ast_channel_lock(to_transferee);
-		to_transferee_bridge_channel = ast_channel_get_bridge_channel(to_transferee);
-		ast_channel_unlock(to_transferee);
-
-		ast_channel_lock(to_transfer_target);
-		to_target_bridge_channel = ast_channel_get_bridge_channel(to_transfer_target);
-		ast_channel_unlock(to_transfer_target);
+		if (!to_transferee_bridge_channel || !to_target_bridge_channel) {
+			return AST_BRIDGE_TRANSFER_INVALID;
+		}
 
 		ast_bridge_lock_both(to_transferee_bridge, to_target_bridge);
 		res = two_bridge_attended_transfer(to_transferee, to_transferee_bridge_channel,

Modified: team/rmudgett/bridge_phase/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/channel.c?view=diff&rev=390089&r1=390088&r2=390089
==============================================================================
--- team/rmudgett/bridge_phase/main/channel.c (original)
+++ team/rmudgett/bridge_phase/main/channel.c Wed May 29 15:39:36 2013
@@ -1348,11 +1348,10 @@
 	return __ast_queue_frame(chan, fin, 1, NULL);
 }
 
-/*! \internal \brief Publish a channel blob message */
-static void publish_channel_blob(struct ast_channel *chan,
-	struct stasis_message_type *type, struct ast_json *blob)
+void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
 {
 	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+
 	if (!blob) {
 		blob = ast_json_null();
 	}
@@ -1372,7 +1371,7 @@
 	/* Yeah, let's not change a lock-critical value without locking */
 	ast_channel_lock(chan);
 	ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV);
-	publish_channel_blob(chan, ast_channel_hangup_request_type(), NULL);
+	ast_channel_publish_blob(chan, ast_channel_hangup_request_type(), NULL);
 
 	res = ast_queue_frame(chan, &f);
 	ast_channel_unlock(chan);
@@ -1398,7 +1397,7 @@
 	}
 	blob = ast_json_pack("{s: i}",
 			     "cause", cause);
-	publish_channel_blob(chan, ast_channel_hangup_request_type(), blob);
+	ast_channel_publish_blob(chan, ast_channel_hangup_request_type(), blob);
 
 	res = ast_queue_frame(chan, &f);
 	ast_channel_unlock(chan);
@@ -1419,7 +1418,7 @@
 				     "musicclass", musicclass);
 	}
 
-	publish_channel_blob(chan, ast_channel_hold_type(), blob);
+	ast_channel_publish_blob(chan, ast_channel_hold_type(), blob);
 
 	res = ast_queue_frame(chan, &f);
 	return res;
@@ -1430,7 +1429,7 @@
 	struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_UNHOLD };
 	int res;
 
-	publish_channel_blob(chan, ast_channel_unhold_type(), NULL);
+	ast_channel_publish_blob(chan, ast_channel_unhold_type(), NULL);
 
 	res = ast_queue_frame(chan, &f);
 	return res;
@@ -2741,7 +2740,7 @@
 	blob = ast_json_pack("{s: i, s: b}",
 			     "cause", cause,
 			     "soft", 1);
-	publish_channel_blob(chan, ast_channel_hangup_request_type(), blob);
+	ast_channel_publish_blob(chan, ast_channel_hangup_request_type(), blob);
 	ast_channel_unlock(chan);
 
 	return res;
@@ -3755,7 +3754,7 @@
 		return;
 	}
 
-	publish_channel_blob(chan, ast_channel_dtmf_begin_type(), blob);
+	ast_channel_publish_blob(chan, ast_channel_dtmf_begin_type(), blob);
 }
 
 static void send_dtmf_end_event(struct ast_channel *chan,
@@ -3772,7 +3771,7 @@
 		return;
 	}
 
-	publish_channel_blob(chan, ast_channel_dtmf_end_type(), blob);
+	ast_channel_publish_blob(chan, ast_channel_dtmf_end_type(), blob);
 }
 
 static void ast_read_generator_actions(struct ast_channel *chan, struct ast_frame *f)




More information about the asterisk-commits mailing list