[svn-commits] moy: branch moy/dahdi-tap-1.6.2 r219809 - /team/moy/dahdi-tap-1.6.2/channels/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Sep 22 11:52:09 CDT 2009


Author: moy
Date: Tue Sep 22 11:52:05 2009
New Revision: 219809

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=219809
Log:
inital code to record calls on tapped PRI links

Modified:
    team/moy/dahdi-tap-1.6.2/channels/chan_dahdi.c

Modified: team/moy/dahdi-tap-1.6.2/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/moy/dahdi-tap-1.6.2/channels/chan_dahdi.c?view=diff&rev=219809&r1=219808&r2=219809
==============================================================================
--- team/moy/dahdi-tap-1.6.2/channels/chan_dahdi.c (original)
+++ team/moy/dahdi-tap-1.6.2/channels/chan_dahdi.c Tue Sep 22 11:52:05 2009
@@ -106,6 +106,8 @@
 #include "asterisk/event.h"
 #include "asterisk/devicestate.h"
 #include "asterisk/paths.h"
+#include "asterisk/pbx.h"
+#include "asterisk/features.h"
 
 /*** DOCUMENTATION
 	<application name="DAHDISendKeypadFacility" language="en_US">
@@ -4130,6 +4132,17 @@
 #endif	/* defined(HAVE_PRI) */
 
 #if defined(HAVE_PRI)
