[asterisk-commits] rmudgett: branch 13 r430034 - /branches/13/main/bridge_basic.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Dec 22 15:18:27 CST 2014
Author: rmudgett
Date: Mon Dec 22 15:18:22 2014
New Revision: 430034
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=430034
Log:
DTMF atxfer: Setup recall channels as if the transferee initiated the call.
After the initial DTMF atxfer call attempt to the transfer target fails to
answer during a blonde transfer, the recall callback channels do not get
setup with information from the initial transferrer channel. As a result,
the recall callback to the transferrer does not have callid, channel
variables, datastores, accountcode, peeraccount, COLP, and CLID setup. A
similar situation happens with the recall callback to the transfer target
but it is less visible. The recall callback to the transfer target does
not have callid, channel variables, datastores, accountcode, peeraccount,
and COLP setup.
* Added missing information to the recall callback channels before
initiating the call. callid, channel variables, datastores, accountcode,
peeraccount, COLP, and CLID
* Set callid of the transferrer channel on the DTMF atxfer controller
thread attended_transfer_monitor_thread().
* Added missing channel unlocks and props unref to off nominal paths in
attended_transfer_properties_alloc().
ASTERISK-23841 #close
Reported by: Richard Mudgett
Review: https://reviewboard.asterisk.org/r/4259/
Modified:
branches/13/main/bridge_basic.c
Modified: branches/13/main/bridge_basic.c
URL: http://svnview.digium.com/svn/asterisk/branches/13/main/bridge_basic.c?view=diff&rev=430034&r1=430033&r2=430034
==============================================================================
--- branches/13/main/bridge_basic.c (original)
+++ branches/13/main/bridge_basic.c Mon Dec 22 15:18:22 2014
@@ -45,6 +45,7 @@
#include "asterisk/app.h"
#include "asterisk/dial.h"
#include "asterisk/stasis_bridges.h"
+#include "asterisk/stasis_channels.h"
#include "asterisk/features.h"
#include "asterisk/format_cache.h"
#include "asterisk/test.h"
@@ -1347,6 +1348,8 @@
struct ast_dial *dial;
/*! The bridging features the transferer has available */
struct ast_flags transferer_features;
+ /*! Saved transferer connected line data for recalling the transferer. */
+ struct ast_party_connected_line original_transferer_colp;
};
static void attended_transfer_properties_destructor(void *obj)
@@ -1361,6 +1364,7 @@
ast_channel_cleanup(props->transferer);
ast_channel_cleanup(props->transfer_target);
ast_channel_cleanup(props->recall_target);
+ ast_party_connected_line_free(&props->original_transferer_colp);
ast_string_field_free_memory(props);
ast_cond_destroy(&props->cond);
}
@@ -1428,6 +1432,7 @@
xfer_cfg = ast_get_chan_features_xfer_config(props->transferer);
if (!xfer_cfg) {
ast_log(LOG_ERROR, "Unable to get transfer configuration from channel %s\n", ast_channel_name(props->transferer));
+ ast_channel_unlock(props->transferer);
ao2_ref(props, -1);
return NULL;
}
@@ -1443,11 +1448,20 @@
ast_string_field_set(props, failsound, xfer_cfg->xferfailsound);
ast_string_field_set(props, xfersound, xfer_cfg->xfersound);
+ /*
+ * Save the transferee's party information for any recall calls.
+ * This is the only piece of information needed that gets overwritten
+ * on the transferer channel by the inital call to the transfer target.
+ */
+ ast_party_connected_line_copy(&props->original_transferer_colp,
+ ast_channel_connected(props->transferer));
+
tech = ast_strdupa(ast_channel_name(props->transferer));
addr = strchr(tech, '/');
if (!addr) {
ast_log(LOG_ERROR, "Transferer channel name does not follow typical channel naming format (tech/address)\n");
- ast_channel_unref(props->transferer);
+ ast_channel_unlock(props->transferer);
+ ao2_ref(props, -1);
return NULL;
}
*addr++ = '\0';
@@ -2331,10 +2345,50 @@
}
}
+/*!
+ * \internal
+ * \brief Setup common things to transferrer and transfer_target recall channels.
+ *
+ * \param recall Channel for recalling a party.
+ * \param transferer Channel supplying recall information.
+ *
+ * \details
+ * Setup callid, variables, datastores, accountcode, and peeraccount.
+ *
+ * \pre Both channels are locked on entry.
+ *
+ * \pre COLP and CLID on the recall channel are setup by the caller but not
+ * explicitly published yet.
+ *
+ * \return Nothing
+ */
+static void common_recall_channel_setup(struct ast_channel *recall, struct ast_channel *transferer)
+{
+ struct ast_callid *callid;
+
+ callid = ast_read_threadstorage_callid();
+ if (callid) {
+ ast_channel_callid_set(recall, callid);
+ ast_callid_unref(callid);
+ }
+
+ ast_channel_inherit_variables(transferer, recall);
+ ast_channel_datastore_inherit(transferer, recall);
+
+ /*
+ * Stage a snapshot to ensure that a snapshot is always done
+ * on the recall channel so earler COLP and CLID setup will
+ * get published.
+ */
+ ast_channel_stage_snapshot(recall);
+ ast_channel_req_accountcodes(recall, transferer, AST_CHANNEL_REQUESTOR_REPLACEMENT);
+ ast_channel_stage_snapshot_done(recall);
+}
static int recalling_enter(struct attended_transfer_properties *props)
{
RAII_VAR(struct ast_format_cap *, cap, ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
+ struct ast_channel *recall;
if (!cap) {
return -1;
@@ -2360,7 +2414,26 @@
return -1;
}
- ast_dial_set_state_callback(props->dial, &recall_callback);
+ /*
+ * Setup callid, variables, datastores, accountcode, peeraccount,
+ * COLP, and CLID on the recalled transferrer.
+ */
+ recall = ast_dial_get_channel(props->dial, 0);
+ if (!recall) {
+ return -1;
+ }
+ ast_channel_lock_both(recall, props->transferer);
+
+ ast_party_caller_copy(ast_channel_caller(recall),
+ ast_channel_caller(props->transferer));
+ ast_party_connected_line_copy(ast_channel_connected(recall),
+ &props->original_transferer_colp);
+
+ common_recall_channel_setup(recall, props->transferer);
+ ast_channel_unlock(recall);
+ ast_channel_unlock(props->transferer);
+
+ ast_dial_set_state_callback(props->dial, recall_callback);
ao2_ref(props, +1);
ast_dial_set_user_data(props->dial, props);
@@ -2487,6 +2560,20 @@
return -1;
}
+ /*
+ * Setup callid, variables, datastores, accountcode, peeraccount,
+ * and COLP on the recalled transfer target.
+ */
+ ast_channel_lock_both(props->recall_target, props->transferer);
+
+ ast_party_connected_line_copy(ast_channel_connected(props->recall_target),
+ &props->original_transferer_colp);
+ ast_party_id_reset(&ast_channel_connected(props->recall_target)->priv);
+
+ common_recall_channel_setup(props->recall_target, props->recall_target);
+ ast_channel_unlock(props->recall_target);
+ ast_channel_unlock(props->transferer);
+
if (ast_call(props->recall_target, destination, 0)) {
ast_log(LOG_ERROR, "Unable to place outbound call to recall target\n");
ast_hangup(props->recall_target);
@@ -2881,6 +2968,18 @@
static void *attended_transfer_monitor_thread(void *data)
{
struct attended_transfer_properties *props = data;
+ struct ast_callid *callid;
+
+ /*
+ * Set thread callid to the transferer's callid because we
+ * are doing all this on that channel's behalf.
+ */
+ ast_channel_lock(props->transferer);
+ callid = ast_channel_callid(props->transferer);
+ ast_channel_unlock(props->transferer);
+ if (callid) {
+ ast_callid_threadassoc_add(callid);
+ }
for (;;) {
enum attended_transfer_stimulus stimulus;
@@ -2912,6 +3011,11 @@
}
attended_transfer_properties_shutdown(props);
+
+ if (callid) {
+ ast_callid_unref(callid);
+ ast_callid_threadassoc_remove();
+ }
return NULL;
}
More information about the asterisk-commits
mailing list