[asterisk-commits] russell: branch russell/chan_refcount r100143 - /team/russell/chan_refcount/m...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Jan 24 11:13:42 CST 2008
Author: russell
Date: Thu Jan 24 11:13:41 2008
New Revision: 100143
URL: http://svn.digium.com/view/asterisk?view=rev&rev=100143
Log:
Apply my res_features changes to features.c
Modified:
team/russell/chan_refcount/main/features.c
Change Statistics:
0 files changed
Modified: team/russell/chan_refcount/main/features.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/main/features.c?view=diff&rev=100143&r1=100142&r2=100143
==============================================================================
--- team/russell/chan_refcount/main/features.c (original)
+++ team/russell/chan_refcount/main/features.c Thu Jan 24 11:13:41 2008
@@ -2917,6 +2917,8 @@
*/
static void do_bridge_masquerade(struct ast_channel *chan, struct ast_channel *tmpchan)
{
+ ast_channel_lock_both(chan, tmpchan);
+
ast_moh_stop(chan);
ast_channel_lock(chan);
ast_setstate(tmpchan, chan->_state);
@@ -2927,8 +2929,9 @@
ast_do_masquerade(tmpchan);
/* when returning from bridge, the channel will continue at the next priority */
ast_explicit_goto(tmpchan, chan->context, chan->exten, chan->priority + 1);
+
+ ast_channel_unlock(chan);
ast_channel_unlock(tmpchan);
- ast_channel_unlock(chan);
}
/*!
@@ -2953,52 +2956,55 @@
struct ast_channel *chana = NULL, *chanb = NULL;
struct ast_channel *tmpchana = NULL, *tmpchanb = NULL;
struct ast_bridge_thread_obj *tobj = NULL;
+ const char *err_msg = NULL;
+ int res = 0;
/* make sure valid channels were specified */
- if (!ast_strlen_zero(channela) && !ast_strlen_zero(channelb)) {
- chana = ast_get_channel_by_name_prefix_locked(channela, strlen(channela));
- chanb = ast_get_channel_by_name_prefix_locked(channelb, strlen(channelb));
- if (chana)
- ast_channel_unlock(chana);
- if (chanb)
- ast_channel_unlock(chanb);
-
- /* send errors if any of the channels could not be found/locked */
- if (!chana) {
- char buf[256];
- snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
- astman_send_error(s, m, buf);
- return 0;
- }
- if (!chanb) {
- char buf[256];
- snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
- astman_send_error(s, m, buf);
- return 0;
- }
- } else {
+ if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
astman_send_error(s, m, "Missing channel parameter in request");
return 0;
}
- /* Answer the channels if needed */
+ if (!(chana = ast_channel_get_by_name_prefix(channela, strlen(channela)))) {
+ char buf[256];
+
+ snprintf(buf, sizeof(buf), "Channel1 does not exists: %s", channela);
+ astman_send_error(s, m, buf);
+
+ return 0;
+ }
+
+ if (!(chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb)))) {
+ char buf[256];
+
+ ast_channel_unref(chana);
+
+ snprintf(buf, sizeof(buf), "Channel2 does not exists: %s", channelb);
+ astman_send_error(s, m, buf);
+
+ return 0;
+ }
+
if (chana->_state != AST_STATE_UP)
ast_answer(chana);
+
if (chanb->_state != AST_STATE_UP)
ast_answer(chanb);
/* create the placeholder channels and grab the other channels */
if (!(tmpchana = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
NULL, NULL, 0, "Bridge/%s", chana->name))) {
- astman_send_error(s, m, "Unable to create temporary channel!");
- return 1;
+ err_msg = "Unable to create temporary channel!";
+ res = 1;
+ goto return_cleanup;
}
if (!(tmpchanb = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
NULL, NULL, 0, "Bridge/%s", chanb->name))) {
- astman_send_error(s, m, "Unable to create temporary channels!");
- ast_channel_free(tmpchana);
- return 1;
+ err_msg = "Unable to create temporary channel!";
+ tmpchana = ast_channel_release(tmpchana);
+ res = 1;
+ goto return_cleanup;
}
do_bridge_masquerade(chana, tmpchana);
@@ -3007,19 +3013,21 @@
/* make the channels compatible, send error if we fail doing so */
if (ast_channel_make_compatible(tmpchana, tmpchanb)) {
ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for manager bridge\n", tmpchana->name, tmpchanb->name);
- astman_send_error(s, m, "Could not make channels compatible for manager bridge");
+ err_msg = "Could not make channels compatible for manager bridge";
ast_hangup(tmpchana);
ast_hangup(tmpchanb);
- return 1;
+ res = 1;
+ goto return_cleanup;
}
/* setup the bridge thread object and start the bridge */
if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
ast_log(LOG_WARNING, "Unable to spawn a new bridge thread on %s and %s: %s\n", tmpchana->name, tmpchanb->name, strerror(errno));
- astman_send_error(s, m, "Unable to spawn a new bridge thread");
+ err_msg = "Unable to spawn a new bridge thread";
ast_hangup(tmpchana);
ast_hangup(tmpchanb);
- return 1;
+ res = 1;
+ goto return_cleanup;
}
tobj->chan = tmpchana;
@@ -3037,7 +3045,14 @@
astman_send_ack(s, m, "Launched bridge thread with success");
- return 0;
+return_cleanup:
+ ast_channel_unref(chana);
+ ast_channel_unref(chanb);
+
+ if (err_msg)
+ astman_send_error(s, m, err_msg);
+
+ return res;
}
/*!
@@ -3188,24 +3203,23 @@
return 0;
}
- ch1 = ast_get_channel_by_name_locked(channel);
- if (!ch1) {
+ if (!(ch1 = ast_channel_get_by_name(channel))) {
snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel);
astman_send_error(s, m, buf);
return 0;
}
- ch2 = ast_get_channel_by_name_locked(channel2);
- if (!ch2) {
+ if (!(ch2 = ast_channel_get_by_name(channel2))) {
+ ast_channel_unref(ch1);
snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel2);
astman_send_error(s, m, buf);
- ast_channel_unlock(ch1);
return 0;
}
- if (!ast_strlen_zero(timeout)) {
+ if (!ast_strlen_zero(timeout))
sscanf(timeout, "%d", &to);
- }
+
+ ast_channel_lock_both(ch1, ch2);
res = ast_masq_park_call(ch1, ch2, to, &parkExt);
if (!res) {
@@ -3217,6 +3231,9 @@
ast_channel_unlock(ch1);
ast_channel_unlock(ch2);
+
+ ast_channel_unref(ch1);
+ ast_channel_unref(ch2);
return 0;
}
@@ -3233,17 +3250,27 @@
{
struct ast_channel *cur = NULL;
int res = -1;
-
- while ((cur = ast_channel_walk_locked(cur)) != NULL) {
+ struct ast_channel_iterator *iter;
+
+ if (!(iter = ast_channel_iterator_all_new()))
+ return -1;
+
+ while ((cur = ast_channel_iterator_next(iter))) {
+ ast_channel_lock(cur);
if (!cur->pbx &&
(cur != chan) &&
(chan->pickupgroup & cur->callgroup) &&
((cur->_state == AST_STATE_RINGING) ||
(cur->_state == AST_STATE_RING))) {
+ ast_channel_unlock(cur);
break;
}
ast_channel_unlock(cur);
- }
+ ast_channel_unref(cur);
+ }
+
+ iter = ast_channel_iterator_destroy(iter);
+
if (cur) {
ast_debug(1, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
res = ast_answer(chan);
@@ -3255,10 +3282,11 @@
res = ast_channel_masquerade(cur, chan);
if (res)
ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
- ast_channel_unlock(cur);
+ ast_channel_unref(cur);
} else {
ast_debug(1, "No call pickup possible...\n");
}
+
return res;
}
@@ -3329,7 +3357,7 @@
}
/* make sure we have a valid end point */
- if (!(current_dest_chan = ast_get_channel_by_name_prefix_locked(args.dest_chan,
+ if (!(current_dest_chan = ast_channel_get_by_name_prefix(args.dest_chan,
strlen(args.dest_chan)))) {
ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
"cannot get its lock\n", args.dest_chan);
@@ -3341,7 +3369,6 @@
pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
return 0;
}
- ast_channel_unlock(current_dest_chan);
/* answer the channel if needed */
if (current_dest_chan->_state != AST_STATE_UP)
@@ -3356,11 +3383,21 @@
"Reason: cannot create placeholder\r\n"
"Channel1: %s\r\n"
"Channel2: %s\r\n", chan->name, args.dest_chan);
- }
+ ast_hangup(current_dest_chan);
+ pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT");
+ return 0;
+ }
+
+ ast_channel_lock_both(current_dest_chan, final_dest_chan);
do_bridge_masquerade(current_dest_chan, final_dest_chan);
+ ast_channel_unlock(final_dest_chan);
+ ast_channel_unlock(current_dest_chan);
+ current_dest_chan = ast_channel_unref(current_dest_chan);
+
/* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
/* try to make compatible, send error if we fail */
+ ast_channel_lock(final_dest_chan);
if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
manager_event(EVENT_FLAG_CALL, "BridgeExec",
@@ -3368,6 +3405,7 @@
"Reason: Could not make channels compatible for bridge\r\n"
"Channel1: %s\r\n"
"Channel2: %s\r\n", chan->name, final_dest_chan->name);
+ ast_channel_unlock(final_dest_chan);
ast_hangup(final_dest_chan); /* may be we should return this channel to the PBX? */
pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "INCOMPATIBLE");
return 0;
@@ -3386,7 +3424,9 @@
ast_log(LOG_WARNING, "Failed to play courtesy tone on %s\n", final_dest_chan->name);
}
}
-
+
+ ast_channel_unlock(final_dest_chan);
+
/* do the bridge */
ast_bridge_call(chan, final_dest_chan, &bconfig);
@@ -3402,6 +3442,8 @@
ast_hangup(final_dest_chan);
} else
ast_debug(1, "SUCCESS continuing PBX on chan %s\n", final_dest_chan->name);
+
+ ast_channel_unref(final_dest_chan);
} else {
ast_debug(1, "hangup chan %s since the other endpoint has hung up\n", final_dest_chan->name);
ast_hangup(final_dest_chan);
More information about the asterisk-commits
mailing list