+static struct dahdi_pri *pri_find_by_span(int span)
+{
+	int x;
+	for (x = 0; x < NUM_SPANS; x++) {
+		if (pris[x].span == span) {
+			return &pris[x];
+		}
+	}
+	return NULL;
+}
+
 static int pri_find_dchan(struct dahdi_pri *pri)
 {
 	int oldslot = -1;
@@ -12341,6 +12354,199 @@
 #endif	/* defined(HAVE_PRI) */
 
 #if defined(HAVE_PRI)
+struct dahdi_pri_bridge_info
+{
+	struct ast_channel *chan;
+	struct ast_channel *peer;
+};
+
+static void *pri_bridge_call(void *args)
+{
+	struct ast_bridge_config bconfig = { { 0, }, };
+	int ret = 0;
+	struct dahdi_pri_bridge_info *binfo = args;
+	ast_log(LOG_NOTICE, "Bridging PRI channels %s and %s\n", binfo->chan->name, binfo->peer->name);
+	ret = ast_bridge_call(binfo->chan, binfo->peer, &bconfig);
+	ast_log(LOG_NOTICE, "Done Bridging of PRI channels %s and %s\n", binfo->chan->name, binfo->chan->name);
+	ast_hangup(binfo->chan);
+	ast_hangup(binfo->peer);
+	ast_free(binfo);
+	return NULL;
+}
+
+static void launch_pri_bridge_thread(struct ast_channel *c1, struct ast_channel *c2)
+{
+	struct dahdi_pri_bridge_info *binfo = NULL;
+	pthread_t thread;
+	pthread_attr_t attr;
+	pthread_attr_init(&attr);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+	binfo = ast_calloc(1, sizeof(*binfo));
+	if (!binfo) {
+		ast_log(LOG_WARNING, "Failed to create PRI bridge info structure\n");
+		return;
+	}
+
+	binfo->chan = c1;
+	binfo->peer = c2;
+	if (ast_pthread_create_background(&thread, &attr, pri_bridge_call, binfo)) {
+		ast_log(LOG_WARNING, "Failed to create PRI bridge thread\n");
+		return;
+	}
+
+	pthread_attr_destroy(&attr);
+}
+
+static void handle_pri_passive_event(struct dahdi_pri *pri, pri_event *e)
+{
+	int chanpos;
+	struct ast_app *app = NULL;
+	struct ast_channel *c = NULL;
+	struct ast_channel *peer  = NULL;
+	int peerspan = !(pri->span % 2) ? (pri->span - 1) : (pri->span + 1);
+	struct dahdi_pri *peerpri = pri_find_by_span(peerspan);
+	if (!peerpri) {
+		ast_log(LOG_WARNING, "Ignoring passive PRI event on span %d, no peer span found\n", pri->span);
+		return;
+	}
+	/* XXX TODO: chanpos is calculated for both pri and peerpri, is it needed or will it be always the same chanpos for both? XXX */
+	switch (e->e) {
+
+	case PRI_EVENT_RING:
+		ast_log(LOG_NOTICE, "Ring on channel %d of span %d\n", e->ring.channel, pri->span);
+		break;
+
+	case PRI_EVENT_PROGRESS:
+		ast_log(LOG_NOTICE, "Progress on channel %d of span %d\n", e->proceeding.channel, pri->span);
+		break;
+
+	case PRI_EVENT_PROCEEDING:
+		ast_log(LOG_NOTICE, "Proceeding on channel %d of span %d\n", e->proceeding.channel, pri->span);
+		/* at this point we should know the real b chan that will be used */
+		chanpos = pri_find_principle(pri, e->proceeding.channel);
+		if (chanpos < 0) {
+			ast_log(LOG_WARNING, "Proceeding requested on odd/unavailable channel number %d/%d on span %d\n",
+				PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
+			break;
+		}
+
+		/* XXX FIXME: Law must be taken from PRI_EVENT_RING, I think, the same for capabilities XXX */
+		c = dahdi_new(pri->pvts[chanpos], AST_STATE_RINGING, 0, SUB_REAL, DAHDI_LAW_MULAW, AST_TRANS_CAP_SPEECH);
+		if (!c) {
+			ast_log(LOG_WARNING, "Failed to create channel for call on channel %d/%d on span %d\n",
+				PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
+			break;
+		}
+		pri->pvts[chanpos]->owner = c;
+
+		/* now get the bridged peer pvt */
+		chanpos = pri_find_principle(peerpri, e->proceeding.channel);
+		if (chanpos < 0) {
+			ast_log(LOG_WARNING, "Proceeding requested on odd/unavailable channel number %d/%d on peer span %d\n",
+				PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), peerpri->span);
+			break;
+		}
+		c = dahdi_new(peerpri->pvts[chanpos], AST_STATE_RINGING, 0, SUB_REAL, DAHDI_LAW_MULAW, AST_TRANS_CAP_SPEECH);
+		if (!c) {
+			ast_log(LOG_WARNING, "Failed to create channel for call on channel %d/%d on peer span %d\n",
+				PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), peerpri->span);
+			break;
+		}
+		peerpri->pvts[chanpos]->owner = c;
+		
+		break;
+
+	case PRI_EVENT_ANSWER:
+		ast_log(LOG_NOTICE, "Answer on channel %d of span %d\n", e->proceeding.channel, pri->span);
+		chanpos = pri_find_principle(pri, e->answer.channel);
+		if (!pri->pvts[chanpos]->owner) {
+			ast_log(LOG_WARNING, "No owner on answer in channel number %d/%d on span %d\n",
+				PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
+			break;
+		}
+		if (chanpos < 0) {
+			ast_log(LOG_WARNING, "Answer requested on odd/unavailable channel number %d/%d on span %d\n",
+				PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
+			break;
+		}
+		c = pri->pvts[chanpos]->owner;
+		ast_setstate(c, AST_STATE_UP);
+		
+		/* Now launch the monitor in the first channel */
+		app = pbx_findapp("MixMonitor");
+		if (!app) {
+			ast_log(LOG_WARNING, "Failed to find mix monitor application for channel number %d/%d on span %d\n",
+				PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
+			break;
+		}
+		if (pbx_exec(pri->pvts[chanpos]->owner, app, "/tmp/sangoma_monitor.ulaw")) {
+			ast_log(LOG_WARNING, "Failed to launch mix monitor in channel number %d/%d on span %d\n",
+				PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
+			break;
+		}
+
+		chanpos = pri_find_principle(peerpri, e->answer.channel);
+		if (!peerpri->pvts[chanpos]->owner) {
+			ast_log(LOG_WARNING, "No owner on answer in channel number %d/%d on peer span %d\n",
+				PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), peerpri->span);
+			break;
+		}
+		if (chanpos < 0) {
+			ast_log(LOG_WARNING, "Answer requested on odd/unavailable channel number %d/%d on peer span %d\n",
+				PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
+			break;
+		}
+		peer = peerpri->pvts[chanpos]->owner;
+		ast_setstate(peer, AST_STATE_UP);
+
+
+		/* Now bridge them in their own thread */
+		launch_pri_bridge_thread(c, peer);
+		break;
+
+	case PRI_EVENT_HANGUP:
+		/* XXX TODO: Verify how the interal pri call struct will be freed XXX */
+
+		ast_log(LOG_NOTICE, "Hangup on channel %d of span %d\n", e->hangup.channel, pri->span);
+		chanpos = pri_find_principle(pri, e->hangup.channel);
+		if (chanpos < 0) {
+			ast_log(LOG_WARNING, "Hangup requested on odd/unavailable channel number %d/%d on span %d\n",
+				PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+			break;
+		}
+		if (!pri->pvts[chanpos]->owner) {
+			ast_log(LOG_WARNING, "No owner on hangup in channel number %d/%d on span %d\n",
+				PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+			break;
+		}
+		ast_queue_hangup(pri->pvts[chanpos]->owner);
+
+		chanpos = pri_find_principle(peerpri, e->hangup.channel);
+		if (chanpos < 0) {
+			ast_log(LOG_WARNING, "Hangup requested on odd/unavailable channel number %d/%d on peer span %d\n",
+				PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), peerpri->span);
+			break;
+		}
+
+		if (!peerpri->pvts[chanpos]->owner) {
+			ast_log(LOG_WARNING, "No owner on hangup in channel number %d/%d on peer span %d\n",
+				PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), peerpri->span);
+			break;
+		}
+		ast_queue_hangup(peerpri->pvts[chanpos]->owner);
+		break;
+
+	case PRI_EVENT_HANGUP_ACK:
+		ast_log(LOG_NOTICE, "Hangup ack on channel %d of span %d\n", e->hangup.channel, pri->span);
+		break;
+
+	default:
+		ast_log(LOG_NOTICE, "Ignoring passive event %s on span %d\n", pri_event2str(e->gen.e), pri->span);
+		break;
+	}
+}
+
 static void *pri_dchannel(void *vpri)
 {
 	struct dahdi_pri *pri = vpri;
@@ -12547,7 +12753,15 @@
 
 					ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
 				} else if (fds[which].revents & POLLIN) {
+#ifdef CHAN_DAHDI_NORMAL
 					e = pri_check_event(pri->dchans[which]);
+#else
+					e = pri_read_event(pri->dchans[which]);
+					if (e) {
+						handle_pri_passive_event(pri, e);
+						e = NULL;
+					}
+#endif
 				}
 				if (e)
 					break;




More information about the svn-commits mailing list