[asterisk-commits] moy: branch moy/dahdi-tap-trunk r221688 - /team/moy/dahdi-tap-trunk/channels/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Oct 1 13:01:23 CDT 2009


Author: moy
Date: Thu Oct  1 13:01:19 2009
New Revision: 221688

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=221688
Log:
do proper locking of pvt structures

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

Modified: team/moy/dahdi-tap-trunk/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/moy/dahdi-tap-trunk/channels/chan_dahdi.c?view=diff&rev=221688&r1=221687&r2=221688
==============================================================================
--- team/moy/dahdi-tap-trunk/channels/chan_dahdi.c (original)
+++ team/moy/dahdi-tap-trunk/channels/chan_dahdi.c Thu Oct  1 13:01:19 2009
@@ -5202,6 +5202,7 @@
 	if (p->tappingpeer) {
 		struct dahdi_confinfo pinfo;
 		struct dahdi_pvt *pp = p->tappingpeer;
+		ast_log(LOG_DEBUG, "Cleaning up tapping conference and tapping peer\n");
 
 		/* remove pvt from the conference */
 		memset(&pinfo, 0, sizeof(pinfo));
@@ -5216,6 +5217,7 @@
 		ioctl(p->tappingfd, DAHDI_SETCONF);
 		dahdi_close(p->tappingfd);
 
+#ifdef HAVE_PRI
 		/* if its PRI reset data mode for the peer channel */
 		if (dahdi_sig_pri_lib_handles(p->sig)) {
 			int paudio = 1;
@@ -5223,6 +5225,7 @@
 				ast_log(LOG_WARNING, "Unable to set data mode on peer channel %d: %s\n", pp->channel, strerror(errno));
 			}
 		}
+#endif
 		p->tappingfd = -1;
 		p->tappingpeer = NULL;
 		pp->tappingpeer = NULL;

Modified: team/moy/dahdi-tap-trunk/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/moy/dahdi-tap-trunk/channels/sig_pri.c?view=diff&rev=221688&r1=221687&r2=221688
==============================================================================
--- team/moy/dahdi-tap-trunk/channels/sig_pri.c (original)
+++ team/moy/dahdi-tap-trunk/channels/sig_pri.c Thu Oct  1 13:01:19 2009
@@ -1266,6 +1266,8 @@
 {
 	int chanpos, peerpos, law, layer1, transcap;
 	struct dahdi_tapcall *tapcall = NULL;
+	struct sig_pri_chan *masterpvt = NULL;
+	struct sig_pri_chan *peerpvt = NULL;
 	struct ast_channel *c = NULL;
 	struct sig_pri_pri *peerpri = pri->tappingpeer;
 
@@ -1339,57 +1341,83 @@
 			break;
 		}
 
+		masterpvt = pri->pvts[chanpos];
+		peerpvt = peerpri->pvts[peerpos];
+
+		/* lock the dahdi pvts and do some sanity check */
+		sig_pri_lock_private(masterpvt);
+		if (masterpvt->owner) {
+			ast_log(LOG_WARNING, "Got proceeding on channel %d/%d already in use on span %d\n",
+				PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
+			sig_pri_unlock_private(masterpvt);
+			break;
+		}
+
+		sig_pri_lock_private(peerpvt);
+		if (peerpvt->owner) {
+			ast_log(LOG_WARNING, "Got proceeding on peer channel %d/%d already in use on span %d\n",
+				PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), peerpri->span);
+			sig_pri_unlock_private(masterpvt);
+			sig_pri_unlock_private(peerpvt);
+			break;
+		}
+
+
 		/* save the call reference */
-		pri->pvts[chanpos]->call = e->proceeding.call;
-		peerpri->pvts[peerpos]->call = e->proceeding.call;
+		masterpvt->call = e->proceeding.call;
+		peerpvt->call = e->proceeding.call;
 
 		/* Set calling and callee information */
-		ast_copy_string(pri->pvts[chanpos]->cid_num, tapcall->callingnum, sizeof(pri->pvts[chanpos]->cid_num));
-		ast_shrink_phone_number(pri->pvts[chanpos]->cid_num);
+		ast_copy_string(masterpvt->cid_num, tapcall->callingnum, sizeof(masterpvt->cid_num));
+		ast_shrink_phone_number(masterpvt->cid_num);
 #ifdef PRI_ANI
 		if (!ast_strlen_zero(tapcall->callingani)) {
-			ast_copy_string(pri->pvts[chanpos]->cid_ani, tapcall->callingani, sizeof(pri->pvts[chanpos]->cid_ani));
-			ast_shrink_phone_number(pri->pvts[chanpos]->cid_ani);
+			ast_copy_string(masterpvt->cid_ani, tapcall->callingani, sizeof(masterpvt->cid_ani));
+			ast_shrink_phone_number(masterpvt->cid_ani);
 		} else {
-			pri->pvts[chanpos]->cid_ani[0] = '\0';
-		}
-#endif
-		ast_copy_string(pri->pvts[chanpos]->cid_name, tapcall->callingname, sizeof(pri->pvts[chanpos]->cid_name));
+			masterpvt->cid_ani[0] = '\0';
+		}
+#endif
+		ast_copy_string(masterpvt->cid_name, tapcall->callingname, sizeof(masterpvt->cid_name));
 
 		if (!ast_strlen_zero(tapcall->callednum)) {
-			ast_copy_string(pri->pvts[chanpos]->exten, tapcall->callednum, sizeof(pri->pvts[chanpos]->exten));
+			ast_copy_string(masterpvt->exten, tapcall->callednum, sizeof(masterpvt->exten));
 		} else if (pri->overlapdial)
