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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Sep 24 17:19:47 CDT 2009


Author: moy
Date: Thu Sep 24 17:19:42 2009
New Revision: 220416

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=220416
Log:
include callerid and other information in the created channels

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=220416&r1=220415&r2=220416
==============================================================================
--- team/moy/dahdi-tap-1.6.2/channels/chan_dahdi.c (original)
+++ team/moy/dahdi-tap-1.6.2/channels/chan_dahdi.c Thu Sep 24 17:19:42 2009
@@ -505,6 +505,16 @@
 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
 
+/* Passive call structure.
+ * As of now just valid for pri but eventually may be reused for other protocols with monitoring support */
+struct dahdi_pcall {
+	void *callref;
+	char callingnum[AST_MAX_EXTENSION];
+	char callingani[AST_MAX_EXTENSION];
+	char callingname[AST_MAX_EXTENSION];
+	char callednum[AST_MAX_EXTENSION];
+};
+
 struct dahdi_pri {
 	pthread_t master;						/*!< Thread of master */
 	ast_mutex_t lock;						/*!< Mutex */
@@ -555,9 +565,11 @@
 	int sig;
 	/*! \brief Whether this is a passive PRI (just sniffing/monitoring) */
 	int passive;
+	/* TODO: allocate this structures on demand only when the pri is flagged as passive */
+	struct dahdi_pcall pcalls[MAX_CHANNELS];		        /*!< Passive calls if any.*/
 	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 */
+	struct dahdi_pvt *crvend;					/*!< Pointer to end of CRV structs */
 };
 
 
@@ -12368,9 +12380,9 @@
 	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);
+	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 of PRI channels %s and %s\n", binfo->chan->name, binfo->chan->name);
+	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);
@@ -12387,143 +12399,279 @@
 
 	binfo = ast_calloc(1, sizeof(*binfo));
 	if (!binfo) {
-		ast_log(LOG_WARNING, "Failed to create PRI bridge info structure\n");
+		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_WARNING, "Failed to create PRI bridge thread\n");
+		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)
+{
+	int i;
+	for (i = 0; i < ARRAY_LEN(pri->pcalls); i++) {
+		if (callref == pri->pcalls[i].callref) {
+			return &pri->pcalls[i];
+		}
+	}
+	return NULL;
+}
+
+static struct dahdi_pcall *pri_get_crv_pcall(struct dahdi_pri *pri, int crv)
+{
+	int i;
+	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) {
+			return &pri->pcalls[i];
+		}
+	}
+	return NULL;
+}
+
+static void pri_put_pcall(struct dahdi_pri *pri, void *callref)
+{
+	int i;
+	for (i = 0; i < ARRAY_LEN(pri->pcalls); i++) {
+		if (callref == pri->pcalls[i].callref) {
+			memset(&pri->pcalls[i], 0, sizeof(pri->pcalls[0]));
+		}
+	}
+}
+
 static void handle_pri_passive_event(struct dahdi_pri *pri, pri_event *e)
 {
-	int chanpos;
+	int chanpos, peerpos, law, layer1, transcap, res;
+	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);
 	if (!peerpri) {
-		ast_log(LOG_WARNING, "Ignoring passive PRI event on span %d, no peer span found!\n", pri->span);
+		ast_log(LOG_ERROR, "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);
+		ast_log(LOG_DEBUG, "Ring on channel %d of span %d\n", e->ring.channel, pri->span);
+		/* 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);
+		if (!pcall) {
+			ast_log(LOG_ERROR, "Failed to get a free PRI passive call slot, this is a bug!\n");
+			break;
+		}
+		pcall->callref = e->ring.call;
+		ast_copy_string(pcall->callingnum, e->ring.callingnum, sizeof(pcall->callingnum));
+		ast_copy_string(pcall->callingani, e->ring.callingani, sizeof(pcall->callingani));
+		ast_copy_string(pcall->callingname, e->ring.callingname, sizeof(pcall->callingname));
+		ast_copy_string(pcall->callednum, e->ring.callednum, sizeof(pcall->callednum));
 		break;
 
 	case PRI_EVENT_PROGRESS:
-		ast_log(LOG_NOTICE, "Progress on channel %d of span %d\n", e->proceeding.channel, pri->span);
+		ast_log(LOG_DEBUG, "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 */
+		ast_log(LOG_DEBUG, "Proceed 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 and can therefore proceed to setup the ast channels, but
+		 * only if a couple of call tests are passed */
+
+		/* check that the layer 1 and trans capability are supported 
+		 * we could have saved layer 1 and capability when receiving the PRI_EVENT_RING, but that requires maintaining 
+		 * those values somewhere until the PROCEEDING msg arrives, no point in doing so, better we ask libpri at this
+		 * point the right values since libpri keeps those values anyways. Note that even though PRI_TRANS_CAP_SPEECH
+		 * and AST_TRANS_CAP_SPEECH conveniently have the same value, we don't assume it
+		 * the settings of the call are in the peer call structure because we are the originating side, and therefore
+		 * we did not get a PRI_EVENT_RING event
+		 * */
+		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);
+			break;
+		}
+
+		/* check that we already know about this call in the peer PRI (which was the one receiving the PRI_EVENT_RING event) */
+		if (!(pcall = pri_get_crv_pcall(peerpri, pri_get_crv(pri->pri, e->proceeding.call, NULL)))) {
+			ast_log(LOG_ERROR, 
+				"BUG, we got proceeding in channel number %d/%d on span %d for call reference %d "
+				"but we never got PRI_EVENT_RING for that call on peer span %d?\n", 
+				PRI_SPAN(e->proceeding.channel), 
+				PRI_CHANNEL(e->proceeding.channel),
+				pri->span, e->proceeding.cref, peerpri->span);
+			break;
+		}
+		layer1 = pri_get_layer1(peerpri->pri, pcall->callref);
+		transcap = pri_get_transcap(peerpri->pri, pcall->callref);
+
+		if (PRI_LAYER_1_ULAW != layer1 && PRI_LAYER_1_ALAW != layer1) {
+			ast_log(LOG_NOTICE, "Not monitoring call with unsupported layer 1 format %d\n", layer1);
+			break;
+		}
+		if (transcap != PRI_TRANS_CAP_SPEECH) {
+			ast_log(LOG_NOTICE, "Not monitoring call with unsupported capability %d\n", transcap);
+			break;
+		}
+
 		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",
+			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;
 		}
