summaryrefslogtreecommitdiff
path: root/channels/chan_mgcp.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2013-05-21 18:00:22 +0000
committerRichard Mudgett <rmudgett@digium.com>2013-05-21 18:00:22 +0000
commit3d63833bd6c869b7efa383e8dea14be1a6eff998 (patch)
tree34957dd051b8f67c7cc58a510e24ee3873a61ad4 /channels/chan_mgcp.c
parente1e1cc2deefb92f8b43825f1f34e619354737842 (diff)
Merge in the bridge_construction branch to make the system use the Bridging API.
Breaks many things until they can be reworked. A partial list: chan_agent chan_dahdi, chan_misdn, chan_iax2 native bridging app_queue COLP updates DTMF attended transfers Protocol attended transfers git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@389378 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/chan_mgcp.c')
-rw-r--r--channels/chan_mgcp.c102
1 files changed, 48 insertions, 54 deletions
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index e254823bb..1f0830762 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -83,6 +83,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#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
@@ -480,7 +481,6 @@ static struct ast_channel_tech mgcp_tech = {
.fixup = mgcp_fixup,
.send_digit_begin = mgcp_senddigit_begin,
.send_digit_end = mgcp_senddigit_end,
- .bridge = ast_rtp_instance_bridge,
.func_channel_read = acf_channel_read,
};
@@ -3213,56 +3213,55 @@ static void *mgcp_ss(void *data)
return NULL;
}
-static int attempt_transfer(struct mgcp_endpoint *p)
+/*! \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)
{
- /* *************************
- * 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;
+ 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);
}
- /*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 */
+ 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;
}
@@ -3511,13 +3510,8 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
/* 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;