[asterisk-commits] jrose: branch 12 r414400 - in /branches/12: channels/ include/asterisk/ main/...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu May 22 10:44:24 CDT 2014
Author: jrose
Date: Thu May 22 10:44:11 2014
New Revision: 414400
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=414400
Log:
res_pjsip_refer: Fix bugs involving Parking/PJSIP/transfers
PJSIP would never send the final 200 Notify for a blind transfer
when transferring to parking. This patch fixes that. In addition,
it fixes a reference leak when performing blind transfers to
non-bridging extensions.
Review: https://reviewboard.asterisk.org/r/3485/
Modified:
branches/12/channels/chan_dahdi.c
branches/12/channels/chan_mgcp.c
branches/12/channels/chan_sip.c
branches/12/channels/sig_analog.c
branches/12/include/asterisk/bridge.h
branches/12/include/asterisk/parking.h
branches/12/main/bridge.c
branches/12/main/bridge_basic.c
branches/12/main/parking.c
branches/12/res/parking/parking_applications.c
branches/12/res/parking/parking_bridge_features.c
branches/12/res/res_pjsip_refer.c
Modified: branches/12/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/channels/chan_dahdi.c?view=diff&rev=414400&r1=414399&r2=414400
==============================================================================
--- branches/12/channels/chan_dahdi.c (original)
+++ branches/12/channels/chan_dahdi.c Thu May 22 10:44:11 2014
@@ -9731,7 +9731,7 @@
bridge_channel = ast_channel_get_bridge_channel(p->subs[SUB_THREEWAY].owner);
ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
if (bridge_channel) {
- if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten)) {
+ if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten, NULL, NULL)) {
/*
* Swap things around between the three-way and real call so we
* can hear where the channel got parked.
Modified: branches/12/channels/chan_mgcp.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/channels/chan_mgcp.c?view=diff&rev=414400&r1=414399&r2=414400
==============================================================================
--- branches/12/channels/chan_mgcp.c (original)
+++ branches/12/channels/chan_mgcp.c Thu May 22 10:44:11 2014
@@ -3167,7 +3167,7 @@
ast_channel_lock(chan);
bridge_channel = ast_channel_get_bridge_channel(chan);
ast_channel_unlock(chan);
- if (bridge_channel && !ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), p->dtmf_buf)) {
+ if (bridge_channel && !ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), p->dtmf_buf, NULL, NULL)) {
ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan));
}
break;
Modified: branches/12/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/channels/chan_sip.c?view=diff&rev=414400&r1=414399&r2=414400
==============================================================================
--- branches/12/channels/chan_sip.c (original)
+++ branches/12/channels/chan_sip.c Thu May 22 10:44:11 2014
@@ -26289,10 +26289,10 @@
* \param user_data A blind_transfer_cb_data struct
* \param transfer_type Unused
*/
-static void blind_transfer_cb(struct ast_channel *chan, void *user_data,
+static void blind_transfer_cb(struct ast_channel *chan, struct transfer_channel_data *user_data_wrapper,
enum ast_transfer_type transfer_type)
{
- struct blind_transfer_cb_data *cb_data = user_data;
+ struct blind_transfer_cb_data *cb_data = user_data_wrapper->data;
pbx_builtin_setvar_helper(chan, "SIPTRANSFER", "yes");
pbx_builtin_setvar_helper(chan, "SIPTRANSFER_REFERER", cb_data->referred_by);
Modified: branches/12/channels/sig_analog.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/channels/sig_analog.c?view=diff&rev=414400&r1=414399&r2=414400
==============================================================================
--- branches/12/channels/sig_analog.c (original)
+++ branches/12/channels/sig_analog.c Thu May 22 10:44:11 2014
@@ -2259,7 +2259,7 @@
bridge_channel = ast_channel_get_bridge_channel(p->subs[ANALOG_SUB_THREEWAY].owner);
ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner);
if (bridge_channel) {
- if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten)) {
+ if (!ast_parking_blind_transfer_park(bridge_channel, ast_channel_context(chan), exten, NULL, NULL)) {
/*
* Swap things around between the three-way and real call so we
* can hear where the channel got parked.
Modified: branches/12/include/asterisk/bridge.h
URL: http://svnview.digium.com/svn/asterisk/branches/12/include/asterisk/bridge.h?view=diff&rev=414400&r1=414399&r2=414400
==============================================================================
--- branches/12/include/asterisk/bridge.h (original)
+++ branches/12/include/asterisk/bridge.h Thu May 22 10:44:11 2014
@@ -904,6 +904,22 @@
};
/*!
+ * \brief AO2 object that wraps data for transfer_channel_cb
+ */
+struct transfer_channel_data {
+ void *data; /*! Data to be used by the transfer_channel_cb -- note that this
+ * pointer is going to be pointing to something on the stack, so
+ * it must not be used at any point after returning from the
+ * transfer_channel_cb. */
+ int completed; /*! Initially 0, This will be set to 1 by either the transfer
+ * code or by transfer code hooks (e.g. parking) when the
+ * transfer is completed and any remaining actions have taken
+ * place (e.g. parking announcements). It will never be reset
+ * to 0. This is used for deferring progress for channel
+ * drivers that support deferred progress. */
+};
+
+/*!
* \brief Callback function type called during blind transfers
*
* A caller of ast_bridge_transfer_blind() may wish to set data on
@@ -914,7 +930,7 @@
* \param user_data User-provided data needed in the callback
* \param transfer_type The type of transfer being completed
*/
-typedef void (*transfer_channel_cb)(struct ast_channel *chan, void *user_data,
+typedef void (*transfer_channel_cb)(struct ast_channel *chan, struct transfer_channel_data *user_data,
enum ast_transfer_type transfer_type);
/*!
Modified: branches/12/include/asterisk/parking.h
URL: http://svnview.digium.com/svn/asterisk/branches/12/include/asterisk/parking.h?view=diff&rev=414400&r1=414399&r2=414400
==============================================================================
--- branches/12/include/asterisk/parking.h (original)
+++ branches/12/include/asterisk/parking.h Thu May 22 10:44:11 2014
@@ -24,6 +24,7 @@
*/
#include "asterisk/stringfields.h"
+#include "asterisk/bridge.h"
/*!
* \brief The default parking application that Asterisk expects.
@@ -163,6 +164,8 @@
* \param parker The \ref bridge_channel object that is initiating the parking
* \param context The context to blind transfer to
* \param exten The extension to blind transfer to
+ * \param parked_channel_cb Execute the following function on the the channel that gets parked
+ * \param parked_channel_data Data for the parked_channel_cb
*
* \note If the bridge \ref parker is in has more than one other occupant, the entire
* bridge will be parked using a Local channel
@@ -172,7 +175,8 @@
* \retval 0 on success
* \retval non-zero on error
*/
- int (* parking_blind_transfer_park)(struct ast_bridge_channel *parker, const char *context, const char *exten);
+ int (* parking_blind_transfer_park)(struct ast_bridge_channel *parker, const char *context,
+ const char *exten, transfer_channel_cb parked_channel_cb, struct transfer_channel_data *parked_channel_data);
/*!
* \brief Perform a direct park on a channel in a bridge.
@@ -224,6 +228,9 @@
* \param parker The \ref bridge_channel object that is initiating the parking
* \param context The context to blind transfer to
* \param exten The extension to blind transfer to
+ * \param exten The extension to blind transfer to
+ * \param parked_channel_cb Execute the following function on the the channel that gets parked
+ * \param parked_channel_data Data for the parked_channel_cb
*
* \note If the bridge \ref parker is in has more than one other occupant, the entire
* bridge will be parked using a Local channel
@@ -233,7 +240,8 @@
* \retval 0 on success
* \retval non-zero on error
*/
-int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context, const char *exten);
+int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context,
+ const char *exten, transfer_channel_cb parked_channel_cb, struct transfer_channel_data *parked_channel_data);
/*!
* \brief Perform a direct park on a channel in a bridge.
Modified: branches/12/main/bridge.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/main/bridge.c?view=diff&rev=414400&r1=414399&r2=414400
==============================================================================
--- branches/12/main/bridge.c (original)
+++ branches/12/main/bridge.c Thu May 22 10:44:11 2014
@@ -3718,7 +3718,7 @@
*/
static enum ast_transfer_result blind_transfer_bridge(struct ast_channel *transferer,
struct ast_bridge *bridge, const char *exten, const char *context,
- transfer_channel_cb new_channel_cb, void *user_data)
+ transfer_channel_cb new_channel_cb, struct transfer_channel_data *user_data_wrapper)
{
struct ast_channel *local;
char chan_name[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
@@ -3734,7 +3734,7 @@
pbx_builtin_setvar_helper(local, BLINDTRANSFER, ast_channel_name(transferer));
if (new_channel_cb) {
- new_channel_cb(local, user_data, AST_BRIDGE_TRANSFER_MULTI_PARTY);
+ new_channel_cb(local, user_data_wrapper, AST_BRIDGE_TRANSFER_MULTI_PARTY);
}
if (ast_call(local, chan_name, 0)) {
@@ -3968,7 +3968,9 @@
return transferee;
}
-static enum ast_transfer_result try_parking(struct ast_channel *transferer, const char *context, const char *exten)
+static enum ast_transfer_result try_parking(struct ast_channel *transferer,
+ const char *context, const char *exten, transfer_channel_cb new_channel_cb,
+ struct transfer_channel_data *user_data_wrapper)
{
RAII_VAR(struct ast_bridge_channel *, transferer_bridge_channel, NULL, ao2_cleanup);
@@ -3985,7 +3987,7 @@
}
if (ast_parking_blind_transfer_park(transferer_bridge_channel,
- context, exten)) {
+ context, exten, new_channel_cb, user_data_wrapper)) {
return AST_BRIDGE_TRANSFER_FAIL;
}
@@ -4089,6 +4091,7 @@
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, ast_channel_cleanup);
+ RAII_VAR(struct transfer_channel_data *, user_data_wrapper, NULL, ao2_cleanup);
int do_bridge_transfer;
int transfer_prohibited;
enum ast_transfer_result transfer_result;
@@ -4106,13 +4109,24 @@
goto publish;
}
+ user_data_wrapper = ao2_alloc(sizeof(*user_data_wrapper), NULL);
+ if (!user_data_wrapper) {
+ transfer_result = AST_BRIDGE_TRANSFER_FAIL;
+ goto publish;
+ }
+
+ user_data_wrapper->data = user_data;
+
/* Take off hold if they are on hold. */
ast_bridge_channel_write_unhold(bridge_channel);
- transfer_result = try_parking(transferer, context, exten);
+ transfer_result = try_parking(transferer, context, exten, new_channel_cb, user_data_wrapper);
if (transfer_result == AST_BRIDGE_TRANSFER_SUCCESS) {
goto publish;
}
+
+ /* Since parking didn't take control of the user_data_wrapper, we are just going to raise the completed flag now. */
+ user_data_wrapper->completed = 1;
{
SCOPED_LOCK(lock, bridge, ast_bridge_lock, ast_bridge_unlock);
@@ -4142,7 +4156,7 @@
if (do_bridge_transfer) {
transfer_result = blind_transfer_bridge(transferer, bridge, exten, context,
- new_channel_cb, user_data);
+ new_channel_cb, user_data_wrapper);
goto publish;
}
@@ -4155,7 +4169,7 @@
}
if (bridge_channel_internal_queue_blind_transfer(transferee, exten, context,
- new_channel_cb, user_data)) {
+ new_channel_cb, user_data_wrapper)) {
transfer_result = AST_BRIDGE_TRANSFER_FAIL;
goto publish;
}
Modified: branches/12/main/bridge_basic.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/main/bridge_basic.c?view=diff&rev=414400&r1=414399&r2=414400
==============================================================================
--- branches/12/main/bridge_basic.c (original)
+++ branches/12/main/bridge_basic.c Thu May 22 10:44:11 2014
@@ -3145,10 +3145,10 @@
return 0;
}
-static void blind_transfer_cb(struct ast_channel *new_channel, void *user_data,
+static void blind_transfer_cb(struct ast_channel *new_channel, struct transfer_channel_data *user_data_wrapper,
enum ast_transfer_type transfer_type)
{
- struct ast_channel *transferer_channel = user_data;
+ struct ast_channel *transferer_channel = user_data_wrapper->data;
if (transfer_type == AST_BRIDGE_TRANSFER_MULTI_PARTY) {
copy_caller_data(new_channel, transferer_channel);
Modified: branches/12/main/parking.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/main/parking.c?view=diff&rev=414400&r1=414399&r2=414400
==============================================================================
--- branches/12/main/parking.c (original)
+++ branches/12/main/parking.c Thu May 22 10:44:11 2014
@@ -142,7 +142,9 @@
return table->parking_park_bridge_channel(parkee, parkee_uuid, parker_uuid, app_data);
}
-int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker, const char *context, const char *exten)
+int ast_parking_blind_transfer_park(struct ast_bridge_channel *parker,
+ const char *context, const char *exten, transfer_channel_cb parked_channel_cb,
+ struct transfer_channel_data *parked_channel_data)
{
RAII_VAR(struct ast_parking_bridge_feature_fn_table *, table,
ao2_global_obj_ref(parking_provider), ao2_cleanup);
@@ -153,10 +155,10 @@
if (table->module_info) {
SCOPED_MODULE_USE(table->module_info->self);
- return table->parking_blind_transfer_park(parker, context, exten);
- }
-
- return table->parking_blind_transfer_park(parker, context, exten);
+ return table->parking_blind_transfer_park(parker, context, exten, parked_channel_cb, parked_channel_data);
+ }
+
+ return table->parking_blind_transfer_park(parker, context, exten, parked_channel_cb, parked_channel_data);
}
int ast_parking_park_call(struct ast_bridge_channel *parker, char *exten, size_t length)
Modified: branches/12/res/parking/parking_applications.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/parking/parking_applications.c?view=diff&rev=414400&r1=414399&r2=414400
==============================================================================
--- branches/12/res/parking/parking_applications.c (original)
+++ branches/12/res/parking/parking_applications.c Thu May 22 10:44:11 2014
@@ -516,6 +516,7 @@
if (!silence_announcements && !transferer) {
ast_stream_and_wait(chan, "pbx-parkingfailed", "");
}
+ publish_parked_call_failure(chan);
return 0;
}
@@ -523,6 +524,7 @@
res = ast_bridge_features_init(&chan_features);
if (res) {
ast_bridge_features_cleanup(&chan_features);
+ publish_parked_call_failure(chan);
return -1;
}
Modified: branches/12/res/parking/parking_bridge_features.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/parking/parking_bridge_features.c?view=diff&rev=414400&r1=414399&r2=414400
==============================================================================
--- branches/12/res/parking/parking_bridge_features.c (original)
+++ branches/12/res/parking/parking_bridge_features.c Thu May 22 10:44:11 2014
@@ -49,6 +49,7 @@
};
struct parked_subscription_data {
+ struct transfer_channel_data *transfer_data;
char *parkee_uuid;
int hangup_after:1;
char parker_uuid[0];
@@ -89,7 +90,7 @@
const char *parkee_to_act_on = data->parkee_uuid;
char saynum_buf[16];
struct ast_channel_snapshot *parkee_snapshot = message->parkee;
- RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_channel *, parker, NULL, ast_channel_cleanup);
RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
if (strcmp(parkee_to_act_on, parkee_snapshot->uniqueid)) {
@@ -113,22 +114,35 @@
return;
}
+ /* This subscription callback will block for the duration of the announcement if
+ * parked_subscription_data is tracking a transfer_channel_data struct. */
if (message->event_type == PARKED_CALL) {
/* queue the saynum on the bridge channel and hangup */
snprintf(saynum_buf, sizeof(saynum_buf), "%u %u", data->hangup_after, message->parkingspace);
- ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL);
- wipe_subscription_datastore(bridge_channel->chan);
- }
-
- if (message->event_type == PARKED_CALL_FAILED) {
- ast_bridge_channel_queue_playfile(bridge_channel, NULL, "pbx-parkingfailed", NULL);
- wipe_subscription_datastore(bridge_channel->chan);
+ if (!data->transfer_data) {
+ ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL);
+ } else {
+ ast_bridge_channel_queue_playfile_sync(bridge_channel, say_parking_space, saynum_buf, NULL);
+ data->transfer_data->completed = 1;
+ }
+ wipe_subscription_datastore(parker);
+ } else if (message->event_type == PARKED_CALL_FAILED) {
+ if (!data->transfer_data) {
+ ast_bridge_channel_queue_playfile(bridge_channel, NULL, "pbx-parkingfailed", NULL);
+ } else {
+ ast_bridge_channel_queue_playfile_sync(bridge_channel, NULL, "pbx-parkingfailed", NULL);
+ data->transfer_data->completed = 1;
+ }
+ wipe_subscription_datastore(parker);
}
}
static void parker_update_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
{
if (stasis_subscription_final_message(sub, message)) {
+ struct parked_subscription_data *ps_data = data;
+ ao2_cleanup(ps_data->transfer_data);
+ ps_data->transfer_data = NULL;
ast_free(data);
return;
}
@@ -139,7 +153,8 @@
}
}
-int create_parked_subscription(struct ast_channel *chan, const char *parkee_uuid, int hangup_after)
+static int create_parked_subscription_full(struct ast_channel *chan, const char *parkee_uuid, int hangup_after,
+ struct transfer_channel_data *parked_channel_data)
{
struct ast_datastore *datastore;
struct parked_subscription_datastore *parked_datastore;
@@ -167,6 +182,11 @@
return -1;
}
+ if (parked_channel_data) {
+ subscription_data->transfer_data = parked_channel_data;
+ ao2_ref(parked_channel_data, +1);
+ }
+
subscription_data->hangup_after = hangup_after;
subscription_data->parkee_uuid = subscription_data->parker_uuid + parker_uuid_size;
strcpy(subscription_data->parkee_uuid, parkee_uuid);
@@ -183,6 +203,11 @@
ast_channel_unlock(chan);
return 0;
+}
+
+int create_parked_subscription(struct ast_channel *chan, const char *parkee_uuid, int hangup_after)
+{
+ return create_parked_subscription_full(chan, parkee_uuid, hangup_after, NULL);
}
/*!
@@ -191,7 +216,7 @@
* identical to the dial_transfer function in bridge_basic.c, however it doesn't swap the
* local channel and the channel that instigated the park.
*/
-static struct ast_channel *park_local_transfer(struct ast_channel *parker, const char *context, const char *exten)
+static struct ast_channel *park_local_transfer(struct ast_channel *parker, const char *context, const char *exten, struct transfer_channel_data *parked_channel_data)
{
char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
struct ast_channel *parkee;
@@ -220,7 +245,11 @@
ast_channel_unlock(parkee);
/* We need to have the parker subscribe to the new local channel before hand. */
- create_parked_subscription(parker, ast_channel_uniqueid(parkee_side_2), 1);
+ if (create_parked_subscription_full(parker, ast_channel_uniqueid(parkee_side_2), 1, parked_channel_data)) {
+ ast_channel_unref(parkee_side_2);
+ ast_hangup(parkee);
+ return NULL;
+ }
ast_bridge_set_transfer_variables(parkee_side_2, ast_channel_name(parker), 0);
@@ -272,14 +301,21 @@
* \param bridge_channel The bridge_channel representing the channel performing the park
* \param context The context to blind transfer to
* \param exten The extension to blind transfer to
+ * \param parked_channel_cb Optional callback executed prior to sending the parked channel into the bridge
+ * \param parked_channel_data Data for the parked_channel_cb
*
* \retval 0 on success
* \retval non-zero on error
*/
static int parking_blind_transfer_park(struct ast_bridge_channel *bridge_channel,
- const char *context, const char *exten)
+ const char *context, const char *exten, transfer_channel_cb parked_channel_cb,
+ struct transfer_channel_data *parked_channel_data)
{
RAII_VAR(struct ast_bridge_channel *, other, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_channel *, other_chan, NULL, ast_channel_cleanup);
+
+ struct ast_exten *e;
+ struct pbx_find_info find_info = { .stacklen = 0 };
int peer_count;
if (ast_strlen_zero(context) || ast_strlen_zero(exten)) {
@@ -299,6 +335,8 @@
if (peer_count == 2) {
other = ast_bridge_channel_peer(bridge_channel);
ao2_ref(other, +1);
+ other_chan = other->chan;
+ ast_channel_ref(other_chan);
}
ast_bridge_unlock(bridge_channel->bridge);
@@ -313,33 +351,47 @@
if (peer_count > 2) {
struct ast_channel *transfer_chan = NULL;
- transfer_chan = park_local_transfer(bridge_channel->chan, context, exten);
+ transfer_chan = park_local_transfer(bridge_channel->chan, context, exten, parked_channel_data);
if (!transfer_chan) {
return -1;
}
+ ast_channel_ref(transfer_chan);
+
+ if (parked_channel_cb) {
+ parked_channel_cb(transfer_chan, parked_channel_data, AST_BRIDGE_TRANSFER_MULTI_PARTY);
+ }
if (ast_bridge_impart(bridge_channel->bridge, transfer_chan, NULL, NULL,
AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
ast_hangup(transfer_chan);
+ ast_channel_unref(transfer_chan);
return -1;
}
+
+ ast_channel_unref(transfer_chan);
+
return 0;
}
/* Subscribe to park messages with the other channel entering */
- if (create_parked_subscription(bridge_channel->chan, ast_channel_uniqueid(other->chan), 1)) {
- return -1;
- }
+ if (create_parked_subscription_full(bridge_channel->chan, ast_channel_uniqueid(other->chan), 1, parked_channel_data)) {
+ return -1;
+ }
+
+ if (parked_channel_cb) {
+ parked_channel_cb(other_chan, parked_channel_data, AST_BRIDGE_TRANSFER_SINGLE_PARTY);
+ }
+
+ e = pbx_find_extension(NULL, NULL, &find_info, context, exten, 1, NULL, NULL, E_MATCH);
/* Write the park frame with the intended recipient and other data out to the bridge. */
ast_bridge_channel_write_park(bridge_channel,
- ast_channel_uniqueid(other->chan),
+ ast_channel_uniqueid(other_chan),
ast_channel_uniqueid(bridge_channel->chan),
- NULL);
+ e ? ast_get_extension_app_data(e) : NULL);
return 0;
}
-
/*!
* \internal
@@ -444,7 +496,7 @@
if (exten) {
ast_copy_string(exten, lot->cfg->parkext, length);
}
- return parking_blind_transfer_park(parker, lot->cfg->parking_con, lot->cfg->parkext);
+ return parking_blind_transfer_park(parker, lot->cfg->parking_con, lot->cfg->parkext, NULL, NULL);
}
static int feature_park_call(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Modified: branches/12/res/res_pjsip_refer.c
URL: http://svnview.digium.com/svn/asterisk/branches/12/res/res_pjsip_refer.c?view=diff&rev=414400&r1=414399&r2=414400
==============================================================================
--- branches/12/res/res_pjsip_refer.c (original)
+++ branches/12/res/res_pjsip_refer.c Thu May 22 10:44:11 2014
@@ -55,6 +55,8 @@
struct ast_taskprocessor *serializer;
/*! \brief Stasis subscription for bridge events */
struct stasis_subscription *bridge_sub;
+ /*! \brief Reference to transfer_channel_data related to the refer */
+ struct transfer_channel_data *transfer_data;
/*! \brief Uniqueid of transferee channel */
char *transferee;
};
@@ -165,6 +167,12 @@
return;
}
+ if (!progress->transfer_data->completed) {
+ /* We can't act on this message because the transfer_channel_data doesn't show that
+ * the transfer is ready to progress */
+ return;
+ }
+
/* OMG the transferee is joining a bridge. His call got answered! */
notification = refer_progress_notification_alloc(progress, 200, PJSIP_EVSUB_STATE_TERMINATED);
if (notification) {
@@ -183,6 +191,11 @@
/* We only care about frames *to* the channel */
if (!f || (event != AST_FRAMEHOOK_EVENT_WRITE)) {
+ return f;
+ }
+
+ /* If the completed flag hasn't been raised, skip this pass. */
+ if (!progress->transfer_data->completed) {
return f;
}
@@ -241,6 +254,10 @@
ao2_cleanup(notification);
}
+ if (progress->bridge_sub) {
+ progress->bridge_sub = stasis_unsubscribe(progress->bridge_sub);
+ }
+
ao2_cleanup(progress);
}
@@ -296,6 +313,8 @@
if (progress->bridge_sub) {
progress->bridge_sub = stasis_unsubscribe(progress->bridge_sub);
}
+
+ ao2_cleanup(progress->transfer_data);
ast_free(progress->transferee);
ast_taskprocessor_unreference(progress->serializer);
@@ -473,9 +492,10 @@
};
/*! \brief Blind transfer callback function */
-static void refer_blind_callback(struct ast_channel *chan, void *user_data, enum ast_transfer_type transfer_type)
-{
- struct refer_blind *refer = user_data;
+static void refer_blind_callback(struct ast_channel *chan, struct transfer_channel_data *user_data_wrapper,
+ enum ast_transfer_type transfer_type)
+{
+ struct refer_blind *refer = user_data_wrapper->data;
pjsip_generic_string_hdr *referred_by;
static const pj_str_t str_referred_by = { "Referred-By", 11 };
@@ -503,6 +523,10 @@
refer_progress_notify(notification);
}
}
+
+ /* Progress needs a reference to the transfer_channel_data so that it can track the completed status of the transfer */
+ ao2_ref(user_data_wrapper, +1);
+ refer->progress->transfer_data = user_data_wrapper;
/* We need to bump the reference count up on the progress structure since it is in the frame hook now */
ao2_ref(refer->progress, +1);
More information about the asterisk-commits
mailing list