[Asterisk-code-review] app_confbridge: Attended transfer event fixup (...asterisk[certified/13.21])
George Joseph
asteriskteam at digium.com
Tue Jun 11 14:39:16 CDT 2019
George Joseph has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/11455
Change subject: app_confbridge: Attended transfer event fixup
......................................................................
app_confbridge: Attended transfer event fixup
When a channel already in a conference bridge is attended transfered
to another extension, or when an exysting call is attended
transferred into a conference bridge, we now generate ConfbridgeJoin
and ConfbridgeLeave events for the entering and departing channels.
Change-Id: Id7709cfbceb26fbcb828b2d0d2a6b2fbeaf028e1
---
M apps/app_confbridge.c
M apps/confbridge/confbridge_manager.c
M apps/confbridge/include/confbridge.h
M main/cdr.c
4 files changed, 154 insertions(+), 2 deletions(-)
git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/55/11455/1
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index df93215..888a25f 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -1459,6 +1459,122 @@
return 0;
}
+void confbridge_handle_atxfer(struct ast_attended_transfer_message *msg)
+{
+ struct ast_channel_snapshot *old_snapshot;
+ struct ast_channel_snapshot *new_snapshot;
+ char *confbr_name = NULL;
+ char *comma;
+ struct confbridge_conference *conference = NULL;
+ struct confbridge_user *user = NULL;
+ struct confbridge_user temp_user = { 0, };
+ struct ast_channel *new_chan = NULL;
+ struct ast_channel *old_chan = NULL;
+ struct user_profile u_profile;
+
+ if (msg->to_transferee.channel_snapshot
+ && strcmp(msg->to_transferee.channel_snapshot->appl, "ConfBridge") == 0) {
+ /* We're transferring a bridge to an extension */
+ old_snapshot = msg->to_transferee.channel_snapshot;
+ new_snapshot = msg->target;
+ } else if (msg->to_transfer_target.channel_snapshot
+ && strcmp(msg->to_transfer_target.channel_snapshot->appl, "ConfBridge") == 0) {
+ /* We're transferring a call to a bridge */
+ old_snapshot = msg->to_transfer_target.channel_snapshot;
+ new_snapshot = msg->transferee;
+ } else {
+ ast_log(LOG_ERROR, "Could not determine proper channels\n");
+ return;
+ }
+
+ /*
+ * old_snapshot->data should have the original parameters passed to
+ * the ConfBridge app:
+ * conference[,bridge_profile[,user_profile[,menu]]]
+ * We'll use "conference" to look up the bridge.
+ *
+ * We _could_ use old_snapshot->bridgeid to get the bridge but
+ * that would involve locking the conference_bridges container
+ * and iterating over it looking for a matching bridge.
+ */
+ if (ast_strlen_zero(old_snapshot->data)) {
+ ast_log(LOG_ERROR, "Channel '%s' didn't have app data set\n", old_snapshot->name);
+ return;
+ }
+ confbr_name = ast_strdupa(old_snapshot->data);
+ comma = strchr(confbr_name, ',');
+ if (comma) {
+ *comma = '\0';
+ }
+
+ ast_debug(1, "Confbr: %s Leaving: %s Joining: %s\n", confbr_name, old_snapshot->name, new_snapshot->name);
+
+ conference = ao2_find(conference_bridges, confbr_name, OBJ_SEARCH_KEY);
+ if (!conference) {
+ ast_log(LOG_ERROR, "Conference bridge '%s' not found\n", confbr_name);
+ return;
+ }
+ ao2_lock(conference);
+
+ AST_LIST_TRAVERSE(&conference->active_list, user, list) {
+ if (strcasecmp(ast_channel_name(user->chan), old_snapshot->name) == 0) {
+ old_chan = user->chan;
+ u_profile = user->u_profile;
+ break;
+ }
+ }
+
+ if (!old_chan && conference->waitingusers) {
+ AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
+ if (strcasecmp(ast_channel_name(user->chan), old_snapshot->name) == 0) {
+ old_chan = user->chan;
+ u_profile = user->u_profile;
+ break;
+ }
+ }
+ }
+
+ if (!old_chan) {
+ ast_log(LOG_ERROR, "Channel '%s' left before it could be replaced in bridge '%s'\n",
+ old_snapshot->name, confbr_name);
+ ao2_unlock(conference);
+ ao2_ref(conference, -1);
+ return;
+ }
+ ast_channel_ref(old_chan);
+
+ new_chan = ast_channel_get_by_name(new_snapshot->name);
+ if (!new_chan) {
+ ast_log(LOG_ERROR, "Channel '%s' left before it could be joined to bridge '%s'\n",
+ new_snapshot->name, confbr_name);
+ ast_channel_cleanup(old_chan);
+ ao2_unlock(conference);
+ ao2_ref(conference, -1);
+ return;
+ }
+
+ ast_debug(1, "Old chan: %p %s New chan: %p %s\n", old_chan, ast_channel_name(old_chan),
+ new_chan, ast_channel_name(new_chan));
+
+ /*
+ * We're going to use the existing user profile to create the messages.
+ * It and the channel are the only things in the user structure that
+ * are used by the send event functions.
+ */
+ temp_user.u_profile = u_profile;
+
+ temp_user.chan = old_chan;
+ send_leave_event(&temp_user, conference);
+ ast_channel_cleanup(old_chan);
+
+ temp_user.chan = new_chan;
+ send_join_event(&temp_user, conference);
+ ast_channel_cleanup(new_chan);
+
+ ao2_unlock(conference);
+ ao2_ref(conference, -1);
+}
+
/*!
* \brief Join a conference bridge
*
diff --git a/apps/confbridge/confbridge_manager.c b/apps/confbridge/confbridge_manager.c
index 9ac0d55..c6ae0af 100644
--- a/apps/confbridge/confbridge_manager.c
+++ b/apps/confbridge/confbridge_manager.c
@@ -325,6 +325,26 @@
ast_free(extra_text);
}
+static void confbridge_atxfer_cb(void *data, struct stasis_subscription *sub,
+ struct stasis_message *message)
+{
+ struct ast_attended_transfer_message *msg = stasis_message_data(message);
+
+ if (msg->result != AST_BRIDGE_TRANSFER_SUCCESS) {
+ return;
+ }
+
+ /*
+ * This callback will get called for ALL attended transfers
+ * so we need to make sure this transfer belongs to
+ * a conference bridge before trying to handle it.
+ */
+ if (msg->dest_type == AST_ATTENDED_TRANSFER_DEST_APP
+ && strcmp(msg->dest.app, "ConfBridge") == 0) {
+ confbridge_handle_atxfer(msg);
+ }
+}
+
static void confbridge_start_record_cb(void *data, struct stasis_subscription *sub,
struct stasis_message *message)
{
@@ -452,6 +472,13 @@
return -1;
}
if (stasis_message_router_add(bridge_state_router,
+ ast_attended_transfer_type(),
+ confbridge_atxfer_cb,
+ NULL)) {
+ manager_confbridge_shutdown();
+ return -1;
+ }
+ if (stasis_message_router_add(bridge_state_router,
confbridge_leave_type(),
confbridge_leave_cb,
NULL)) {
diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h
index e59400c..9bedfc0 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -28,6 +28,7 @@
#include "asterisk/channel.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_features.h"
+#include "asterisk/stasis_bridges.h"
#include "conf_state.h"
/* Maximum length of a conference bridge name */
@@ -650,4 +651,14 @@
* \retval -1 on error.
*/
int conf_announce_channel_push(struct ast_channel *ast);
+
+/*!
+ * \brief Create join/leave events for attended transfers
+ * \since 13.28.0
+ *
+ * \param msg The attended transfer stasis message
+ *
+ */
+void confbridge_handle_atxfer(struct ast_attended_transfer_message *msg);
+
#endif
diff --git a/main/cdr.c b/main/cdr.c
index 496fb36..644ebdd 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -1593,14 +1593,12 @@
static int base_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
{
/* In general, most things shouldn't get a bridge leave */
- ast_assert(0);
return 1;
}
static int base_process_dial_end(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const char *dial_status)
{
/* In general, most things shouldn't get a dial end. */
- ast_assert(0);
return 0;
}
--
To view, visit https://gerrit.asterisk.org/c/asterisk/+/11455
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings
Gerrit-Project: asterisk
Gerrit-Branch: certified/13.21
Gerrit-Change-Id: Id7709cfbceb26fbcb828b2d0d2a6b2fbeaf028e1
Gerrit-Change-Number: 11455
Gerrit-PatchSet: 1
Gerrit-Owner: George Joseph <gjoseph at digium.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20190611/f638391a/attachment-0001.html>
More information about the asterisk-code-review
mailing list