[asterisk-commits] rmudgett: branch rmudgett/native_dahdi r394389 - in /team/rmudgett/native_dah...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Jul 15 13:00:19 CDT 2013


Author: rmudgett
Date: Mon Jul 15 13:00:17 2013
New Revision: 394389

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=394389
Log:
Fill in native_start() and native_stop().

Modified:
    team/rmudgett/native_dahdi/channels/chan_dahdi.c
    team/rmudgett/native_dahdi/channels/chan_dahdi.h
    team/rmudgett/native_dahdi/channels/dahdi/bridge_native_dahdi.c

Modified: team/rmudgett/native_dahdi/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/native_dahdi/channels/chan_dahdi.c?view=diff&rev=394389&r1=394388&r2=394389
==============================================================================
--- team/rmudgett/native_dahdi/channels/chan_dahdi.c (original)
+++ team/rmudgett/native_dahdi/channels/chan_dahdi.c Mon Jul 15 13:00:17 2013
@@ -694,6 +694,12 @@
 #define POLARITY_IDLE   0
 #define POLARITY_REV    1
 
+const char * const subnames[] = {
+	"Real",
+	"Callwait",
+	"Threeway"
+};
+
 #define DATA_EXPORT_DAHDI_PVT(MEMBER)					\
 	MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE)			\
 	MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE)			\
@@ -4359,7 +4365,7 @@
 	return 0;
 }
 
-static void update_conf(struct dahdi_pvt *p)
+void update_conf(struct dahdi_pvt *p)
 {
 	int needconf = 0;
 	int x;
@@ -6710,7 +6716,7 @@
 	return res;
 }
 
-static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
+void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
 {
 	/* Unlink a specific slave or all slaves/masters from a given master */
 	int x;
@@ -6766,7 +6772,8 @@
 	}
 }
 
-static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
+void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master)
+{
 	int x;
 	if (!slave || !master) {
 		ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");

Modified: team/rmudgett/native_dahdi/channels/chan_dahdi.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/native_dahdi/channels/chan_dahdi.h?view=diff&rev=394389&r1=394388&r2=394389
==============================================================================
--- team/rmudgett/native_dahdi/channels/chan_dahdi.h (original)
+++ team/rmudgett/native_dahdi/channels/chan_dahdi.h Mon Jul 15 13:00:17 2013
@@ -52,7 +52,7 @@
 struct sig_ss7_linkset;
 #endif	/* defined(HAVE_SS7) */
 
-#define SUB_REAL	0			/*!< Active call */
+#define SUB_REAL		0			/*!< Active call */
 #define SUB_CALLWAIT	1			/*!< Call-Waiting call on hold */
 #define SUB_THREEWAY	2			/*!< Three-way call */
 
@@ -70,11 +70,7 @@
 };
 
 
-static const char * const subnames[] = {
-	"Real",
-	"Callwait",
-	"Threeway"
-};
+extern const char * const subnames[];
 
 struct dahdi_subchannel {
 	int dfd;
@@ -800,6 +796,10 @@
 void dahdi_enable_ec(struct dahdi_pvt *p);
 void dahdi_disable_ec(struct dahdi_pvt *p);
 
+void update_conf(struct dahdi_pvt *p);
+void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master);
+void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock);
+
 /* ------------------------------------------------------------------- */
 
 #if defined(__cplusplus) || defined(c_plusplus)

