aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2005-08-09 01:59:59 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2005-08-09 01:59:59 +0000
commite915d19e2feb107878a566f88f99f023b82b90f6 (patch)
treefe65734fb55f7f0e65a4e554aa801939b67b4b80 /channels
parent53fb7866aba8a5605080dc284ac036f245352fb6 (diff)
bridging code cleanups:
code style, formatting use enum/symbolic constants for return codes efficiency improvements (zaptel) only disable DTMF detection once per bridge, not every frame (zaptel) ensure VPM DTMF detector is turned off during native bridge git-svn-id: http://svn.digium.com/svn/asterisk/trunk@6312 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rwxr-xr-xchannels/chan_iax2.c32
-rwxr-xr-xchannels/chan_vpb.c15
-rwxr-xr-xchannels/chan_zap.c300
3 files changed, 184 insertions, 163 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index cfa62bb54..9c12b29f5 100755
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -708,7 +708,7 @@ static struct ast_frame *iax2_read(struct ast_channel *c);
static int iax2_write(struct ast_channel *c, struct ast_frame *f);
static int iax2_indicate(struct ast_channel *c, int condition);
static int iax2_setoption(struct ast_channel *c, int option, void *data, int datalen);
-static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
+static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
static int iax2_transfer(struct ast_channel *c, const char *dest);
static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan);
@@ -3050,7 +3050,7 @@ static void unlock_both(unsigned short callno0, unsigned short callno1)
ast_mutex_unlock(&iaxsl[callno0]);
}
-static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
+static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
{
struct ast_channel *cs[3];
struct ast_channel *who;
@@ -3089,7 +3089,7 @@ static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
iaxs[callno1]->bridgecallno = 0;
ast_mutex_unlock(&iaxsl[callno1]);
}
- return -2;
+ return AST_BRIDGE_FAILED_NOWARN;
}
if (c0->nativeformats != c1->nativeformats) {
if (option_verbose > 2) {
@@ -3104,7 +3104,7 @@ static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
iaxs[callno0]->bridgecallno = 0;
iaxs[callno1]->bridgecallno = 0;
unlock_both(callno0, callno1);
- return -2;
+ return AST_BRIDGE_FAILED_NOWARN;
}
/* check if transfered and if we really want native bridging */
if (!transferstarted && !ast_test_flag(iaxs[callno0], IAX_NOTRANSFER) && !ast_test_flag(iaxs[callno1], IAX_NOTRANSFER) &&
@@ -3124,7 +3124,7 @@ static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
c1->_softhangup |= AST_SOFTHANGUP_DEV;
*fo = NULL;
*rc = c0;
- res = 0;
+ res = AST_BRIDGE_COMPLETE;
break;
}
}
@@ -3132,7 +3132,7 @@ static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
who = ast_waitfor_n(cs, 2, &to);
if (!who) {
if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
- res = -1;
+ res = AST_BRIDGE_FAILED;
break;
}
continue;
@@ -3141,28 +3141,27 @@ static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
if (!f) {
*fo = NULL;
*rc = who;
- res = 0;
+ res = AST_BRIDGE_COMPLETE;
break;
}
if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
*fo = f;
*rc = who;
- res = 0;
+ res = AST_BRIDGE_COMPLETE;
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_DTMF)) {
+ (f->frametype == AST_FRAME_TEXT) ||
+ (f->frametype == AST_FRAME_VIDEO) ||
+ (f->frametype == AST_FRAME_IMAGE) ||
+ (f->frametype == AST_FRAME_DTMF)) {
if ((f->frametype == AST_FRAME_DTMF) &&
- (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
+ (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))) {
if ((who == c0)) {
if ((flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
*rc = c0;
*fo = f;
- /* Take out of conference mode */
- res = 0;
+ res = AST_BRIDGE_COMPLETE;
/* Remove from native mode */
break;
} else
@@ -3172,8 +3171,7 @@ static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags
if (flags & AST_BRIDGE_DTMF_CHANNEL_1) {
*rc = c1;
*fo = f;
- res = 0;
- /* Remove from native mode */
+ res = AST_BRIDGE_COMPLETE;
break;
} else
goto tackygoto;
diff --git a/channels/chan_vpb.c b/channels/chan_vpb.c
index 6289629eb..be6004992 100755
--- a/channels/chan_vpb.c
+++ b/channels/chan_vpb.c
@@ -326,7 +326,7 @@ static int vpb_hangup(struct ast_channel *ast);
static int vpb_answer(struct ast_channel *ast);
static struct ast_frame *vpb_read(struct ast_channel *ast);
static int vpb_write(struct ast_channel *ast, struct ast_frame *frame);
-static int vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
+static enum ast_bridge_result vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
static int vpb_indicate(struct ast_channel *ast, int condition);
static int vpb_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
@@ -396,11 +396,12 @@ static struct ast_channel_tech vpb_tech_indicate = {
/* #define HALF_DUPLEX_BRIDGE */
/* This is the Native bridge code, which Asterisk will try before using its own bridging code */
-static int vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
+static enum ast_bridge_result vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
{
struct vpb_pvt *p0 = (struct vpb_pvt *)c0->tech_pvt;
struct vpb_pvt *p1 = (struct vpb_pvt *)c1->tech_pvt;
- int i, res;
+ int i;
+ enum ast_bridge_result res;
struct ast_channel *cs[3];
struct ast_channel *who;
@@ -412,10 +413,10 @@ static int vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
#ifdef BAD_V4PCI_BRIDGE
if(p0->vpb_model==vpb_model_v4pci)
- return -2;
+ return AST_BRIDGE_FAILED_NOWARN;
#endif
if ( UseNativeBridge != 1){
- return -2;
+ return AST_BRIDGE_FAILED_NOWARN;
}
/*
@@ -444,7 +445,7 @@ static int vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
ast_log(LOG_WARNING, "%s: vpb_bridge: Failed to bridge %s and %s!\n", p0->dev, c0->name, c1->name);
ast_mutex_unlock(&p0->lock);
ast_mutex_unlock(&p1->lock);
- return -2;
+ return AST_BRIDGE_FAILED_NOWARN;
} else {
/* Set bridge pointers. You don't want to take these locks while holding bridge lock.*/
ast_mutex_lock(&p0->lock); {
@@ -581,7 +582,7 @@ static int vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
ast_mutex_unlock(&p0->lock);
ast_mutex_unlock(&p1->lock);
*/
- return (res==VPB_OK)?0:-1;
+ return (res==VPB_OK) ? AST_BRIDGE_COMPLETE : AST_BRIDGE_FAILED;
}
/* Caller ID can be located in different positions between the rings depending on your Telco
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index 0874a3118..b352a1fa6 100755
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -323,7 +323,7 @@ static pthread_t monitor_thread = AST_PTHREADT_NULL;
static int restart_monitor(void);
-static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
+static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
static int zt_sendtext(struct ast_channel *c, const char *text);
@@ -664,7 +664,6 @@ static int zt_hangup(struct ast_channel *ast);
static int zt_answer(struct ast_channel *ast);
struct ast_frame *zt_read(struct ast_channel *ast);
static int zt_write(struct ast_channel *ast, struct ast_frame *frame);
-static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
struct ast_frame *zt_exception(struct ast_channel *ast);
static int zt_indicate(struct ast_channel *chan, int condition);
static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
@@ -2775,29 +2774,59 @@ static void zt_link(struct zt_pvt *slave, struct zt_pvt *master) {
ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
}
-static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
+static void disable_dtmf_detect(struct zt_pvt *p)
{
- struct ast_channel *who = NULL, *cs[3];
+ int val;
+
+ p->ignoredtmf = 1;
+
+#ifdef ZT_TONEDETECT
+ val = 0;
+ ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
+#endif
+
+}
+
+static void enable_dtmf_detect(struct zt_pvt *p)
+{
+ int val;
+
+ p->ignoredtmf = 0;
+
+#ifdef ZT_TONEDETECT
+ val = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
+ ioctl(p->subs[SUB_REAL].zfd, ZT_TONEDETECT, &val);
+#endif
+}
+
+static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
+{
+ struct ast_channel *who;
struct zt_pvt *p0, *p1, *op0, *op1;
- struct zt_pvt *master=NULL, *slave=NULL;
+ struct zt_pvt *master = NULL, *slave = NULL;
struct ast_frame *f;
int to;
int inconf = 0;
- int nothingok = 0;
- int ofd1, ofd2;
- int oi1, oi2, i1 = -1, i2 = -1, t1, t2;
- int os1 = -1, os2 = -1;
- struct ast_channel *oc1, *oc2;
+ int nothingok = 1;
+ int ofd0, ofd1;
+ int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
+ int os0 = -1, os1 = -1;
+ struct ast_channel *oc0, *oc1;
+ enum ast_bridge_result res;
+
#ifdef PRI_2BCT
int triedtopribridge = 0;
q931_call *q931c0 = NULL, *q931c1 = NULL;
#endif
+ /* For now, don't attempt to native bridge if either channel needs DTMF detection.
+ There is code below to handle it properly until DTMF is actually seen,
+ but due to currently unresolved issues it's ignored...
+ */
- /* if need DTMF, cant native bridge */
if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
- return -2;
-
+ return AST_BRIDGE_FAILED_NOWARN;
+
ast_mutex_lock(&c0->lock);
ast_mutex_lock(&c1->lock);
@@ -2807,24 +2836,23 @@ static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
ast_mutex_unlock(&c0->lock);
ast_mutex_unlock(&c1->lock);
- return -2;
+ return AST_BRIDGE_FAILED_NOWARN;
}
- op0 = p0 = c0->tech_pvt;
- op1 = p1 = c1->tech_pvt;
- ofd1 = c0->fds[0];
- ofd2 = c1->fds[0];
- oi1 = zt_get_index(c0, p0, 0);
- oi2 = zt_get_index(c1, p1, 0);
- oc1 = p0->owner;
- oc2 = p1->owner;
- if ((oi1 < 0) || (oi2 < 0)) {
+ oi0 = zt_get_index(c0, p0, 0);
+ oi1 = zt_get_index(c1, p1, 0);
+ if ((oi0 < 0) || (oi1 < 0)) {
ast_mutex_unlock(&c0->lock);
ast_mutex_unlock(&c1->lock);
- return -1;
+ return AST_BRIDGE_FAILED;
}
-
+ op0 = p0 = c0->tech_pvt;
+ op1 = p1 = c1->tech_pvt;
+ ofd0 = c0->fds[0];
+ ofd1 = c1->fds[0];
+ oc0 = p0->owner;
+ oc1 = p1->owner;
ast_mutex_lock(&p0->lock);
if (ast_mutex_trylock(&p1->lock)) {
@@ -2833,13 +2861,11 @@ static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
ast_mutex_unlock(&c0->lock);
ast_mutex_unlock(&c1->lock);
ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
- return -3;
+ return AST_BRIDGE_RETRY;
}
- if ((oi1 == SUB_REAL) && (oi2 == SUB_REAL)) {
- if (!p0->owner || !p1->owner) {
- /* Currently unowned -- Do nothing. */
- nothingok = 1;
- } else {
+
+ if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
+ if (p0->owner && p1->owner) {
/* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
master = p0;
@@ -2851,40 +2877,41 @@ static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
inconf = 1;
} else {
ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
- ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", p0->channel, oi1, (p0->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0, p0->subs[SUB_REAL].inthreeway,
- p0->channel, oi1, (p1->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0, p1->subs[SUB_REAL].inthreeway);
+ ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
+ p0->channel,
+ oi0, (p0->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
+ p0->subs[SUB_REAL].inthreeway, p0->channel,
+ oi0, (p1->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
+ p1->subs[SUB_REAL].inthreeway);
}
+ nothingok = 0;
}
- } else if ((oi1 == SUB_REAL) && (oi2 == SUB_THREEWAY)) {
+ } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
if (p1->subs[SUB_THREEWAY].inthreeway) {
master = p1;
slave = p0;
- } else {
- nothingok = 1;
+ nothingok = 0;
}
- } else if ((oi1 == SUB_THREEWAY) && (oi2 == SUB_REAL)) {
+ } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
if (p0->subs[SUB_THREEWAY].inthreeway) {
master = p0;
slave = p1;
- } else {
- nothingok = 1;
+ nothingok = 0;
}
- } else if ((oi1 == SUB_REAL) && (oi2 == SUB_CALLWAIT)) {
+ } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
/* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
don't put us in anything */
if (p1->subs[SUB_CALLWAIT].inthreeway) {
master = p1;
slave = p0;
- } else {
- nothingok = 1;
+ nothingok = 0;
}
- } else if ((oi1 == SUB_CALLWAIT) && (oi2 == SUB_REAL)) {
+ } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
/* Same as previous */
if (p0->subs[SUB_CALLWAIT].inthreeway) {
master = p0;
slave = p1;
- } else {
- nothingok = 1;
+ nothingok = 0;
}
}
ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
@@ -2893,31 +2920,31 @@ static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
/* Stop any tones, or play ringtone as appropriate. If they're bridged
in an active threeway call with a channel that is ringing, we should
indicate ringing. */
- if ((oi2 == SUB_THREEWAY) &&
- p1->subs[SUB_THREEWAY].inthreeway &&
- p1->subs[SUB_REAL].owner &&
- p1->subs[SUB_REAL].inthreeway &&
- (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
- ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
- tone_zone_play_tone(p0->subs[oi1].zfd, ZT_TONE_RINGTONE);
- os2 = p1->subs[SUB_REAL].owner->_state;
- } else {
- ast_log(LOG_DEBUG, "Stoping tones on %d/%d talking to %d/%d\n", p0->channel, oi1, p1->channel, oi2);
- tone_zone_play_tone(p0->subs[oi1].zfd, -1);
- }
if ((oi1 == SUB_THREEWAY) &&
- p0->subs[SUB_THREEWAY].inthreeway &&
- p0->subs[SUB_REAL].owner &&
- p0->subs[SUB_REAL].inthreeway &&
- (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
- ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
- tone_zone_play_tone(p1->subs[oi2].zfd, ZT_TONE_RINGTONE);
- os1 = p0->subs[SUB_REAL].owner->_state;
+ p1->subs[SUB_THREEWAY].inthreeway &&
+ p1->subs[SUB_REAL].owner &&
+ p1->subs[SUB_REAL].inthreeway &&
+ (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
+ ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
+ tone_zone_play_tone(p0->subs[oi0].zfd, ZT_TONE_RINGTONE);
+ os1 = p1->subs[SUB_REAL].owner->_state;
+ } else {
+ ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
+ tone_zone_play_tone(p0->subs[oi0].zfd, -1);
+ }
+ if ((oi0 == SUB_THREEWAY) &&
+ p0->subs[SUB_THREEWAY].inthreeway &&
+ p0->subs[SUB_REAL].owner &&
+ p0->subs[SUB_REAL].inthreeway &&
+ (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
+ ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
+ tone_zone_play_tone(p1->subs[oi1].zfd, ZT_TONE_RINGTONE);
+ os0 = p0->subs[SUB_REAL].owner->_state;
} else {
- ast_log(LOG_DEBUG, "Stoping tones on %d/%d talking to %d/%d\n", p1->channel, oi2, p0->channel, oi1);
- tone_zone_play_tone(p1->subs[oi1].zfd, -1);
+ ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
+ tone_zone_play_tone(p1->subs[oi0].zfd, -1);
}
- if ((oi1 == SUB_REAL) && (oi2 == SUB_REAL)) {
+ if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
if (!p0->echocanbridged || !p1->echocanbridged) {
/* Disable echo cancellation if appropriate */
zt_disable_ec(p0);
@@ -2927,12 +2954,12 @@ static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
zt_link(slave, master);
master->inconference = inconf;
} else if (!nothingok)
- ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi1], p1->channel, subnames[oi2]);
+ ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
update_conf(p0);
update_conf(p1);
- t1 = p0->subs[SUB_REAL].inthreeway;
- t2 = p1->subs[SUB_REAL].inthreeway;
+ t0 = p0->subs[SUB_REAL].inthreeway;
+ t1 = p1->subs[SUB_REAL].inthreeway;
ast_mutex_unlock(&p0->lock);
ast_mutex_unlock(&p1->lock);
@@ -2942,17 +2969,22 @@ static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
/* Native bridge failed */
if ((!master || !slave) && !nothingok) {
- if (op0 == p0)
- zt_enable_ec(p0);
- if (op1 == p1)
- zt_enable_ec(p1);
- return -1;
+ zt_enable_ec(p0);
+ zt_enable_ec(p1);
+ return AST_BRIDGE_FAILED;
}
- cs[0] = c0;
- cs[1] = c1;
- cs[2] = NULL;
+ if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0))
+ disable_dtmf_detect(op0);
+
+ if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1))
+ disable_dtmf_detect(op1);
+
for (;;) {
+ struct ast_channel *c0_priority[2] = {c0, c1};
+ struct ast_channel *c1_priority[2] = {c1, c0};
+ int priority = 0;
+
/* Here's our main loop... Start by locking things, looking for private parts,
and then balking if anything is wrong */
ast_mutex_lock(&c0->lock);
@@ -2964,94 +2996,84 @@ static int zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags,
q931c0 = p0->call;
q931c1 = p1->call;
if (p0->transfer && p1->transfer
- && q931c0 && q931c1
- && !triedtopribridge) {
-
+ && q931c0 && q931c1
+ && !triedtopribridge) {
pri_channel_bridge(q931c0, q931c1);
triedtopribridge = 1;
}
#endif
+
if (op0 == p0)
- i1 = zt_get_index(c0, p0, 1);
+ i0 = zt_get_index(c0, p0, 1);
if (op1 == p1)
- i2 = zt_get_index(c1, p1, 1);
+ i1 = zt_get_index(c1, p1, 1);
ast_mutex_unlock(&c0->lock);
ast_mutex_unlock(&c1->lock);
- if ((op0 != p0) || (op1 != p1) ||
- (ofd1 != c0->fds[0]) ||
- (ofd2 != c1->fds[0]) ||
- (p0->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p0->subs[SUB_REAL].owner->_state)) ||
- (p1->subs[SUB_REAL].owner && (os2 > -1) && (os2 != p1->subs[SUB_REAL].owner->_state)) ||
- (oc1 != p0->owner) ||
- (oc2 != p1->owner) ||
- (t1 != p0->subs[SUB_REAL].inthreeway) ||
- (t2 != p1->subs[SUB_REAL].inthreeway) ||
- (oi1 != i1) ||
- (oi2 != i2)) {
- if (slave && master)
- zt_unlink(slave, master, 1);
+
+ if ((op0 != p0) ||
+ (op1 != p1) ||
+ (ofd0 != c0->fds[0]) ||
+ (ofd1 != c1->fds[0]) ||
+ (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
+ (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
+ (oc0 != p0->owner) ||
+ (oc1 != p1->owner) ||
+ (t0 != p0->subs[SUB_REAL].inthreeway) ||
+ (t1 != p1->subs[SUB_REAL].inthreeway) ||
+ (oi0 != i0) ||
+ (oi1 != i0)) {
ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
- op0->channel, oi1, op1->channel, oi2);
- if (op0 == p0)
- zt_enable_ec(p0);
- if (op1 == p1)
- zt_enable_ec(p1);
- return -3;
+ op0->channel, oi0, op1->channel, oi1);
+ res = AST_BRIDGE_RETRY;
+ goto return_from_bridge;
}
to = -1;
- who = ast_waitfor_n(cs, 2, &to);
+ who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &to);
if (!who) {
ast_log(LOG_DEBUG, "Ooh, empty read...\n");
continue;
}
- if (who->tech_pvt == op0)
- op0->ignoredtmf = 1;
- else if (who->tech_pvt == op1)
- op1->ignoredtmf = 1;
f = ast_read(who);
- if (who->tech_pvt == op0)
- op0->ignoredtmf = 0;
- else if (who->tech_pvt == op1)
- op1->ignoredtmf = 0;
- if (!f) {
- *fo = NULL;
- *rc = who;
- if (slave && master)
- zt_unlink(slave, master, 1);
- if (op0 == p0)
- zt_enable_ec(p0);
- if (op1 == p1)
- zt_enable_ec(p1);
- return 0;
- }
- if (f->frametype == AST_FRAME_CONTROL) {
+ if (!f || (f->frametype == AST_FRAME_CONTROL)) {
*fo = f;
*rc = who;
- if (slave && master)
- zt_unlink(slave, master, 1);
- return 0;
+ res = AST_BRIDGE_COMPLETE;
+ goto return_from_bridge;
}
if (f->frametype == AST_FRAME_DTMF) {
- if (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
- ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))) {
- *fo = f;
- *rc = who;
- if (slave && master)
- zt_unlink(slave, master, 1);
- return 0;
- } else if ((who == c0) && p0->pulsedial) {
+ if ((who == c0) && p0->pulsedial) {
ast_write(c1, f);
- } else if ((who == c1) && p1->pulsedial) {
+ } else if (p1->pulsedial) {
ast_write(c0, f);
+ } else {
+ *fo = f;
+ *rc = who;
+ res = AST_BRIDGE_COMPLETE;
+ goto return_from_bridge;
}
}
ast_frfree(f);
-
+
/* Swap who gets priority */
- cs[2] = cs[0];
- cs[0] = cs[1];
- cs[1] = cs[2];
+ priority = !priority;
}
+
+return_from_bridge:
+ if (op0 == p0)
+ zt_enable_ec(p0);
+
+ if (op1 == p1)
+ zt_enable_ec(p1);
+
+ if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0))
+ enable_dtmf_detect(op0);
+
+ if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1))
+ enable_dtmf_detect(op1);
+
+ zt_unlink(slave, master, 1);
+
+ return res;
}
static int zt_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)