[asterisk-commits] rmudgett: branch rmudgett/ect r247361 - /team/rmudgett/ect/channels/sig_pri.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Feb 17 16:22:32 CST 2010
Author: rmudgett
Date: Wed Feb 17 16:22:29 2010
New Revision: 247361
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=247361
Log:
Now we actually handle the new PRI_SUBCMD_TRANSFER_CALL instead of punting.
Modified:
team/rmudgett/ect/channels/sig_pri.c
Modified: team/rmudgett/ect/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/ect/channels/sig_pri.c?view=diff&rev=247361&r1=247360&r2=247361
==============================================================================
--- team/rmudgett/ect/channels/sig_pri.c (original)
+++ team/rmudgett/ect/channels/sig_pri.c Wed Feb 17 16:22:29 2010
@@ -1478,6 +1478,103 @@
/*!
* \internal
+ * \brief Attempt to transfer the two calls to each other.
+ * \since 1.8
+ *
+ * \param pri sig_pri PRI control structure.
+ * \param call_1 First call involved in the transfer.
+ * \param call_2 Second call involved in the transfer.
+ * \param call_1_held TRUE if call_1 is on hold.
+ * \param call_2_held TRUE if call_2 is on hold.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int sig_pri_attempt_transfer(struct sig_pri_pri *pri, q931_call *call_1, q931_call *call_2, int call_1_held, int call_2_held)
+{
+ int retval;
+ int call_1_chanpos;
+ int call_2_chanpos;
+ struct ast_channel *call_1_ast;
+ struct ast_channel *call_2_ast;
+ struct ast_channel *bridged;
+
+ call_1_chanpos = pri_find_pri_call(pri, call_1);
+ call_2_chanpos = pri_find_pri_call(pri, call_2);
+ if (call_1_chanpos < 0 || call_2_chanpos < 0) {
+ return -1;
+ }
+
+ sig_pri_lock_private(pri->pvts[call_1_chanpos]);
+ sig_pri_lock_private(pri->pvts[call_2_chanpos]);
+ sig_pri_lock_owner(pri, call_1_chanpos);
+ sig_pri_lock_owner(pri, call_2_chanpos);
+
+ call_1_ast = pri->pvts[call_1_chanpos]->owner;
+ call_2_ast = pri->pvts[call_2_chanpos]->owner;
+ if (!call_1_ast || !call_2_ast) {
+ if (call_1_ast) {
+ ast_channel_unlock(call_1_ast);
+ }
+ if (call_2_ast) {
+ ast_channel_unlock(call_2_ast);
+ }
+ sig_pri_unlock_private(pri->pvts[call_1_chanpos]);
+ sig_pri_unlock_private(pri->pvts[call_2_chanpos]);
+ return -1;
+ }
+
+ bridged = ast_bridged_channel(call_2_ast);
+ if (bridged) {
+ if (call_1_held) {
+ ast_queue_control(call_1_ast, AST_CONTROL_UNHOLD);
+ }
+ if (call_2_held) {
+ ast_queue_control(call_2_ast, AST_CONTROL_UNHOLD);
+ }
+
+ ast_verb(3, "TRANSFERRING %s to %s\n", call_2_ast->name, call_1_ast->name);
+ retval = ast_channel_masquerade(call_1_ast, bridged);
+ } else {
+ /* Try masquerading the other way. */
+ bridged = ast_bridged_channel(call_1_ast);
+ if (bridged) {
+ if (call_1_held) {
+ ast_queue_control(call_1_ast, AST_CONTROL_UNHOLD);
+ }
+ if (call_2_held) {
+ ast_queue_control(call_2_ast, AST_CONTROL_UNHOLD);
+ }
+
+ ast_verb(3, "TRANSFERRING %s to %s\n", call_1_ast->name, call_2_ast->name);
+ retval = ast_channel_masquerade(call_2_ast, bridged);
+ } else {
+ /* Could not transfer. */
+ retval = -1;
+ }
+ }
+ if (bridged && retval) {
+ /* Restore HOLD on held calls because masquerade failed. */
+ if (call_1_held) {
+ ast_queue_control(call_1_ast, AST_CONTROL_HOLD);
+ }
+ if (call_2_held) {
+ ast_queue_control(call_2_ast, AST_CONTROL_HOLD);
+ }
+ }
+
+ ast_channel_unlock(call_1_ast);
+ ast_channel_unlock(call_2_ast);
+ sig_pri_unlock_private(pri->pvts[call_1_chanpos]);
+ sig_pri_unlock_private(pri->pvts[call_2_chanpos]);
+
+ return retval;
+}
+
+/*!
+ * \internal
* \brief Handle the call associated PRI subcommand events.
* \since 1.8
*
@@ -1649,8 +1746,19 @@
#endif /* defined(HAVE_PRI_CALL_REROUTING) */
#if defined(HAVE_PRI_TRANSFER)
case PRI_SUBCMD_TRANSFER_CALL:
- /* BUGBUG transfer call. */
- pri_transfer_rsp(pri->pri, call_rsp, subcmd->u.transfer.invoke_id, 0);
+ if (!call_rsp) {
+ /* Should never happen. */
+ ast_log(LOG_ERROR,
+ "Call transfer subcommand without call to send response!\n");
+ break;
+ }
+
+ sig_pri_unlock_private(pri->pvts[chanpos]);
+ pri_transfer_rsp(pri->pri, call_rsp, subcmd->u.transfer.invoke_id,
+ sig_pri_attempt_transfer(pri, subcmd->u.transfer.call_1,
+ subcmd->u.transfer.call_2, subcmd->u.transfer.is_call_1_held,
+ subcmd->u.transfer.is_call_2_held) ? 1 : 0);
+ sig_pri_lock_private(pri->pvts[chanpos]);
break;
#endif /* defined(HAVE_PRI_TRANSFER) */
default:
@@ -1666,7 +1774,7 @@
#if defined(HAVE_PRI_CALL_HOLD)
/*!
* \internal
- * \brief Attempt to transfer the active call to the held call.
+ * \brief Attempt to transfer the active call to the held call on disconnect.
* \since 1.8
*
* \param pri sig_pri PRI control structure.
@@ -1678,60 +1786,9 @@
* \retval 0 on success.
* \retval -1 on error.
*/
-static int sig_pri_attempt_transfer(struct sig_pri_pri *pri, q931_call *active_call, q931_call *held_call)
-{
- int retval;
- int active_chanpos;
- int held_chanpos;
- struct ast_channel *active_ast;
- struct ast_channel *held_ast;
- struct ast_channel *bridged;
-
- active_chanpos = pri_find_pri_call(pri, active_call);
- held_chanpos = pri_find_pri_call(pri, held_call);
- if (active_chanpos < 0 || held_chanpos < 0) {
- return -1;
- }
-
- sig_pri_lock_private(pri->pvts[active_chanpos]);
- sig_pri_lock_private(pri->pvts[held_chanpos]);
- sig_pri_lock_owner(pri, active_chanpos);
- sig_pri_lock_owner(pri, held_chanpos);
-
- active_ast = pri->pvts[active_chanpos]->owner;
- held_ast = pri->pvts[held_chanpos]->owner;
- if (!active_ast || !held_ast) {
- if (active_ast) {
- ast_channel_unlock(active_ast);
- }
- if (held_ast) {
- ast_channel_unlock(held_ast);
- }
- sig_pri_unlock_private(pri->pvts[active_chanpos]);
- sig_pri_unlock_private(pri->pvts[held_chanpos]);
- return -1;
- }
-
- bridged = ast_bridged_channel(held_ast);
- if (bridged) {
- ast_queue_control(held_ast, AST_CONTROL_UNHOLD);
-
- ast_verb(3, "TRANSFERRING %s to %s\n", held_ast->name, active_ast->name);
- retval = ast_channel_masquerade(active_ast, bridged);
- } else {
- /*
- * Could not transfer. Held channel is not bridged anymore.
- * Held party probably got tired of waiting and hung up.
- */
- retval = -1;
- }
-
- ast_channel_unlock(active_ast);
- ast_channel_unlock(held_ast);
- sig_pri_unlock_private(pri->pvts[active_chanpos]);
- sig_pri_unlock_private(pri->pvts[held_chanpos]);
-
- return retval;
+static int sig_pri_attempt_disconnect_transfer(struct sig_pri_pri *pri, q931_call *active_call, q931_call *held_call)
+{
+ return sig_pri_attempt_transfer(pri, active_call, held_call, 0, 1);
}
#endif /* defined(HAVE_PRI_CALL_HOLD) */
@@ -2928,7 +2985,7 @@
&& pri->hold_disconnect_transfer) {
/* We are to transfer the call instead of simply hanging up. */
sig_pri_unlock_private(pri->pvts[chanpos]);
- if (!sig_pri_attempt_transfer(pri, e->hangup.call_active,
+ if (!sig_pri_attempt_disconnect_transfer(pri, e->hangup.call_active,
e->hangup.call_held)) {
break;
}
More information about the asterisk-commits
mailing list