Modified: team/rmudgett/native_dahdi/channels/dahdi/bridge_native_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/native_dahdi/channels/dahdi/bridge_native_dahdi.c?view=diff&rev=394389&r1=394388&r2=394389
==============================================================================
--- team/rmudgett/native_dahdi/channels/dahdi/bridge_native_dahdi.c (original)
+++ team/rmudgett/native_dahdi/channels/dahdi/bridge_native_dahdi.c Mon Jul 15 13:00:17 2013
@@ -142,7 +142,31 @@
  */
 static void native_stop(struct ast_bridge *bridge)
 {
-	/*! \todo BUGBUG native_stop() not written */
+	struct native_pvt_bridge *bridge_tech_pvt;
+	struct ast_bridge_channel *cur;
+
+	ast_assert(bridge->tech_pvt != NULL);
+
+	AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
+		struct native_pvt_chan *chan_tech_pvt;
+
+		chan_tech_pvt = cur->tech_pvt;
+		if (!chan_tech_pvt) {
+			continue;
+		}
+
+		ast_mutex_lock(&chan_tech_pvt->pvt->lock);
+		if (chan_tech_pvt->pvt == ast_channel_tech_pvt(cur->chan)) {
+			dahdi_enable_ec(chan_tech_pvt->pvt);
+		}
+		if (chan_tech_pvt->index == SUB_REAL) {
+			enable_dtmf_detect(chan_tech_pvt->pvt);
+		}
+		ast_mutex_unlock(&chan_tech_pvt->pvt->lock);
+	}
+
+	bridge_tech_pvt = bridge->tech_pvt;
+	dahdi_unlink(bridge_tech_pvt->slave, bridge_tech_pvt->master, 1);
 }
 
 /*!
@@ -166,6 +190,7 @@
 	if (!tech_pvt->connected) {
 		return;
 	}
+	tech_pvt->connected = 0;
 
 	/* Now to actually stop the bridge. */
 	native_stop(bridge);
