[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