-
-		/* 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);
+		pri->pvts[chanpos]->call = e->proceeding.call;
+
+		/* Set calling and called 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
+		if (!ast_strlen_zero(pcall->callingani)) {
+			ast_copy_string(pri->pvts[chanpos]->cid_ani, pcall->callingani, sizeof(pri->pvts[chanpos]->cid_ani));
+			ast_shrink_phone_number(pri->pvts[chanpos]->cid_ani);
+		} else {
+			pri->pvts[chanpos]->cid_ani[0] = '\0';
+		}
+#endif
+		ast_copy_string(pri->pvts[chanpos]->cid_name, pcall->callingname, sizeof(pri->pvts[chanpos]->cid_name));
+
+		if (!ast_strlen_zero(pcall->callednum)) {
+			ast_copy_string(pri->pvts[chanpos]->exten, pcall->callednum, sizeof(pri->pvts[chanpos]->exten));
+			ast_copy_string(pri->pvts[chanpos]->dnid, pcall->callednum, sizeof(pri->pvts[chanpos]->dnid));
+		} else if (pri->overlapdial)
+			pri->pvts[chanpos]->exten[0] = '\0';
+		else {
+			/* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
+			pri->pvts[chanpos]->exten[0] = 's';
+			pri->pvts[chanpos]->exten[1] = '\0';
+		}
+
+		/* Set DNID on all incoming calls -- even immediate */
+		if (!ast_strlen_zero(pcall->callednum)) {
+			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 */
+		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);
 		if (!c) {
-			ast_log(LOG_WARNING, "Failed to create channel for call on channel %d/%d on span %d\n",
+			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);
+		}
+		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);
+		}
+		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));
+		}
 		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;
-		}
+		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 */
 		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",
+			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);
 			break;
 		}
-		peerpri->pvts[chanpos]->owner = c;
+		peerpri->pvts[peerpos]->owner = c;
+		ast_log(LOG_DEBUG, "Set owner %s on peer span %d pos %d\n", c->name, peerpri->span, chanpos);
 		
 		break;
 
 	case PRI_EVENT_ANSWER:
-		ast_log(LOG_NOTICE, "Answer on channel %d of span %d\n", e->proceeding.channel, pri->span);
+		ast_log(LOG_DEBUG, "Answer on channel %d of span %d\n", e->proceeding.channel, pri->span);
+
+		/* get the chan pos for the answered channel and check we have an owner already */
 		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",