@@ -186,27 +211,256 @@
  */
 static int native_start(struct ast_bridge *bridge)
 {
+	struct native_pvt_bridge *tech_pvt;
+	struct ast_bridge_channel *bc0;
+	struct ast_bridge_channel *bc1;
+	struct native_pvt_chan *npc0;
+	struct native_pvt_chan *npc1;
+	struct ast_channel *c0;
+	struct ast_channel *c1;
+	struct dahdi_pvt *p0;
+	struct dahdi_pvt *p1;
+	struct dahdi_pvt *master;
+	struct dahdi_pvt *slave;
+	int inconf;
+	int nothing_ok;
+
+	ast_assert(bridge->tech_pvt != NULL);
+
+	bc0 = AST_LIST_FIRST(&bridge->channels);
+	bc1 = AST_LIST_LAST(&bridge->channels);
+	c0 = bc0->chan;
+	c1 = bc1->chan;
+
+	/* Lock channels and privates */
+	for (;;) {
+		ast_channel_lock(c0);
+		if (!ast_channel_trylock(c1)) {
+			p0 = ast_channel_tech_pvt(c0);
+			if (!ast_mutex_trylock(&p0->lock)) {
+				p1 = ast_channel_tech_pvt(c1);
+				if (!ast_mutex_trylock(&p1->lock)) {
+					/* Got all locks */
+					break;
+				}
+				ast_mutex_unlock(&p0->lock);
+			}
+			ast_channel_unlock(c1);
+		}
+		ast_channel_unlock(c0);
+		sched_yield();
+	}
+
+	npc0 = bc0->tech_pvt;
+	npc0->pvt = p0;
+	npc0->owner = p0->owner;
+	npc0->index = dahdi_get_index(c0, p0, 0);
+	npc0->fd0 = ast_channel_fd(c0, 0);
+	npc0->state = -1;
+	npc0->inthreeway = p0->subs[SUB_REAL].inthreeway;
+
+	npc1 = bc1->tech_pvt;
+	npc1->pvt = p1;
+	npc1->owner = p1->owner;
+	npc1->index = dahdi_get_index(c1, p1, 0);
+	npc1->fd0 = ast_channel_fd(c1, 0);
+	npc1->state = -1;
+	npc1->inthreeway = p1->subs[SUB_REAL].inthreeway;
+
 	/*
 	 * Check things that can change on the privates while in native
 	 * bridging and cause native to not activate.
 	 */
-#if 0 //BUGBUG
-	if (dahdi_get_index(chan, pvt, 0) < 0) {
-		/* This is something that can change while in native bridge. */
-	}
+	if (npc0->index < 0 || npc1->index < 0
 #if defined(HAVE_PRI)
-	if (dahdi_sig_pri_lib_handles(pvt->sig)
-		&& ((struct sig_pri_chan *) pvt->sig_pvt)->no_b_channel) {
 		/*
 		 * PRI nobch channels (hold and call waiting) are equivalent to
-		 * pseudo channels and cannot be done here.
+		 * pseudo channels and cannot be nativly bridged.
 		 */
-	}
+		|| (dahdi_sig_pri_lib_handles(p0->sig)
+			&& ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
+		|| (dahdi_sig_pri_lib_handles(p1->sig)
+			&& ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)
 #endif	/* defined(HAVE_PRI) */
-#endif
-
-	/*! \todo BUGBUG native_start() not written */
-	return -1;
+		) {
+		ast_mutex_unlock(&p0->lock);
+		ast_mutex_unlock(&p1->lock);
+		ast_channel_unlock(c0);
+		ast_channel_unlock(c1);
+		return -1;
+	}
+
+	inconf = 0;
+	nothing_ok = 1;
+	master = NULL;
+	slave = NULL;
+	if (npc0->index == SUB_REAL && npc1->index == 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;
+				slave = p1;
+				inconf = 1;
+			} else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
+				master = p1;
+				slave = p0;
+				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,
+					npc0->index, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
+					p0->subs[SUB_REAL].inthreeway,
+					p0->channel,
+					npc0->index, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
+					p1->subs[SUB_REAL].inthreeway);
+			}
+			nothing_ok = 0;
+		}
+	} else if (npc0->index == SUB_REAL && npc1->index == SUB_THREEWAY) {
+		if (p1->subs[SUB_THREEWAY].inthreeway) {
+			master = p1;
+			slave = p0;
+			nothing_ok = 0;
+		}
+	} else if (npc0->index == SUB_THREEWAY && npc1->index == SUB_REAL) {
+		if (p0->subs[SUB_THREEWAY].inthreeway) {
+			master = p0;
+			slave = p1;
+			nothing_ok = 0;
+		}
+	} else if (npc0->index == SUB_REAL && npc1->index == 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;
+			nothing_ok = 0;
+		}
+	} else if (npc0->index == SUB_CALLWAIT && npc1->index == SUB_REAL) {
+		/* Same as previous */
+		if (p0->subs[SUB_CALLWAIT].inthreeway) {
+			master = p0;
+			slave = p1;
+			nothing_ok = 0;
+		}
+	}
+	ast_debug(1, "master: %d, slave: %d, nothing_ok: %d\n",
+		master ? master->channel : 0,
+		slave ? slave->channel : 0,
+		nothing_ok);
+	if (master && slave) {
+		/*
+		 * Stop any tones, or play ringtone as appropriate.  If they are
+		 * bridged in an active threeway call with a channel that is
+		 * ringing, we should indicate ringing.
+		 */
+		if (npc1->index == SUB_THREEWAY
+			&& p1->subs[SUB_THREEWAY].inthreeway
+			&& p1->subs[SUB_REAL].owner
+			&& p1->subs[SUB_REAL].inthreeway
+			&& ast_channel_state(p1->subs[SUB_REAL].owner) == AST_STATE_RINGING) {
+			ast_debug(1,
+				"Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
+				p0->channel, npc0->index, ast_channel_name(c0),
+				p1->channel, npc1->index, ast_channel_name(c1));
+			tone_zone_play_tone(p0->subs[npc0->index].dfd, DAHDI_TONE_RINGTONE);
+			npc1->state = ast_channel_state(p1->subs[SUB_REAL].owner);
+		} else {
+			ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
+				p0->channel, npc0->index, ast_channel_name(c0),
+				p1->channel, npc1->index, ast_channel_name(c1));
+			tone_zone_play_tone(p0->subs[npc0->index].dfd, -1);
+		}
+
+		if (npc0->index == SUB_THREEWAY
+			&& p0->subs[SUB_THREEWAY].inthreeway
+			&& p0->subs[SUB_REAL].owner
+			&& p0->subs[SUB_REAL].inthreeway
+			&& ast_channel_state(p0->subs[SUB_REAL].owner) == AST_STATE_RINGING) {
+			ast_debug(1,
+				"Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
+				p1->channel, npc1->index, ast_channel_name(c1),
+				p0->channel, npc0->index, ast_channel_name(c0));
+			tone_zone_play_tone(p1->subs[npc1->index].dfd, DAHDI_TONE_RINGTONE);
+			npc0->state = ast_channel_state(p0->subs[SUB_REAL].owner);
+		} else {
+			ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
+				p1->channel, npc1->index, ast_channel_name(c1),
+				p0->channel, npc0->index, ast_channel_name(c0));
+			tone_zone_play_tone(p1->subs[npc1->index].dfd, -1);
+		}
+
+		if (npc0->index == SUB_REAL && npc1->index == SUB_REAL) {
+			if (!p0->echocanbridged || !p1->echocanbridged) {
+				/* Disable echo cancellation if appropriate */
+				dahdi_disable_ec(p0);
+				dahdi_disable_ec(p1);
+			}
+		}
+		dahdi_link(slave, master);
+		master->inconference = inconf;
+	} else if (!nothing_ok) {
+		ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n",
+			p0->channel, subnames[npc0->index],
+			p1->channel, subnames[npc1->index]);
+	}
+	update_conf(p0);
+	update_conf(p1);
+
+	ast_channel_unlock(c0);
+	ast_channel_unlock(c1);
+
+	/* Native bridge failed */
+	if ((!master || !slave) && !nothing_ok) {
+		ast_mutex_unlock(&p0->lock);
+		ast_mutex_unlock(&p1->lock);
+		return -1;
+	}
+
+	if (npc0->index == SUB_REAL) {
+		disable_dtmf_detect(p0);
+	}
+	if (npc1->index == SUB_REAL) {
+		disable_dtmf_detect(p1);
+	}
+
+	ast_mutex_unlock(&p0->lock);
+	ast_mutex_unlock(&p1->lock);
+
+	tech_pvt = bridge->tech_pvt;
+	tech_pvt->master = master;
+	tech_pvt->slave = slave;
+
+	ast_verb(3, "Native bridging %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));
+
+#if defined(HAVE_PRI) && defined(PRI_2BCT)
+	if (!tech_pvt->tried_trombone_removal) {
+		tech_pvt->tried_trombone_removal = 1;
+
+		if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
+			q931_call *q931_c0;
+			q931_call *q931_c1;
+
+			/* Try to eliminate the tromboned call. */
+			ast_mutex_lock(&p0->pri->lock);
+			ast_assert(dahdi_sig_pri_lib_handles(p0->sig));
+			ast_assert(dahdi_sig_pri_lib_handles(p1->sig));
+			q931_c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
+			q931_c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
+			if (q931_c0 && q931_c1) {
+				pri_channel_bridge(q931_c0, q931_c1);
+			}
+			ast_mutex_unlock(&p0->pri->lock);
+		}
+	}
+#endif	/* defined(HAVE_PRI) && defined(PRI_2BCT) */
+	return 0;
 }
 
 /*!
@@ -243,33 +497,7 @@
 	if (native_start(bridge)) {
 		return;
 	}
-
-#if defined(HAVE_PRI) && defined(PRI_2BCT)
-	if (!tech_pvt->tried_trombone_removal) {
-		struct dahdi_pvt *master;
-		struct dahdi_pvt *slave;
-
-		tech_pvt->tried_trombone_removal = 1;
-
-		master = tech_pvt->master;
-		slave = tech_pvt->slave;
-		if (master->pri && master->pri == slave->pri && master->pri->transfer) {
-			q931_call *q931_master;
-			q931_call *q931_slave;
-
-			/* Try to eliminate the tromboned call. */
-			ast_mutex_lock(&master->pri->lock);
-			ast_assert(dahdi_sig_pri_lib_handles(master->sig));
-			ast_assert(dahdi_sig_pri_lib_handles(slave->sig));
-			q931_master = ((struct sig_pri_chan *) (master->sig_pvt))->call;
-			q931_slave = ((struct sig_pri_chan *) (slave->sig_pvt))->call;
-			if (q931_master && q931_slave) {
-				pri_channel_bridge(q931_master, q931_slave);
-			}
-			ast_mutex_unlock(&master->pri->lock);
-		}
-	}
-#endif	/* defined(HAVE_PRI) && defined(PRI_2BCT) */
+	tech_pvt->connected = 1;
 }
 
 /*!




More information about the asterisk-commits mailing list