summaryrefslogtreecommitdiff
path: root/main/stasis_bridges.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/stasis_bridges.c')
-rw-r--r--main/stasis_bridges.c219
1 files changed, 160 insertions, 59 deletions
diff --git a/main/stasis_bridges.c b/main/stasis_bridges.c
index 56f7605f7..c94d2ea10 100644
--- a/main/stasis_bridges.c
+++ b/main/stasis_bridges.c
@@ -62,6 +62,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
contacted. It means that a party was succesfully placed into the dialplan at the expected location.</para></note>
</parameter>
<channel_snapshot prefix="Transferer"/>
+ <channel_snapshot prefix="Transferee"/>
<bridge_snapshot/>
<parameter name="IsExternal">
<para>Indicates if the transfer was performed outside of Asterisk. For instance,
@@ -113,6 +114,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<para>The name of the surviving transferer channel when a transfer results in a threeway call</para>
<note><para>This header is only present when <replaceable>DestType</replaceable> is <literal>Threeway</literal></para></note>
</parameter>
+ <channel_snapshot prefix="Transferee" />
</syntax>
<description>
<para>The headers in this event attempt to describe all the major details of the attended transfer. The two transferer channels
@@ -633,30 +635,41 @@ static const char *result_strs[] = {
static struct ast_json *blind_transfer_to_json(struct stasis_message *msg,
const struct stasis_message_sanitizer *sanitize)
{
- struct ast_bridge_blob *blob = stasis_message_data(msg);
- struct ast_json *json_channel, *out;
+ struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
+ struct ast_json *json_transferer, *json_transferee, *out;
const struct timeval *tv = stasis_message_timestamp(msg);
- json_channel = ast_channel_snapshot_to_json(blob->channel, sanitize);
- if (!json_channel) {
+ json_transferer = ast_channel_snapshot_to_json(transfer_msg->to_transferee.channel_snapshot, sanitize);
+ if (!json_transferer) {
return NULL;
}
- out = ast_json_pack("{s: s, s: o, s: o, s: O, s: O, s: s, s: o}",
+ if (transfer_msg->transferee) {
+ json_transferee = ast_channel_snapshot_to_json(transfer_msg->transferee, sanitize);
+ if (!json_transferee) {
+ return NULL;
+ }
+ } else {
+ json_transferee = ast_json_null();
+ }
+
+ out = ast_json_pack("{s: s, s: o, s: o, s: o, s: s, s: s, s: s, s: o}",
"type", "BridgeBlindTransfer",
"timestamp", ast_json_timeval(*tv, NULL),
- "channel", json_channel,
- "exten", ast_json_object_get(blob->blob, "exten"),
- "context", ast_json_object_get(blob->blob, "context"),
- "result", result_strs[ast_json_integer_get(ast_json_object_get(blob->blob, "result"))],
- "is_external", ast_json_boolean(ast_json_integer_get(ast_json_object_get(blob->blob, "is_external"))));
+ "transferer", json_transferer,
+ "transferee", json_transferee,
+ "exten", transfer_msg->exten,
+ "context", transfer_msg->context,
+ "result", result_strs[transfer_msg->result],
+ "is_external", ast_json_boolean(transfer_msg->is_external));
if (!out) {
return NULL;
}
- if (blob->bridge) {
- struct ast_json *json_bridge = ast_bridge_snapshot_to_json(blob->bridge, sanitize);
+ if (transfer_msg->to_transferee.bridge_snapshot) {
+ struct ast_json *json_bridge = ast_bridge_snapshot_to_json(
+ transfer_msg->to_transferee.bridge_snapshot, sanitize);
if (!json_bridge || ast_json_object_set(out, "bridge", json_bridge)) {
ast_json_unref(out);
@@ -669,73 +682,96 @@ static struct ast_json *blind_transfer_to_json(struct stasis_message *msg,
static struct ast_manager_event_blob *blind_transfer_to_ami(struct stasis_message *msg)
{
- RAII_VAR(struct ast_str *, channel_state, NULL, ast_free_ptr);
+ RAII_VAR(struct ast_str *, transferer_state, NULL, ast_free_ptr);
RAII_VAR(struct ast_str *, bridge_state, NULL, ast_free_ptr);
- struct ast_bridge_blob *blob = stasis_message_data(msg);
- const char *exten;
- const char *context;
- enum ast_transfer_result result;
- int is_external;
+ RAII_VAR(struct ast_str *, transferee_state, NULL, ast_free_ptr);
+ struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
- if (!blob) {
+ if (!transfer_msg) {
return NULL;
}
- channel_state = ast_manager_build_channel_state_string_prefix(blob->channel, "Transferer");
- if (!channel_state) {
+ transferer_state = ast_manager_build_channel_state_string_prefix(
+ transfer_msg->to_transferee.channel_snapshot, "Transferer");
+ if (!transferer_state) {
return NULL;
}
- if (blob->bridge) {
- bridge_state = ast_manager_build_bridge_state_string(blob->bridge);
+ if (transfer_msg->to_transferee.bridge_snapshot) {
+ bridge_state = ast_manager_build_bridge_state_string(transfer_msg->to_transferee.bridge_snapshot);
if (!bridge_state) {
return NULL;
}
}
- exten = ast_json_string_get(ast_json_object_get(blob->blob, "exten"));
- context = ast_json_string_get(ast_json_object_get(blob->blob, "context"));
- result = ast_json_integer_get(ast_json_object_get(blob->blob, "result"));
- is_external = ast_json_integer_get(ast_json_object_get(blob->blob, "is_external"));
+ if (transfer_msg->transferee) {
+ transferee_state = ast_manager_build_channel_state_string_prefix(
+ transfer_msg->transferee, "Transferee");
+ if (!transferee_state) {
+ return NULL;
+ }
+ }
return ast_manager_event_blob_create(EVENT_FLAG_CALL, "BlindTransfer",
"Result: %s\r\n"
"%s"
"%s"
+ "%s"
"IsExternal: %s\r\n"
"Context: %s\r\n"
"Extension: %s\r\n",
- result_strs[result],
- ast_str_buffer(channel_state),
+ result_strs[transfer_msg->result],
+ ast_str_buffer(transferer_state),
+ transferee_state ? ast_str_buffer(transferee_state) : "",
bridge_state ? ast_str_buffer(bridge_state) : "",
- is_external ? "Yes" : "No",
- context,
- exten);
+ transfer_msg->is_external ? "Yes" : "No",
+ transfer_msg->context,
+ transfer_msg->exten);
+}
+
+static void blind_transfer_dtor(void *obj)
+{
+ struct ast_blind_transfer_message *msg = obj;
+
+ bridge_channel_snapshot_pair_cleanup(&msg->to_transferee);
+ ao2_cleanup(msg->transferee);
}
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_bridge_channel_pair *transferer, const char *context, const char *exten,
+ struct ast_channel *transferee_channel)
{
- RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
- RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+ struct ast_blind_transfer_message *msg;
+ struct stasis_message *stasis;
- json_object = ast_json_pack("{s: s, s: s, s: i, s: i}",
- "context", context, "exten", exten, "result", result, "is_external", is_external);
+ msg = ao2_alloc(sizeof(*msg), blind_transfer_dtor);
+ if (!msg) {
+ return;
+ }
- if (!json_object) {
- ast_log(LOG_NOTICE, "Failed to create json bridge blob\n");
+ if (bridge_channel_snapshot_pair_init(transferer, &msg->to_transferee)) {
+ ao2_cleanup(msg);
return;
}
- msg = ast_bridge_blob_create(ast_blind_transfer_type(),
- transferer->bridge, transferer->channel, json_object);
+ if (transferee_channel) {
+ msg->transferee = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferee_channel));
+ }
+ msg->is_external = is_external;
+ msg->result = result;
+ ast_copy_string(msg->context, context, sizeof(msg->context));
+ ast_copy_string(msg->exten, exten, sizeof(msg->exten));
- if (!msg) {
- ast_log(LOG_NOTICE, "Failed to create blob msg\n");
+ stasis = stasis_message_create(ast_blind_transfer_type(), msg);
+ if (!stasis) {
+ ao2_cleanup(msg);
return;
}
- stasis_publish(ast_bridge_topic_all(), msg);
+ stasis_publish(ast_bridge_topic_all(), stasis);
+
+ ao2_cleanup(stasis);
+ ao2_cleanup(msg);
}
static struct ast_json *attended_transfer_to_json(struct stasis_message *msg,
@@ -743,7 +779,7 @@ static struct ast_json *attended_transfer_to_json(struct stasis_message *msg,
{
struct ast_attended_transfer_message *transfer_msg = stasis_message_data(msg);
RAII_VAR(struct ast_json *, out, NULL, ast_json_unref);
- struct ast_json *json_transferer1, *json_transferer2, *json_bridge, *json_channel;
+ struct ast_json *json_transferer1, *json_transferer2, *json_bridge, *json_channel, *json_transferee, *json_target;
const struct timeval *tv = stasis_message_timestamp(msg);
int res = 0;
@@ -758,11 +794,25 @@ static struct ast_json *attended_transfer_to_json(struct stasis_message *msg,
return NULL;
}
- out = ast_json_pack("{s: s, s: o, s: o, s: o, s: s, s: o}",
+ if (transfer_msg->transferee) {
+ json_transferee = ast_channel_snapshot_to_json(transfer_msg->transferee, sanitize);
+ } else {
+ json_transferee = ast_json_null();
+ }
+
+ if (transfer_msg->target) {
+ json_target = ast_channel_snapshot_to_json(transfer_msg->target, sanitize);
+ } else {
+ json_target = ast_json_null();
+ }
+
+ out = ast_json_pack("{s: s, s: o, s: o, s: o, s: o, s: o, s: s, s: o}",
"type", "BridgeAttendedTransfer",
"timestamp", ast_json_timeval(*tv, NULL),
"transferer_first_leg", json_transferer1,
"transferer_second_leg", json_transferer2,
+ "transferee", json_transferee,
+ "transfer_target", json_target,
"result", result_strs[transfer_msg->result],
"is_external", ast_json_boolean(transfer_msg->is_external));
if (!out) {
@@ -794,6 +844,9 @@ static struct ast_json *attended_transfer_to_json(struct stasis_message *msg,
res |= ast_json_object_set(out, "destination_type", ast_json_string_create("bridge"));
res |= ast_json_object_set(out, "destination_bridge", ast_json_string_create(transfer_msg->dest.bridge));
break;
+ case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
+ res |= ast_json_object_set(out, "replace_channel", ast_channel_snapshot_to_json(transfer_msg->replace_channel, sanitize));
+ /* fallthrough */
case AST_ATTENDED_TRANSFER_DEST_APP:
res |= ast_json_object_set(out, "destination_type", ast_json_string_create("application"));
res |= ast_json_object_set(out, "destination_application", ast_json_string_create(transfer_msg->dest.app));
@@ -851,6 +904,8 @@ static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_mes
RAII_VAR(struct ast_str *, bridge2_state, NULL, ast_free_ptr);
RAII_VAR(struct ast_str *, local1_state, NULL, ast_free_ptr);
RAII_VAR(struct ast_str *, local2_state, NULL, ast_free_ptr);
+ RAII_VAR(struct ast_str *, transferee_state, NULL, ast_free_ptr);
+ RAII_VAR(struct ast_str *, target_state, NULL, ast_free_ptr);
struct ast_attended_transfer_message *transfer_msg = stasis_message_data(msg);
if (!variable_data) {
@@ -862,6 +917,19 @@ static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_mes
if (!transferer1_state || !transferer2_state) {
return NULL;
}
+ if (transfer_msg->transferee) {
+ transferee_state = ast_manager_build_channel_state_string_prefix(transfer_msg->transferee, "Transferee");
+ if (!transferee_state) {
+ return NULL;
+ }
+ }
+
+ if (transfer_msg->target) {
+ target_state = ast_manager_build_channel_state_string_prefix(transfer_msg->target, "TransferTarget");
+ if (!target_state) {
+ return NULL;
+ }
+ }
if (transfer_msg->to_transferee.bridge_snapshot) {
bridge1_state = ast_manager_build_bridge_state_string_prefix(
@@ -885,6 +953,7 @@ static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_mes
ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.bridge);
break;
case AST_ATTENDED_TRANSFER_DEST_APP:
+ case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
ast_str_append(&variable_data, 0, "DestType: App\r\n");
ast_str_append(&variable_data, 0, "DestApp: %s\r\n", transfer_msg->dest.app);
break;
@@ -914,6 +983,8 @@ static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_mes
"%s"
"%s"
"%s"
+ "%s"
+ "%s"
"IsExternal: %s\r\n"
"%s",
result_strs[transfer_msg->result],
@@ -921,6 +992,8 @@ static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_mes
bridge1_state ? ast_str_buffer(bridge1_state) : "",
ast_str_buffer(transferer2_state),
bridge2_state ? ast_str_buffer(bridge2_state) : "",
+ transferee_state ? ast_str_buffer(transferee_state) : "",
+ target_state ? ast_str_buffer(target_state) : "",
transfer_msg->is_external ? "Yes" : "No",
ast_str_buffer(variable_data));
}
@@ -932,6 +1005,9 @@ static void attended_transfer_dtor(void *obj)
bridge_channel_snapshot_pair_cleanup(&msg->to_transferee);
bridge_channel_snapshot_pair_cleanup(&msg->to_transfer_target);
+ ao2_cleanup(msg->replace_channel);
+ ao2_cleanup(msg->transferee);
+ ao2_cleanup(msg->target);
if (msg->dest_type != AST_ATTENDED_TRANSFER_DEST_LINK) {
return;
@@ -942,8 +1018,10 @@ static void attended_transfer_dtor(void *obj)
}
}
-static struct ast_attended_transfer_message *attended_transfer_message_create(int is_external, enum ast_transfer_result result,
- struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target)
+static struct ast_attended_transfer_message *attended_transfer_message_create(int is_external,
+ enum ast_transfer_result result, struct ast_bridge_channel_pair *transferee,
+ struct ast_bridge_channel_pair *target, struct ast_channel *replace_channel,
+ struct ast_channel *transferee_channel, struct ast_channel *target_channel)
{
RAII_VAR(struct ast_attended_transfer_message *, msg, NULL, ao2_cleanup);
@@ -957,6 +1035,19 @@ static struct ast_attended_transfer_message *attended_transfer_message_create(in
return NULL;
}
+ if (replace_channel) {
+ msg->replace_channel = ast_channel_snapshot_get_latest(ast_channel_uniqueid(replace_channel));
+ if (!msg->replace_channel) {
+ return NULL;
+ }
+ }
+
+ if (transferee_channel) {
+ msg->transferee = ast_channel_snapshot_get_latest(ast_channel_uniqueid(transferee_channel));
+ }
+ if (target_channel) {
+ msg->target = ast_channel_snapshot_get_latest(ast_channel_uniqueid(target_channel));
+ }
msg->is_external = is_external;
msg->result = result;
@@ -965,7 +1056,8 @@ static struct ast_attended_transfer_message *attended_transfer_message_create(in
}
void ast_bridge_publish_attended_transfer_fail(int is_external, enum ast_transfer_result result,
- struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target)
+ struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
+ struct ast_channel *transferee_channel, struct ast_channel *target_channel)
{
RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
@@ -974,7 +1066,8 @@ void ast_bridge_publish_attended_transfer_fail(int is_external, enum ast_transfe
return;
}
- transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
+ transfer_msg = attended_transfer_message_create(is_external, result,
+ transferee, target, NULL, transferee_channel, target_channel);
if (!transfer_msg) {
return;
}
@@ -991,7 +1084,8 @@ void ast_bridge_publish_attended_transfer_fail(int is_external, enum ast_transfe
void ast_bridge_publish_attended_transfer_bridge_merge(int is_external, enum ast_transfer_result result,
struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
- struct ast_bridge *final_bridge)
+ struct ast_bridge *final_bridge, struct ast_channel *transferee_channel,
+ struct ast_channel *target_channel)
{
RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
@@ -1000,7 +1094,8 @@ void ast_bridge_publish_attended_transfer_bridge_merge(int is_external, enum ast
return;
}
- transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
+ transfer_msg = attended_transfer_message_create(is_external, result,
+ transferee, target, NULL, transferee_channel, target_channel);
if (!transfer_msg) {
return;
}
@@ -1019,7 +1114,8 @@ void ast_bridge_publish_attended_transfer_bridge_merge(int is_external, enum ast
void ast_bridge_publish_attended_transfer_threeway(int is_external, enum ast_transfer_result result,
struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
- struct ast_bridge_channel_pair *final_pair)
+ struct ast_bridge_channel_pair *final_pair, struct ast_channel *transferee_channel,
+ struct ast_channel *target_channel)
{
RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
@@ -1028,7 +1124,8 @@ void ast_bridge_publish_attended_transfer_threeway(int is_external, enum ast_tra
return;
}
- transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
+ transfer_msg = attended_transfer_message_create(is_external, result,
+ transferee, target, NULL, transferee_channel, target_channel);
if (!transfer_msg) {
return;
}
@@ -1056,7 +1153,8 @@ void ast_bridge_publish_attended_transfer_threeway(int is_external, enum ast_tra
void ast_bridge_publish_attended_transfer_app(int is_external, enum ast_transfer_result result,
struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
- const char *dest_app)
+ struct ast_channel *replace_channel, const char *dest_app,
+ struct ast_channel *transferee_channel, struct ast_channel *target_channel)
{
RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
@@ -1065,12 +1163,13 @@ void ast_bridge_publish_attended_transfer_app(int is_external, enum ast_transfer
return;
}
- transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
+ transfer_msg = attended_transfer_message_create(is_external, result,
+ transferee, target, replace_channel, transferee_channel, target_channel);
if (!transfer_msg) {
return;
}
- transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_APP;
+ transfer_msg->dest_type = replace_channel ? AST_ATTENDED_TRANSFER_DEST_LOCAL_APP : AST_ATTENDED_TRANSFER_DEST_APP;
ast_copy_string(transfer_msg->dest.app, dest_app, sizeof(transfer_msg->dest.app));
msg = stasis_message_create(ast_attended_transfer_type(), transfer_msg);
@@ -1083,7 +1182,8 @@ void ast_bridge_publish_attended_transfer_app(int is_external, enum ast_transfer
void ast_bridge_publish_attended_transfer_link(int is_external, enum ast_transfer_result result,
struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
- struct ast_channel *locals[2])
+ struct ast_channel *locals[2], struct ast_channel *transferee_channel,
+ struct ast_channel *target_channel)
{
RAII_VAR(struct ast_attended_transfer_message *, transfer_msg, NULL, ao2_cleanup);
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
@@ -1093,7 +1193,8 @@ void ast_bridge_publish_attended_transfer_link(int is_external, enum ast_transfe
return;
}
- transfer_msg = attended_transfer_message_create(is_external, result, transferee, target);
+ transfer_msg = attended_transfer_message_create(is_external, result,
+ transferee, target, NULL, transferee_channel, target_channel);
if (!transfer_msg) {
return;
}