+		if (chanpos < 0) {
+			ast_log(LOG_ERROR, "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;
 		}
-		if (chanpos < 0) {
-			ast_log(LOG_WARNING, "Answer requested on odd/unavailable channel number %d/%d on span %d\n",
+
+		if (!pri->pvts[chanpos]->owner) {
+			ast_log(LOG_ERROR, "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;
 		}
+
+		/* save the owner and set its state as UP */
 		c = pri->pvts[chanpos]->owner;
 		ast_setstate(c, AST_STATE_UP);
 		
-		/* Now launch the monitor in the first channel */
+		/* Now launch the monitor in the answered 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",
+			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;
 		}
-
-		snprintf(mixfilename, sizeof(mixfilename), "dahdi-tap-span-%d-chan-%d.ulaw", pri->span, PRI_CHANNEL(e->answer.channel));
+		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.wav", 
+			datestr, pri->span, PRI_CHANNEL(e->answer.channel));
 		mixfilename[sizeof(mixfilename)-1] = '\0';
 		if (pbx_exec(pri->pvts[chanpos]->owner, app, mixfilename)) {
-			ast_log(LOG_WARNING, "Failed to launch mix monitor in channel number %d/%d on span %d\n",
+			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 (!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;
 		}
+
+		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 bridge them in their own thread */
+		/* Now put both channels in a bridge in their own thread, MixMonitor is taking care of the rest */
 		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",
+			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;
 		}
 		if (!pri->pvts[chanpos]->owner) {
-			ast_log(LOG_WARNING, "No owner on hangup in channel number %d/%d on span %d\n",
+			ast_log(LOG_ERROR, "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;
 		}
@@ -12531,27 +12679,116 @@
 
 		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",
+			ast_log(LOG_ERROR, "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",
+			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);
+		/* put back the passive call slot, if any was used */
+		pri_put_pcall(pri, e->hangup.call);
 		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_passive_dchannel(void *vpri)
+{
+	struct dahdi_pri *pri = vpri;
+	pri_event *e;
+	struct pollfd fds[NUM_DCHANS];
+	int res, x, i, numdchans, which;
+
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+
+	for (;;) {
+		for (i = 0; i < NUM_DCHANS; i++) {
+			if (!pri->dchannels[i])
+				break;
+			fds[i].fd = pri->fds[i];
+			fds[i].events = POLLIN | POLLPRI;
+			fds[i].revents = 0;
+		}
+		numdchans = i;
+
+		pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+		pthread_testcancel();
+		e = NULL;
+		res = poll(fds, numdchans, -1);
+		pthread_testcancel();
+		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+
+		if (res == -1 && errno != EINTR) {
+			ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
+			break;
+		} else if (res == -1) {
+			ast_log(LOG_DEBUG, "pri_event got EINT, continuing ...\n");
+			continue;
+		}
+
+		ast_mutex_lock(&pri->lock);
+		for (which = 0; which < NUM_DCHANS; which++) {
+			if (!pri->dchans[which]) {
+				break;
+			}
+
+			if (fds[which].revents & POLLPRI) {
+				/* Check for an event */
+				x = 0;
+				res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
+				if (x) {
+					ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
+					manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
+						"PRIEvent: %s\r\n"
+						"PRIEventCode: %d\r\n"
+						"D-channel: %s\r\n"
+						"Span: %d\r\n",
+						event2str(x),
+						x,
+						pri_order(which),
+						pri->span
+						);
+				}
+				/* Keep track of alarm state */
+				if (x == DAHDI_EVENT_ALARM) {
+					pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
+					pri_find_dchan(pri);
+				} else if (x == DAHDI_EVENT_NOALARM) {
+					pri->dchanavail[which] |= DCHAN_NOTINALARM;
+					pri_restart(pri->dchans[which]);
+				}
+
+				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) {
+				e = pri_read_event(pri->dchans[which]);
+				if (e && pri->debug) {
+					pri_dump_event(pri->dchans[which], e);
+				}
+				if (e) {
+					handle_pri_passive_event(pri, e);
+				}
+			}
+		}
+		ast_mutex_unlock(&pri->lock);
+	}
+	ast_log(LOG_NOTICE, "Finishing passive PRI loop for span %d\n", pri->span);
+	return NULL;
 }
 
 static void *pri_dchannel(void *vpri)
@@ -12760,15 +12997,7 @@
 
 					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) {
-					if (!pri->passive) {
-						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;
-						}
-					}
+					e = pri_check_event(pri->dchans[which]);
 				}
 				if (e)
 					break;
@@ -13783,7 +14012,7 @@
 	/* Assume primary is the one we use */
 	pri->pri = pri->dchans[0];
 	pri->resetpos = -1;
-	if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
+	if (ast_pthread_create_background(&pri->master, NULL, !pri->passive ? pri_dchannel : pri_passive_dchannel, pri)) {
 		for (i = 0; i < NUM_DCHANS; i++) {
 			if (!pri->dchannels[i])
 				break;




More information about the asterisk-commits mailing list