[asterisk-commits] moy: branch moy/dahdi-tap-1.6.2 r220582 - /team/moy/dahdi-tap-1.6.2/channels/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Sep 25 20:13:13 CDT 2009


Author: moy
Date: Fri Sep 25 20:13:09 2009
New Revision: 220582

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=220582
Log:
create just 1 ast_channel per call and send it to the pbx instead of hard-coding the call to MixMonitor

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=220582&r1=220581&r2=220582
==============================================================================
--- team/moy/dahdi-tap-1.6.2/channels/chan_dahdi.c (original)
+++ team/moy/dahdi-tap-1.6.2/channels/chan_dahdi.c Fri Sep 25 20:13:09 2009
@@ -106,8 +106,6 @@
 #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">
@@ -570,6 +568,7 @@
 #define MAX_FORMAT_EXTEN 10
 #define DEFAULT_RECORDING_EXTEN "wav49"
 	char passiverecordexten[MAX_FORMAT_EXTEN];                         /*!< Record format extension */
+	struct dahdi_pri *passivepeer;                                  /*!< Peer PRI structure in passive mode */
 	struct dahdi_pvt *pvts[MAX_CHANNELS];				/*!< Member channel pvt structs */
 	struct dahdi_pvt *crvs;						/*!< Member CRV structs */
 	struct dahdi_pvt *crvend;					/*!< Pointer to end of CRV structs */
@@ -1190,6 +1189,10 @@
 	int prioffset;
 	/*! \brief Logical span number within trunk group */
 	int logicalspan;