-			pri->pvts[chanpos]->exten[0] = '\0';
+			masterpvt->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';
+			masterpvt->exten[0] = 's';
+			masterpvt->exten[1] = '\0';
 		}
 
 		/* set the tapping peers in both pri pvts */
-		peerpri->pvts[peerpos]->tappingpeer = pri->pvts[chanpos];
-		pri->pvts[chanpos]->tappingpeer = peerpri->pvts[peerpos];
+		masterpvt->tappingpeer = peerpvt;
+		peerpvt->tappingpeer = masterpvt;
 
 		/* create the actual ast_channel but dont start a pbx just yet */
 		law = layer1 == PRI_LAYER_1_ULAW ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW;
 		ast_mutex_unlock(&pri->lock);
-		c = sig_pri_new_ast_channel(pri->pvts[chanpos], AST_STATE_RING, 0, law, AST_TRANS_CAP_SPEECH, pri->pvts[chanpos]->exten, NULL);
+		c = sig_pri_new_ast_channel(masterpvt, AST_STATE_RING, 0, law, AST_TRANS_CAP_SPEECH, masterpvt->exten, NULL);
 		ast_mutex_lock(&pri->lock);
 		if (!c) {
 			ast_log(LOG_ERROR, "Failed to create channel for PRI call on channel %d/%d on span %d\n",
 				PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
-			peerpri->pvts[peerpos]->tappingpeer = NULL;
-			pri->pvts[chanpos]->tappingpeer = NULL;
+			peerpvt->tappingpeer = NULL;
+			masterpvt->tappingpeer = NULL;
+			sig_pri_unlock_private(masterpvt);
+			sig_pri_unlock_private(peerpvt);
 			break;
 		}
 		/* the owner for the peer channel will be the same, both dahdi pvt structures will share the owner */
-		peerpri->pvts[peerpos]->owner = c;
+		peerpvt->owner = c;
 
 		/* 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);
 		}
+		sig_pri_unlock_private(masterpvt);
+		sig_pri_unlock_private(peerpvt);
 		break;
 
 	case PRI_EVENT_ANSWER:
@@ -1402,21 +1430,19 @@
 				PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
 			break;
 		}
-
+		masterpvt = pri->pvts[chanpos];
+
+		sig_pri_lock_private(masterpvt);
 		if (!pri->pvts[chanpos]->owner) {
 			/* 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;
-		}
-
-		/* set the owner state as UP */
-		c = pri->pvts[chanpos]->owner;
-		ast_channel_lock(c);
-		if (c->_state == AST_STATE_RING) {
-			ast_setstate(c, AST_STATE_UP);
-		}
-		ast_channel_unlock(c);
+			sig_pri_unlock_private(masterpvt);
+			break;
+		}
+		pri_queue_control(masterpvt, AST_CONTROL_ANSWER, pri);
+		sig_pri_set_echocanceller(masterpvt, 1);
+		sig_pri_unlock_private(masterpvt);
 		break;
 
 	case PRI_EVENT_HANGUP:
@@ -1424,37 +1450,54 @@
 		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",
+			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;
 		}
+		chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
+		if (chanpos < 0) {
+			ast_log(LOG_WARNING, "Hangup REQ on bad channel %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 */
+		 * regardless of whether there is an owner or not, this resource must be freed */
 		pri_put_pcall(pri, e->hangup.call);
 
-		if (!pri->pvts[chanpos]->owner) {
-			/* 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;
-		}
-		ast_queue_hangup(pri->pvts[chanpos]->owner);
-
-		chanpos = pri_find_principle(peerpri, e->hangup.channel);
-		if (chanpos < 0) {
-			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) {
-			/* 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);
-
+		masterpvt = pri->pvts[chanpos];
+		sig_pri_lock_private(masterpvt);
+		if (!masterpvt->alreadyhungup) {
+			masterpvt->alreadyhungup = 1;
+			if (masterpvt->owner) {
+				/* Queue a BUSY instead of a hangup if our cause is appropriate */
+				masterpvt->owner->hangupcause = e->hangup.cause;
+				if (masterpvt->owner->_state == AST_STATE_UP) {
+					ast_softhangup_nolock(masterpvt->owner, AST_SOFTHANGUP_DEV);
+				} else {
+					switch (e->hangup.cause) {
+					case PRI_CAUSE_USER_BUSY:
+						pri_queue_control(masterpvt, AST_CONTROL_BUSY, pri);
+						break;
+					case PRI_CAUSE_CALL_REJECTED:
+					case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
+					case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+					case PRI_CAUSE_SWITCH_CONGESTION:
+					case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+					case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+						pri_queue_control(masterpvt, AST_CONTROL_CONGESTION, pri);
+						break;
+					default:
+						ast_softhangup_nolock(masterpvt->owner, AST_SOFTHANGUP_DEV);
+						break;
+					}
+				}
+			}
+			ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
+				masterpvt->logicalspan, masterpvt->prioffset, pri->span, e->hangup.cause);
+		} else {
+			pri_hangup(pri->pri, masterpvt->call, e->hangup.cause);
+		}
+		sig_pri_unlock_private(masterpvt);
 		break;
 
 	case PRI_EVENT_HANGUP_ACK:
@@ -2708,8 +2751,11 @@
 	p->setup_ack = 0;
 	p->exten[0] = '\0';
 	if (p->tappingpeer) {
-		p->tappingpeer->tappingpeer = NULL;
+		struct sig_pri_chan *pp = p->tappingpeer;
+		ast_log(LOG_DEBUG, "Cleaning up PRI tapping peer\n");
 		p->tappingpeer = NULL;
+		pp->tappingpeer = NULL;
+		pp->owner = NULL;
 	}
 	sig_pri_set_dialing(p, 0);
 




More information about the asterisk-commits mailing list