[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