[asterisk-commits] rmudgett: trunk r390289 - in /trunk: bridges/ include/asterisk/ main/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri May 31 10:34:30 CDT 2013
Author: rmudgett
Date: Fri May 31 10:34:20 2013
New Revision: 390289
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=390289
Log:
Fixup hold/unhold with attended and blind transfers.
* DTMF attended and blind transfers have hold/unhold behavior restored.
* External attended and blind transfers unhold the transfered party when
the transfer is initiated.
* Made prohibit blind transferring a bridge marked as masquerade only.
(ConfBridge bridges)
* Made running an application or playing a file inside a bridge post the
hold/unhold messages if MOH is requested.
Review: https://reviewboard.asterisk.org/r/2574/
Modified:
trunk/bridges/bridge_builtin_features.c
trunk/include/asterisk/bridging.h
trunk/include/asterisk/stasis_channels.h
trunk/main/bridging.c
trunk/main/channel.c
trunk/main/stasis_channels.c
Modified: trunk/bridges/bridge_builtin_features.c
URL: http://svnview.digium.com/svn/asterisk/trunk/bridges/bridge_builtin_features.c?view=diff&rev=390289&r1=390288&r2=390289
==============================================================================
--- trunk/bridges/bridge_builtin_features.c (original)
+++ trunk/bridges/bridge_builtin_features.c Fri May 31 10:34:20 2013
@@ -182,7 +182,8 @@
const char *context;
char *goto_on_blindxfr;
-/* BUGBUG the peer needs to be put on hold for the transfer. */
+ ast_bridge_channel_write_hold(bridge_channel, NULL);
+
ast_channel_lock(bridge_channel->chan);
context = ast_strdupa(get_transfer_context(bridge_channel->chan,
blind_transfer ? blind_transfer->context : NULL));
@@ -192,6 +193,7 @@
/* Grab the extension to transfer to */
if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
+ ast_bridge_channel_write_unhold(bridge_channel);
return 0;
}
@@ -264,9 +266,10 @@
const char *context;
enum atxfer_code transfer_code = ATXFER_INCOMPLETE;
+ ast_bridge_channel_write_hold(bridge_channel, NULL);
+
bridge = ast_bridge_channel_merge_inhibit(bridge_channel, +1);
-/* BUGBUG the peer needs to be put on hold for the transfer. */
ast_channel_lock(bridge_channel->chan);
context = ast_strdupa(get_transfer_context(bridge_channel->chan,
attended_transfer ? attended_transfer->context : NULL));
@@ -276,6 +279,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_unhold(bridge_channel);
return 0;
}
@@ -286,6 +290,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_unhold(bridge_channel);
return 0;
}
@@ -313,6 +318,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_unhold(bridge_channel);
return 0;
}
@@ -326,6 +332,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_unhold(bridge_channel);
return 0;
}
ast_bridge_merge_inhibit(attended_bridge, +1);
@@ -340,6 +347,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_unhold(bridge_channel);
return 0;
}
@@ -384,6 +392,7 @@
break;
case ATXFER_COMPLETE:
/* The peer takes our place in the bridge. */
+ 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;
@@ -394,6 +403,7 @@
* Just impart the peer onto the bridge and have us return to it
* as normal.
*/
+ ast_bridge_channel_write_unhold(bridge_channel);
xfer_failed = ast_bridge_impart(bridge_channel->bridge, peer, NULL, NULL, 1);
break;
case ATXFER_ABORT:
@@ -407,6 +417,7 @@
if (!ast_check_hangup_locked(bridge_channel->chan)) {
ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_NONE);
}
+ ast_bridge_channel_write_unhold(bridge_channel);
}
return 0;
Modified: trunk/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/bridging.h?view=diff&rev=390289&r1=390288&r2=390289
==============================================================================
--- trunk/include/asterisk/bridging.h (original)
+++ trunk/include/asterisk/bridging.h Fri May 31 10:34:20 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: trunk/include/asterisk/stasis_channels.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/stasis_channels.h?view=diff&rev=390289&r1=390288&r2=390289
==============================================================================
--- trunk/include/asterisk/stasis_channels.h (original)
+++ trunk/include/asterisk/stasis_channels.h Fri May 31 10:34:20 2013
@@ -273,6 +273,19 @@
const char *role, struct ast_channel_snapshot *snapshot);
/*!
+ * \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);
+
+/*!
* \since 12
* \brief Publish a \ref ast_channel_snapshot for a channel.
*
Modified: trunk/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/bridging.c?view=diff&rev=390289&r1=390288&r2=390289
==============================================================================
--- trunk/main/bridging.c (original)
+++ trunk/main/bridging.c Fri May 31 10:34:20 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"
@@ -714,6 +715,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;
@@ -738,21 +765,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);
}
}
@@ -821,13 +841,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);
@@ -835,8 +849,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);
}
/*
@@ -5428,24 +5441,48 @@
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;
+ }
+
+ /* Take off hold if they are on hold. */
+ ast_bridge_channel_write_unhold(bridge_channel);
parking_result = try_parking(bridge, transferer, exten, context);
switch (parking_result) {
@@ -5499,26 +5536,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) {
- return NULL;
- }
-
- if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_MASQUERADE_ONLY)) {
- ao2_ref(bridge, -1);
- bridge = NULL;
- }
-
- return bridge;
}
/*!
@@ -5613,6 +5630,8 @@
{
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);
struct ast_bridge *the_bridge;
@@ -5629,19 +5648,31 @@
return AST_BRIDGE_TRANSFER_INVALID;
}
+ 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) {
+ /* Take off hold if they are on hold. */
+ ast_bridge_channel_write_unhold(to_target_bridge_channel);
+ }
+
/* 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: trunk/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel.c?view=diff&rev=390289&r1=390288&r2=390289
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Fri May 31 10:34:20 2013
@@ -1348,21 +1348,6 @@
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)
-{
- RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
- if (!blob) {
- blob = ast_json_null();
- }
-
- message = ast_channel_blob_create(chan, type, blob);
- if (message) {
- stasis_publish(ast_channel_topic(chan), message);
- }
-}
-
/*! \brief Queue a hangup frame for channel */
int ast_queue_hangup(struct ast_channel *chan)
{
@@ -1372,7 +1357,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 +1383,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 +1404,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 +1415,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 +2726,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 +3740,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 +3757,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)
Modified: trunk/main/stasis_channels.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/stasis_channels.c?view=diff&rev=390289&r1=390288&r2=390289
==============================================================================
--- trunk/main/stasis_channels.c (original)
+++ trunk/main/stasis_channels.c Fri May 31 10:34:20 2013
@@ -484,6 +484,20 @@
return obj->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();
+ }
+
+ message = ast_channel_blob_create(chan, type, blob);
+ if (message) {
+ stasis_publish(ast_channel_topic(chan), message);
+ }
+}
+
void ast_channel_publish_snapshot(struct ast_channel *chan)
{
RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
More information about the asterisk-commits
mailing list