+	/*!< Passive peer pvt we're related to, if any */
+	struct dahdi_pvt *passivepeer;
+	int passiveconf;
+	int passivefd;
 #endif
 	/*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
 	int polarity;
@@ -4149,17 +4152,6 @@
 #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;
@@ -4359,6 +4351,17 @@
 	}
 
 	x = 0;
+	if (p->passivefd != -1) {
+		struct dahdi_confinfo pinfo;
+		memset(&pinfo, 0, sizeof(pinfo));
+		ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF);
+		memset(&pinfo, 0, sizeof(pinfo));
+		ioctl(p->passivepeer->subs[SUB_REAL].dfd, DAHDI_SETCONF);
+		memset(&pinfo, 0, sizeof(pinfo));
+		ioctl(p->passivefd, DAHDI_SETCONF);
+		dahdi_close(p->passivefd);
+		p->passivefd = -1;
+	}
 	dahdi_confmute(p, 0);
 	p->muting = 0;
 	restore_gains(p);
@@ -6909,30 +6912,44 @@
 	}
 	readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
 	CHECK_BLOCKING(ast);
-	res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
+#define CHECK_READ_RESULT(res) \
+	if (res < 0) { \
+		f = NULL; \
+		if (res == -1) { \
+			if (errno == EAGAIN) { \
+				ast_mutex_unlock(&p->lock); \
+				return &p->subs[idx].f; \
+			} else if (errno == ELAST) { \
+				f = __dahdi_exception(ast); \
+			} else { \
+				ast_log(LOG_WARNING, "dahdi_read: %s\n", strerror(errno)); \
+			} \
+		} \
+		ast_mutex_unlock(&p->lock); \
+		return f; \
+	} \
+	if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { \
+		ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); \
+		f = __dahdi_exception(ast); \
+		ast_mutex_unlock(&p->lock); \
+		return f; \
+	}
+	if (p->passivefd == -1) {
+		/* do normal reading */
+		res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
+	} else {
+		/* passive channel reading */
+		/* first read from the 2 involved dahdi channels just to consume their frames */
+		res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
+		CHECK_READ_RESULT(res);
+		res = read(p->passivepeer->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
+		CHECK_READ_RESULT(res);
+		/* now read the mixed audio that will be returned to the core */
+		res = read(p->passivefd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
+	}
 	ast_clear_flag(ast, AST_FLAG_BLOCKING);
 	/* Check for hangup */
-	if (res < 0) {
-		f = NULL;
-		if (res == -1) {
-			if (errno == EAGAIN) {
-				/* Return "NULL" frame if there is nobody there */
-				ast_mutex_unlock(&p->lock);
-				return &p->subs[idx].f;
-			} else if (errno == ELAST) {
-				f = __dahdi_exception(ast);
-			} else
-				ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
-		}
-		ast_mutex_unlock(&p->lock);
-		return f;
-	}
-	if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
-		ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
-		f = __dahdi_exception(ast);
-		ast_mutex_unlock(&p->lock);
-		return f;
-	}
+	CHECK_READ_RESULT(res);
 	if (p->tdd) { /* if in TDD mode, see if we receive that */
 		int c;
 
@@ -7111,6 +7128,10 @@
 	if (idx < 0) {
 		ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
 		return -1;
+	}
+
+	if (p->passivepeer) {
+		return 0;
 	}
 
 #if 0
@@ -10293,6 +10314,8 @@
 						tmp->pri = &pris[span];
 						tmp->prioffset = offset;
 						tmp->call = NULL;
+						tmp->passiveconf = 0;
+						tmp->passivefd = -1;
 					} else {
 						ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
 						destroy_dahdi_pvt(&tmp);
@@ -12377,50 +12400,6 @@
 #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 passive 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 passive 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_ERROR, "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_ERROR, "Failed to create PRI bridge thread\n");
-		return;
-	}
-
-	pthread_attr_destroy(&attr);
-}
-
 /* Not thread-safe, we assume nobody else is looking for a passive call slot at the same time in this pri */
 static struct dahdi_pcall *pri_get_pcall(struct dahdi_pri *pri, void *callref)
 {
@@ -12436,8 +12415,10 @@
 static struct dahdi_pcall *pri_get_crv_pcall(struct dahdi_pri *pri, int crv)
 {
 	int i;
+	int tstcrv;
 	for (i = 0; i < ARRAY_LEN(pri->pcalls); i++) {
-		if (pri->pcalls[i].callref && pri_get_crv(pri->pri, pri->pcalls[i].callref, NULL) == crv) {
+		tstcrv = pri->pcalls[i].callref ? pri_get_crv(pri->pri, pri->pcalls[i].callref, NULL) : 0;
+		if (pri->pcalls[i].callref && tstcrv == crv) {
 			return &pri->pcalls[i];
 		}
 	}
@@ -12456,25 +12437,21 @@
 
 static void handle_pri_passive_event(struct dahdi_pri *pri, pri_event *e)
 {
-	int chanpos, peerpos, law, layer1, transcap, res;
+	int chanpos, peerpos, law, layer1, transcap, res, fd;
 	struct dahdi_pcall *pcall = NULL;
-	struct ast_app *app = NULL;
 	struct ast_channel *c = NULL;
-	struct ast_channel *peer  = NULL;
-	struct ast_tm tm;
-	struct timeval now;
-	char mixfilename[512];
-	char datestr[50];
-	int peerspan = !(pri->span % 2) ? (pri->span - 1) : (pri->span + 1);
-	struct dahdi_pri *peerpri = pri_find_by_span(peerspan);
+	struct dahdi_pri *peerpri = pri->passivepeer;
+	struct dahdi_confinfo dahdic = { 0, };
+
 	if (!peerpri) {
 		ast_log(LOG_ERROR, "Ignoring passive PRI event on span %d, no peer span found!\n", pri->span);
 		return;
 	}
+
 	switch (e->e) {
 
 	case PRI_EVENT_RING:
-		ast_log(LOG_DEBUG, "Ring on channel %d of span %d\n", e->ring.channel, pri->span);
+		ast_log(LOG_DEBUG, "Ring on channel %d of span %d with callref %d\n", e->ring.channel, pri->span, e->ring.cref);
 		/* we cannot use any pri->pvts data structure because we still dont know which channel will be used and therefore cant get
 		 * chanpos (ie, flexible channel was requested), thus, we need our own list of call references */
 		pcall = pri_get_pcall(pri, NULL);
@@ -12508,7 +12485,6 @@
 				pri->span, e->proceeding.cref, peerpri->span);
 			break;
 		}
-
 		/* check that the layer 1 and trans capability are supported */
 		layer1 = pri_get_layer1(peerpri->pri, pcall->callref);
 		transcap = pri_get_transcap(peerpri->pri, pcall->callref);
@@ -12522,15 +12498,26 @@
 			break;
 		}
 
+		/* check for valid channels in both the current span and the peer span */
 		chanpos = pri_find_principle(pri, e->proceeding.channel);
 		if (chanpos < 0) {
 			ast_log(LOG_ERROR, "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;
 		}
+
+		peerpos = pri_find_principle(peerpri, e->proceeding.channel);
+		if (peerpos < 0) {
+			ast_log(LOG_ERROR, "Proceeding requested on odd/unavailable peer channel number %d/%d on span %d\n",
+				PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
+			break;
+		}
+
+		/* save the call reference */
 		pri->pvts[chanpos]->call = e->proceeding.call;
-
-		/* Set calling and called information */
+		peerpri->pvts[peerpos]->call = e->proceeding.call;
+
+		/* Set calling and callee information */
 		ast_copy_string(pri->pvts[chanpos]->cid_num, pcall->callingnum, sizeof(pri->pvts[chanpos]->cid_num));
 		ast_shrink_phone_number(pri->pvts[chanpos]->cid_num);
 #ifdef PRI_ANI
@@ -12559,46 +12546,96 @@
 			ast_copy_string(pri->pvts[chanpos]->dnid, pcall->callednum, sizeof(pri->pvts[chanpos]->dnid));
 		}
 
-		/* create the actual ast_channel but dont start a pbx, all will be handled by us */
+		/* create the actual ast_channel but dont start a pbx just yet */
 		law = layer1 == PRI_LAYER_1_ULAW ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW;
-		c = dahdi_new(pri->pvts[chanpos], AST_STATE_RINGING, 0, SUB_REAL, law, AST_TRANS_CAP_SPEECH);
+		c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, AST_TRANS_CAP_SPEECH);
 		if (!c) {
 			ast_log(LOG_ERROR, "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;
 		}
+
 		res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
 		if (res < 0) {
-			ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
+			ast_log(LOG_WARNING, "Unable to set law on channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
 		}
 		res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
 		if (res < 0) {
-			ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
+			ast_log(LOG_WARNING, "Unable to set gains on channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
 		}
 		res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law);
 		if (res < 0) {
 			ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
 		}
+
+		res = dahdi_setlaw(peerpri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
+		if (res < 0) {
+			ast_log(LOG_WARNING, "Unable to set law on peer channel %d: %s\n", peerpri->pvts[chanpos]->channel, strerror(errno));
+		}
+		res = set_actual_gain(peerpri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, peerpri->pvts[chanpos]->rxgain, peerpri->pvts[chanpos]->txgain, law);
+		if (res < 0) {
+			ast_log(LOG_WARNING, "Unable to set gains on peer channel %d: %s\n", peerpri->pvts[chanpos]->channel, strerror(errno));
+		}
+		res = ioctl(peerpri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law);
+		if (res < 0) {
+			ast_log(LOG_WARNING, "Unable to set audio mode on peer channel %d to %d: %s\n", peerpri->pvts[chanpos]->channel, law, strerror(errno));
+		}
+
+		/* the owner for the peer channel will be the same, both dahdi pvt structures will share the owner,
+		 * however Asterisk core will only know about one pvt structure, any future read will be done through
+		 * the conference descriptor
+		 * */
 		pri->pvts[chanpos]->owner = c;
-		ast_log(LOG_DEBUG, "Set owner %s on span %d pos %d\n", c->name, pri->span, chanpos);
-
-		/* now setup the bridged peer, far more easy, no need to set any fields */
-		peerpos = pri_find_principle(peerpri, e->proceeding.channel);
-		if (peerpos < 0) {
-			ast_log(LOG_ERROR, "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);
+		pri->pvts[chanpos]->passivepeer = peerpri->pvts[peerpos];
+		peerpri->pvts[peerpos]->owner = c;
+		peerpri->pvts[peerpos]->passivepeer = pri->pvts[chanpos];
+
+		/* create the mixing conference 
+		 * some DAHDI_SETCONF interface rules to keep in mind
+		 * confno == -1 means create new conference with the given confmode
+		 * confno and confmode == 0 means remove the channel from its conference */
+		dahdic.chan = 0; /* means use current channel (the one the fd belongs to)*/
+		dahdic.confno = -1; /* -1 means create new conference */
+		dahdic.confmode = DAHDI_CONF_CONFMON | DAHDI_CONF_LISTENER | DAHDI_CONF_PSEUDO_LISTENER;
+		fd = dahdi_open("/dev/dahdi/pseudo");
+		/* TODO: what about setting DAHDI_POLICY_IMMEDIATE and buf size? DAHDI_SETLINEAR?? */
+		if (fd < 0 || ioctl(fd, DAHDI_SETCONF, &dahdic)) {
+			 ast_log(LOG_ERROR, "Unable to create dahdi conference for tapping\n");
+			 ast_hangup(c);
+			 break;
+		}
+		pri->pvts[chanpos]->passiveconf = dahdic.confno;
+		pri->pvts[chanpos]->passivefd = fd;
+
+		/* add both parties to the conference */
+		dahdic.chan = 0;
+		dahdic.confno = pri->pvts[chanpos]->passiveconf;
+		dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER;
+		if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_SETCONF, &dahdic)) {
+			ast_log(LOG_ERROR, "Unable to add chan to conference for tapping devices: %s\n", strerror(errno));
+			ast_hangup(c);
 			break;
 		}
-
-		c = dahdi_new(peerpri->pvts[chanpos], AST_STATE_RINGING, 0, SUB_REAL, law, AST_TRANS_CAP_SPEECH);
-		if (!c) {
-			ast_log(LOG_ERROR, "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);
+		dahdic.chan = 0;
+		dahdic.confno = pri->pvts[chanpos]->passiveconf;
+		dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER;
+		if (ioctl(peerpri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_SETCONF, &dahdic)) {
+			ast_log(LOG_ERROR, "Unable to add peer chan to conference for tapping devices: %s\n", strerror(errno));
+			ast_hangup(c);
 			break;
 		}
-		peerpri->pvts[peerpos]->owner = c;
-		ast_log(LOG_DEBUG, "Set owner %s on peer span %d pos %d\n", c->name, peerpri->span, chanpos);
-		
+		ast_log(LOG_DEBUG, "Created conference %d with fd %d between dahdi chans %d and %d for ast channel %s\n", 
+				pri->pvts[chanpos]->passiveconf,
+				pri->pvts[chanpos]->passivefd,
+		      		pri->pvts[chanpos]->channel,
+		      		peerpri->pvts[peerpos]->channel,
+				c->name);
+
+		/* from now on, reading from the conference has the mix of both tapped channels, we can now launch the pbx thread */
+		if (ast_pbx_start(c) != AST_PBX_SUCCESS) {
+			ast_log(LOG_ERROR, "Failed to launch PBX thread for passive channel %s\n", c->name);
+			ast_hangup(c);
+		}
 		break;
 
 	case PRI_EVENT_ANSWER:
@@ -12613,67 +12650,37 @@
 		}
 
 		if (!pri->pvts[chanpos]->owner) {
-			ast_log(LOG_ERROR, "No owner on answer in channel number %d/%d on span %d\n",
+			/* this may be a valid condition if the user hangup the ast channel before the tapped line is answered */
+			ast_log(LOG_NOTICE, "Ignoring answer in tapped channel number %d/%d on span %d, no owner found\n",
 				PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
 			break;
 		}
 
-		/* save the owner and set its state as UP */
+		/* set the owner state as UP */
 		c = pri->pvts[chanpos]->owner;
-		ast_setstate(c, AST_STATE_UP);
-		
-		/* Now launch the monitor in the answered channel */
-		app = pbx_findapp("MixMonitor");
-		if (!app) {
-			ast_log(LOG_ERROR, "Failed to find MixMonitor application to record audio for channel number %d/%d on span %d\n",
-				PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
-			break;
-		}
-		now = ast_tvnow();	
-		ast_localtime(&now, &tm, NULL);
-		ast_strftime(datestr, sizeof(datestr), "%F-%H-%M-%S", &tm);
-		snprintf(mixfilename, sizeof(mixfilename), "dahdi-tap-%s-span-%d-chan-%d-mix.%s", 
-			datestr, pri->span, PRI_CHANNEL(e->answer.channel), pri->passiverecordexten);
-		mixfilename[sizeof(mixfilename)-1] = '\0';
-		if (pbx_exec(pri->pvts[chanpos]->owner, app, mixfilename)) {
-			ast_log(LOG_ERROR, "Failed to launch MixMonitor application to record audio for channel number %d/%d on span %d\n",
-				PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
-			break;
-		}
-
-		/* now get the peer channel and verify its owner */
-		chanpos = pri_find_principle(peerpri, e->answer.channel);
-		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;
-		}
-
-		if (!peerpri->pvts[chanpos]->owner) {
-			ast_log(LOG_WARNING, "No peer 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;
-		}
-
-		/* save the peer and set its state as UP */
-		peer = peerpri->pvts[chanpos]->owner;
-		ast_setstate(peer, AST_STATE_UP);
-
-		/* Now put both channels in a bridge in their own thread, MixMonitor is taking care of the rest */
-		launch_pri_bridge_thread(c, peer);
+		ast_channel_lock(c);
+		if (c->_state == AST_STATE_RING) {
+			ast_setstate(c, AST_STATE_UP);
+		}
+		ast_channel_unlock(c);
 		break;
 
 	case PRI_EVENT_HANGUP:
 
-		ast_log(LOG_NOTICE, "Hangup on channel %d of span %d\n", e->hangup.channel, pri->span);
+		ast_log(LOG_DEBUG, "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_ERROR, "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;
 		}
+		/* first put back the passive call slot, if any was used, since 
+		 * regardless of whethere there is owner or not, this resource must be freed */
+		pri_put_pcall(pri, e->hangup.call);
+
 		if (!pri->pvts[chanpos]->owner) {
-			ast_log(LOG_ERROR, "No owner on hangup in channel number %d/%d on span %d\n",
+			/* this may be a valid condition if the user hangup the ast channel before the tapped line is terminated */
+			ast_log(LOG_NOTICE, "Ignoring hangup in tapped channel number %d/%d on span %d, no owner found\n",
 				PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
 			break;
 		}
@@ -12687,19 +12694,18 @@
 		}
 
 		if (!peerpri->pvts[chanpos]->owner) {
-			ast_log(LOG_ERROR, "No owner on hangup in channel number %d/%d on peer span %d\n",
+			/* invalid, since the owner is the same for both pvts, the owner should be here too */
+			ast_log(LOG_ERROR, "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);
 
-		/* put back the passive call slot, if any was used */
-		pri_put_pcall(pri, e->hangup.call);
 		break;
 
 	case PRI_EVENT_HANGUP_ACK:
 
-		ast_log(LOG_NOTICE, "Hangup ack on channel %d of span %d\n", e->hangup.channel, pri->span);
+		ast_log(LOG_DEBUG, "Hangup ack on channel %d of span %d\n", e->hangup.channel, pri->span);
 		/* put back the passive call slot, if any was used */
 		pri_put_pcall(pri, e->hangup.call);
 		break;
@@ -17658,6 +17664,10 @@
 		int x;
 		for (x = 0; x < NUM_SPANS; x++) {
 			if (pris[x].pvts[0]) {
+				if (pris[x].passive) {
+					int peerspan = !(x % 2) ? (x + 1) : (x - 1);
+					pris[x].passivepeer = &pris[peerspan];
+				}
 				if (start_pri(pris + x)) {
 					ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
 					return -1;




More information about the asterisk-commits mailing list