Stasis: Add information to blind transfer event

When a blind transfer occurs that is forced to create a local channel
pair to satisfy the transfer request, information about the local
channel pair is not published. This adds a field to describe that
channel to the blind transfer message struct so that this information
is conveyed properly to consumers of the blind transfer message.

This also fixes a bug in which Stasis() was unable to properly identify
the channel that was replacing an existing Stasis-controlled channel
due to a blind transfer.

Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3921/
........

Merged revisions 421537 from http://svn.asterisk.org/svn/asterisk/branches/12
........

Merged revisions 421538 from http://svn.asterisk.org/svn/asterisk/branches/13


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@421539 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Kinsey Moore
2014-08-20 13:06:33 +00:00
parent 01f1ff1f77
commit 36f4bff943
8 changed files with 106 additions and 33 deletions

View File

@@ -3805,6 +3805,26 @@ struct ast_channel *ast_bridge_peer(struct ast_bridge *bridge, struct ast_channe
return peer;
}
static void publish_blind_transfer_full(int is_external, enum ast_transfer_result result,
struct ast_channel *transferer, struct ast_bridge *bridge,
const char *context, const char *exten, struct ast_channel *transferee_channel,
struct ast_channel *replace_channel)
{
struct ast_bridge_channel_pair pair;
pair.channel = transferer;
pair.bridge = bridge;
if (bridge) {
ast_bridge_lock(bridge);
}
ast_bridge_publish_blind_transfer(is_external, result, &pair, context, exten,
transferee_channel, replace_channel);
if (bridge) {
ast_bridge_unlock(bridge);
}
}
/*!
* \internal
* \brief Transfer an entire bridge to a specific destination.
@@ -3817,16 +3837,21 @@ struct ast_channel *ast_bridge_peer(struct ast_bridge *bridge, struct ast_channe
* bridges, this method is only used for multi-party bridges since this method would
* be less efficient for two-party bridges.
*
* \param is_external Whether the transfer is externally initiated
* \param transferer The channel performing a transfer
* \param bridge The bridge where the transfer is being performed
* \param exten The destination extension for the blind transfer
* \param transferee The party being transferred if there is only one
* \param context The destination context for the blind transfer
* \param hook Framehook to attach to local channel
*
* \return The success or failure of the operation
*/
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, struct transfer_channel_data *user_data_wrapper)
static enum ast_transfer_result blind_transfer_bridge(int is_external,
struct ast_channel *transferer, struct ast_bridge *bridge,
const char *exten, const char *context, struct ast_channel *transferee,
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];
@@ -3858,6 +3883,8 @@ static enum ast_transfer_result blind_transfer_bridge(struct ast_channel *transf
ast_hangup(local);
return AST_BRIDGE_TRANSFER_FAIL;
}
publish_blind_transfer_full(is_external, AST_BRIDGE_TRANSFER_SUCCESS, transferer, bridge,
context, exten, transferee, local);
return AST_BRIDGE_TRANSFER_SUCCESS;
}
@@ -4214,16 +4241,8 @@ static void publish_blind_transfer(int is_external, enum ast_transfer_result res
struct ast_channel *transferer, struct ast_bridge *bridge,
const char *context, const char *exten, struct ast_channel *transferee_channel)
{
struct ast_bridge_channel_pair pair;
pair.channel = transferer;
pair.bridge = bridge;
if (bridge) {
ast_bridge_lock(bridge);
}
ast_bridge_publish_blind_transfer(is_external, result, &pair, context, exten, transferee_channel);
if (bridge) {
ast_bridge_unlock(bridge);
}
publish_blind_transfer_full(is_external, result, transferer, bridge, context,
exten, transferee_channel, NULL);
}
enum ast_transfer_result ast_bridge_transfer_blind(int is_external,
@@ -4301,8 +4320,12 @@ enum ast_transfer_result ast_bridge_transfer_blind(int is_external,
set_transfer_variables_all(transferer, channels, 0);
if (do_bridge_transfer) {
transfer_result = blind_transfer_bridge(transferer, bridge, exten, context,
new_channel_cb, user_data_wrapper);
/* if blind_transfer_bridge succeeds, it publishes its own message */
transfer_result = blind_transfer_bridge(is_external, transferer, bridge,
exten, context, transferee, new_channel_cb, user_data_wrapper);
if (transfer_result == AST_BRIDGE_TRANSFER_SUCCESS) {
return transfer_result;
}
goto publish;
}

View File

@@ -636,7 +636,10 @@ static struct ast_json *blind_transfer_to_json(struct stasis_message *msg,
const struct stasis_message_sanitizer *sanitize)
{
struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
struct ast_json *json_transferer, *json_transferee = NULL, *out;
struct ast_json *json_transferer;
struct ast_json *json_transferee = NULL;
struct ast_json *out;
struct ast_json *json_replace = NULL;
const struct timeval *tv = stasis_message_timestamp(msg);
json_transferer = ast_channel_snapshot_to_json(transfer_msg->to_transferee.channel_snapshot, sanitize);
@@ -647,6 +650,16 @@ static struct ast_json *blind_transfer_to_json(struct stasis_message *msg,
if (transfer_msg->transferee) {
json_transferee = ast_channel_snapshot_to_json(transfer_msg->transferee, sanitize);
if (!json_transferee) {
ast_json_unref(json_transferer);
return NULL;
}
}
if (transfer_msg->replace_channel) {
json_replace = ast_channel_snapshot_to_json(transfer_msg->replace_channel, sanitize);
if (!json_replace) {
ast_json_unref(json_transferee);
ast_json_unref(json_transferer);
return NULL;
}
}
@@ -661,10 +674,18 @@ static struct ast_json *blind_transfer_to_json(struct stasis_message *msg,
"is_external", ast_json_boolean(transfer_msg->is_external));
if (!out) {
ast_json_unref(json_transferee);
ast_json_unref(json_replace);
return NULL;
}
if (json_transferee && ast_json_object_set(out, "transferee", json_transferee)) {
ast_json_unref(out);
ast_json_unref(json_replace);
return NULL;
}
if (json_replace && ast_json_object_set(out, "replace_channel", json_replace)) {
ast_json_unref(out);
return NULL;
}
@@ -741,7 +762,7 @@ static void blind_transfer_dtor(void *obj)
void ast_bridge_publish_blind_transfer(int is_external, enum ast_transfer_result result,
struct ast_bridge_channel_pair *transferer, const char *context, const char *exten,
struct ast_channel *transferee_channel)
struct ast_channel *transferee_channel, struct ast_channel *replace_channel)
{
struct ast_blind_transfer_message *msg;
struct stasis_message *stasis;
@@ -759,6 +780,9 @@ void ast_bridge_publish_blind_transfer(int is_external, enum ast_transfer_result
if (transferee_channel) {
msg->transferee = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferee_channel));
}
if (replace_channel) {
msg->replace_channel = ast_channel_snapshot_get_latest(ast_channel_uniqueid(replace_channel));
}
msg->is_external = is_external;
msg->result = result;
ast_copy_string(msg->context, context, sizeof(msg->context));