[asterisk-commits] file: branch group/bridge_construction r389073 - /team/group/bridge_construct...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sat May 18 15:24:22 CDT 2013
Author: file
Date: Sat May 18 15:24:17 2013
New Revision: 389073
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=389073
Log:
Migrate chan_mgcp over to using the new attended transfer API.
(closes issue ASTERISK-21525)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2536/
Modified:
team/group/bridge_construction/channels/chan_mgcp.c
Modified: team/group/bridge_construction/channels/chan_mgcp.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/channels/chan_mgcp.c?view=diff&rev=389073&r1=389072&r2=389073
==============================================================================
--- team/group/bridge_construction/channels/chan_mgcp.c (original)
+++ team/group/bridge_construction/channels/chan_mgcp.c Sat May 18 15:24:17 2013
@@ -83,6 +83,7 @@
#include "asterisk/chanvars.h"
#include "asterisk/pktccops.h"
#include "asterisk/stasis.h"
+#include "asterisk/bridging.h"
/*
* Define to work around buggy dlink MGCP phone firmware which
@@ -3212,56 +3213,55 @@
return NULL;
}
-static int attempt_transfer(struct mgcp_endpoint *p)
-{
- /* *************************
- * I hope this works.
- * Copied out of chan_zap
- * Cross your fingers
- * *************************/
-
- /* In order to transfer, we need at least one of the channels to
- actually be in a call bridge. We can't conference two applications
- together (but then, why would we want to?) */
- if (ast_bridged_channel(p->sub->owner)) {
- /* The three-way person we're about to transfer to could still be in MOH, so
- stop it now */
- ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
- if (ast_channel_state(p->sub->owner) == AST_STATE_RINGING) {
- ast_queue_control(p->sub->next->owner, AST_CONTROL_RINGING);
- }
- if (ast_channel_masquerade(p->sub->next->owner, ast_bridged_channel(p->sub->owner))) {
- ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
- ast_channel_name(ast_bridged_channel(p->sub->owner)), ast_channel_name(p->sub->next->owner));
- return -1;
- }
- /* Orphan the channel */
- unalloc_sub(p->sub->next);
- } else if (ast_bridged_channel(p->sub->next->owner)) {
- if (ast_channel_state(p->sub->owner) == AST_STATE_RINGING) {
- ast_queue_control(p->sub->next->owner, AST_CONTROL_RINGING);
- }
- ast_queue_control(p->sub->next->owner, AST_CONTROL_UNHOLD);
- if (ast_channel_masquerade(p->sub->owner, ast_bridged_channel(p->sub->next->owner))) {
- ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
- ast_channel_name(ast_bridged_channel(p->sub->next->owner)), ast_channel_name(p->sub->owner));
- return -1;
- }
- /*swap_subs(p, SUB_THREEWAY, SUB_REAL);*/
- ast_verb(3, "Swapping %d for %d on %s@%s\n", p->sub->id, p->sub->next->id, p->name, p->parent->name);
- p->sub = p->sub->next;
- unalloc_sub(p->sub->next);
- /* Tell the caller not to hangup */
+/*! \brief Complete an attended transfer
+ *
+ * \param p The endpoint performing the attended transfer
+ * \param sub The sub-channel completing the attended transfer
+ *
+ * \note p->sub is the currently active sub-channel (the channel the phone is using)
+ * \note p->sub->next is the sub-channel not in use, potentially on hold
+ *
+ * \retval 0 when channel should be hung up
+ * \retval 1 when channel should not be hung up
+ */
+static int attempt_transfer(struct mgcp_endpoint *p, struct mgcp_subchannel *sub)
+{
+ enum ast_transfer_result res;
+
+ /* Ensure that the other channel goes off hold and that it is indicating properly */
+ ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD);
+ if (ast_channel_state(sub->owner) == AST_STATE_RINGING) {
+ ast_queue_control(sub->next->owner, AST_CONTROL_RINGING);
+ }
+
+ ast_mutex_unlock(&p->sub->next->lock);
+ ast_mutex_unlock(&p->sub->lock);
+ res = ast_bridge_transfer_attended(sub->owner, sub->next->owner, NULL);
+
+ /* Subs are only freed when the endpoint itself is destroyed, so they will continue to exist
+ * after ast_bridge_transfer_attended returns making this safe without reference counting
+ */
+ ast_mutex_lock(&p->sub->lock);
+ ast_mutex_lock(&p->sub->next->lock);
+
+ if (res != AST_BRIDGE_TRANSFER_SUCCESS) {
+ /* If transferring fails hang up the other channel if present and us */
+ if (sub->next->owner) {
+ ast_channel_softhangup_internal_flag_add(sub->next->owner, AST_SOFTHANGUP_DEV);
+ mgcp_queue_hangup(sub->next);
+ }
+ sub->next->alreadygone = 1;
+ return 0;
+ }
+
+ unalloc_sub(sub->next);
+
+ /* If the active sub is NOT the one completing the transfer change it to be, and hang up the other sub */
+ if (p->sub != sub) {
+ p->sub = sub;
return 1;
- } else {
- ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
- ast_channel_name(p->sub->owner), ast_channel_name(p->sub->next->owner));
- ast_channel_softhangup_internal_flag_add(p->sub->next->owner, AST_SOFTHANGUP_DEV);
- if (p->sub->next->owner) {
- p->sub->next->alreadygone = 1;
- mgcp_queue_hangup(p->sub->next);
- }
- }
+ }
+
return 0;
}
@@ -3510,13 +3510,8 @@
/* We're allowed to transfer, we have two avtive calls and */
/* we made at least one of the calls. Let's try and transfer */
ast_mutex_lock(&p->sub->next->lock);
- res = attempt_transfer(p);
- if (res < 0) {
- if (p->sub->next->owner) {
- sub->next->alreadygone = 1;
- mgcp_queue_hangup(sub->next);
- }
- } else if (res) {
+ res = attempt_transfer(p, sub);
+ if (res) {
ast_log(LOG_WARNING, "Transfer attempt failed\n");
ast_mutex_unlock(&p->sub->next->lock);
return -1;
More information about the asterisk-commits
mailing list