[Asterisk-cvs] asterisk channel.c,1.182,1.183
markster at lists.digium.com
markster at lists.digium.com
Wed Mar 30 21:07:05 CST 2005
Update of /usr/cvsroot/asterisk
In directory mongoose.digium.com:/tmp/cvs-serv20815
Modified Files:
channel.c
Log Message:
Make bridging more efficient
Index: channel.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channel.c,v
retrieving revision 1.182
retrieving revision 1.183
diff -u -d -r1.182 -r1.183
--- channel.c 30 Mar 2005 22:09:01 -0000 1.182
+++ channel.c 31 Mar 2005 03:00:37 -0000 1.183
@@ -1286,6 +1286,7 @@
int (*func)(void *);
void *data;
int res;
+ int prestate;
#endif
static struct ast_frame null_frame =
{
@@ -1310,6 +1311,7 @@
ast_mutex_unlock(&chan->lock);
return NULL;
}
+ prestate = chan->_state;
if (!ast_test_flag(chan, AST_FLAG_DEFER_DTMF) && !ast_strlen_zero(chan->dtmfq)) {
/* We have DTMF that has been deferred. Return it now */
@@ -1457,7 +1459,7 @@
ast_log(LOG_WARNING, "Dropping deferred DTMF digits on %s\n", chan->name);
f = &null_frame;
} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
- if (chan->_state == AST_STATE_UP) {
+ if (prestate == AST_STATE_UP) {
ast_log(LOG_DEBUG, "Dropping duplicate answer!\n");
f = &null_frame;
}
@@ -2758,7 +2760,7 @@
check = ast_autoservice_stop(peer);
}
-int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
+static int ast_generic_bridge(int *playitagain, int *playit, struct timeval *start_time, struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
{
/* Copy voice back and forth between the two channels. Give the peer
the ability to transfer calls with '#<extension' syntax. */
@@ -2766,6 +2768,147 @@
int to = -1;
struct ast_frame *f;
struct ast_channel *who = NULL;
+ void *pvt0, *pvt1;
+ int res=0;
+ int o0nativeformats;
+ int o1nativeformats;
+ struct timeval precise_now;
+ long elapsed_ms=0, time_left_ms=0;
+
+ cs[0] = c0;
+ cs[1] = c1;
+ pvt0 = c0->pvt;
+ pvt1 = c1->pvt;
+ o0nativeformats = c0->nativeformats;
+ o1nativeformats = c1->nativeformats;
+
+ for (;;) {
+ if ((c0->pvt != pvt0) || (c1->pvt != pvt1) ||
+ (o0nativeformats != c0->nativeformats) ||
+ (o1nativeformats != c1->nativeformats)) {
+ /* Check for Masquerade, codec changes, etc */
+ res = -3;
+ break;
+ }
+ /* timestamp */
+ if (config->timelimit) {
+ /* If there is a time limit, return now */
+ gettimeofday(&precise_now,NULL);
+ elapsed_ms = tvdiff(&precise_now,start_time);
+ time_left_ms = config->timelimit - elapsed_ms;
+
+ if (*playitagain && ((ast_test_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING)) || (ast_test_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING))) && (config->play_warning && time_left_ms <= config->play_warning)) {
+ res = -3;
+ break;
+ }
+ if (time_left_ms <= 0) {
+ res = -3;
+ break;
+ }
+ if (time_left_ms >= 5000 && *playit) {
+ res = -3;
+ break;
+ }
+
+ }
+
+ who = ast_waitfor_n(cs, 2, &to);
+ if (!who) {
+ ast_log(LOG_DEBUG, "Nobody there, continuing...\n");
+ if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) {
+ if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
+ c0->_softhangup = 0;
+ if (c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
+ c1->_softhangup = 0;
+ c0->_bridge = c1;
+ c1->_bridge = c0;
+ continue;
+ }
+
+ continue;
+ }
+ f = ast_read(who);
+ if (!f) {
+ *fo = NULL;
+ *rc = who;
+ res = 0;
+ ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
+ break;
+ }
+
+ if ((f->frametype == AST_FRAME_CONTROL) && !(config->flags & AST_BRIDGE_IGNORE_SIGS)) {
+ if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD)) {
+ ast_indicate(who == c0 ? c1 : c0, f->subclass);
+ } else {
+ *fo = f;
+ *rc = who;
+ res = 0;
+ ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
+ break;
+ }
+ }
+ if ((f->frametype == AST_FRAME_VOICE) ||
+ (f->frametype == AST_FRAME_TEXT) ||
+ (f->frametype == AST_FRAME_VIDEO) ||
+ (f->frametype == AST_FRAME_IMAGE) ||
+ (f->frametype == AST_FRAME_HTML) ||
+ (f->frametype == AST_FRAME_DTMF)) {
+
+ if ((f->frametype == AST_FRAME_DTMF) &&
+ (config->flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
+ if ((who == c0)) {
+ if ((config->flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
+ *rc = c0;
+ *fo = f;
+ /* Take out of conference mode */
+ res = 0;
+ ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name);
+ break;
+ } else
+ goto tackygoto;
+ } else
+ if ((who == c1)) {
+ if (config->flags & AST_BRIDGE_DTMF_CHANNEL_1) {
+ *rc = c1;
+ *fo = f;
+ res = 0;
+ ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name);
+ break;
+ } else
+ goto tackygoto;
+ }
+ } else {
+#if 0
+ ast_log(LOG_DEBUG, "Read from %s\n", who->name);
+ if (who == last)
+ ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
+ last = who;
+#endif
+tackygoto:
+ /* Don't copy packets if there is a generator on either one, since they're
+ not supposed to be listening anyway */
+ if (who == c0)
+ ast_write(c1, f);
+ else
+ ast_write(c0, f);
+ }
+ }
+ ast_frfree(f);
+
+ /* Swap who gets priority */
+ cs[2] = cs[0];
+ cs[0] = cs[1];
+ cs[1] = cs[2];
+ }
+ return res;
+}
+
+int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
+{
+ /* Copy voice back and forth between the two channels. Give the peer
+ the ability to transfer calls with '#<extension' syntax. */
+ struct ast_channel *cs[3];
+ struct ast_channel *who = NULL;
int res=0;
int nativefailed=0;
int firstpass;
@@ -2865,7 +3008,7 @@
c1->_softhangup = 0;
c0->_bridge = c1;
c1->_bridge = c0;
- ast_log(LOG_DEBUG, "UNBRIDGE SIGNAL RECEIVED! ENDING NATIVE BRIDGE IF IT EXISTS.\n");
+ ast_log(LOG_DEBUG, "Unbridge signal received. Ending native bridge.\n");
continue;
}
@@ -2928,96 +3071,11 @@
return -1;
}
o0nativeformats = c0->nativeformats;
-
o1nativeformats = c1->nativeformats;
}
- who = ast_waitfor_n(cs, 2, &to);
- if (!who) {
- ast_log(LOG_DEBUG, "Nobody there, continuing...\n");
- if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) {
- if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
- c0->_softhangup = 0;
- if (c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE)
- c1->_softhangup = 0;
- c0->_bridge = c1;
- c1->_bridge = c0;
- continue;
- }
-
- continue;
- }
- f = ast_read(who);
- if (!f) {
- *fo = NULL;
- *rc = who;
- res = 0;
- ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
+ res = ast_generic_bridge(&playitagain, &playit, &start_time, c0, c1, config, fo, rc);
+ if (res != -3)
break;
- }
-
- if ((f->frametype == AST_FRAME_CONTROL) && !(config->flags & AST_BRIDGE_IGNORE_SIGS)) {
- if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD)) {
- ast_indicate(who == c0 ? c1 : c0, f->subclass);
- } else {
- *fo = f;
- *rc = who;
- res = 0;
- ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
- break;
- }
- }
- if ((f->frametype == AST_FRAME_VOICE) ||
- (f->frametype == AST_FRAME_TEXT) ||
- (f->frametype == AST_FRAME_VIDEO) ||
- (f->frametype == AST_FRAME_IMAGE) ||
- (f->frametype == AST_FRAME_HTML) ||
- (f->frametype == AST_FRAME_DTMF)) {
-
- if ((f->frametype == AST_FRAME_DTMF) &&
- (config->flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
- if ((who == c0)) {
- if ((config->flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
- *rc = c0;
- *fo = f;
- /* Take out of conference mode */
- res = 0;
- ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_0 on c0 (%s)\n",c0->name);
- break;
- } else
- goto tackygoto;
- } else
- if ((who == c1)) {
- if (config->flags & AST_BRIDGE_DTMF_CHANNEL_1) {
- *rc = c1;
- *fo = f;
- res = 0;
- ast_log(LOG_DEBUG, "Got AST_BRIDGE_DTMF_CHANNEL_1 on c1 (%s)\n",c1->name);
- break;
- } else
- goto tackygoto;
- }
- } else {
-#if 0
- ast_log(LOG_DEBUG, "Read from %s\n", who->name);
- if (who == last)
- ast_log(LOG_DEBUG, "Servicing channel %s twice in a row?\n", last->name);
- last = who;
-#endif
-tackygoto:
- /* Don't copy packets if there is a generator on either one, since they're
- not supposed to be listening anyway */
- if (who == c0)
- ast_write(c1, f);
- else
- ast_write(c0, f);
- }
- }
- ast_frfree(f);
-
- /* Swap who gets priority */
- cs[2] = cs[0];
- cs[0] = cs[1];
- cs[1] = cs[2];
}
c0->_bridge = NULL;
c1->_bridge = NULL;
More information about the svn-commits
mailing list