[asterisk-commits] moy: branch moy/dahdi-tap-1.6.2 r221587 - /team/moy/dahdi-tap-1.6.2/channels/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Oct 1 09:48:17 CDT 2009
Author: moy
Date: Thu Oct 1 09:48:12 2009
New Revision: 221587
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=221587
Log:
add proper locking to pvt and chan structures
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=221587&r1=221586&r2=221587
==============================================================================
--- team/moy/dahdi-tap-1.6.2/channels/chan_dahdi.c (original)
+++ team/moy/dahdi-tap-1.6.2/channels/chan_dahdi.c Thu Oct 1 09:48:12 2009
@@ -4380,6 +4380,12 @@
p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
p->ignoredtmf = 0;
+ if (p->passivepeer) {
+ p->passivepeer->passivepeer = NULL;
+ p->passivepeer->owner = NULL;
+ p->passivepeer = NULL;
+ }
+
if (idx > -1) {
/* Real channel, do some fixup */
p->subs[idx].owner = NULL;
@@ -12432,8 +12438,10 @@
int chanpos, peerpos, law, layer1, transcap, res, fd;
struct dahdi_pcall *pcall = NULL;
struct ast_channel *c = NULL;
+ struct dahdi_pvt *peerpvt = NULL;
+ struct dahdi_pvt *masterpvt = NULL;
+ struct dahdi_confinfo dahdic = { 0, };
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);
@@ -12505,82 +12513,100 @@
break;
}
+ masterpvt = pri->pvts[chanpos];
+ peerpvt = peerpri->pvts[chanpos];
+
+ /* get pvt locks and do sanity checks */
+ ast_mutex_lock(&masterpvt->lock);
+
+ /* sanity check */
+ if (masterpvt->owner) {
+ ast_log(LOG_ERROR, "Master pvt has already an owner when receiving passive call!!\n");
+ ast_mutex_unlock(&masterpvt->lock);
+ break;
+ }
+
+ ast_mutex_lock(&peerpvt->lock);
+ if (peerpvt->owner) {
+ ast_log(LOG_ERROR, "Peer pvt has already an owner when receiving passive call!!\n");
+ ast_mutex_unlock(&masterpvt->lock);
+ ast_mutex_unlock(&peerpvt->lock);
+ 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, pcall->callingnum, sizeof(pri->pvts[chanpos]->cid_num));
- ast_shrink_phone_number(pri->pvts[chanpos]->cid_num);
+ ast_copy_string(masterpvt->cid_num, pcall->callingnum, sizeof(masterpvt->cid_num));
+ ast_shrink_phone_number(masterpvt->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);
+ ast_copy_string(masterpvt->cid_ani, pcall->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, pcall->callingname, sizeof(pri->pvts[chanpos]->cid_name));
+ masterpvt->cid_ani[0] = '\0';
+ }
+#endif
+ ast_copy_string(masterpvt->cid_name, pcall->callingname, sizeof(masterpvt->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));
+ ast_copy_string(masterpvt->exten, pcall->callednum, sizeof(masterpvt->exten));
+ ast_copy_string(masterpvt->dnid, pcall->callednum, sizeof(masterpvt->dnid));
} 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';
- }
-
- /* 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));
+ masterpvt->exten[0] = 's';
+ masterpvt->exten[1] = '\0';
}
/* 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_RING, 0, SUB_REAL, law, AST_TRANS_CAP_SPEECH);
+ c = dahdi_new(masterpvt, 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);
+ ast_mutex_unlock(&peerpvt->lock);
+ ast_mutex_unlock(&masterpvt->lock);
break;
}
- res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
+ res = dahdi_setlaw(masterpvt->subs[SUB_REAL].dfd, law);
if (res < 0) {
- 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);
+ ast_log(LOG_WARNING, "Unable to set law on channel %d: %s\n", masterpvt->channel, strerror(errno));
+ }
+ res = set_actual_gain(masterpvt->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: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
}
- res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law);
+ res = ioctl(masterpvt->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);
+ res = dahdi_setlaw(peerpvt->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);
+ ast_log(LOG_WARNING, "Unable to set law on peer channel %d: %s\n", peerpvt->channel, strerror(errno));
+ }
+ res = set_actual_gain(peerpvt->subs[SUB_REAL].dfd, 0, peerpvt->rxgain, peerpvt->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);
+ ast_log(LOG_WARNING, "Unable to set gains on peer channel %d: %s\n", peerpvt->channel, strerror(errno));
+ }
+ res = ioctl(peerpvt->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));
+ ast_log(LOG_WARNING, "Unable to set audio mode on peer channel %d to %d: %s\n", peerpvt->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;
- pri->pvts[chanpos]->passivepeer = peerpri->pvts[peerpos];
- peerpri->pvts[peerpos]->owner = c;
- peerpri->pvts[peerpos]->passivepeer = pri->pvts[chanpos];
+ masterpvt->owner = c;
+ masterpvt->passivepeer = peerpvt;
+ peerpvt->owner = c;
+ peerpvt->passivepeer = masterpvt;
/* create the mixing conference
* some DAHDI_SETCONF interface rules to keep in mind
@@ -12592,35 +12618,41 @@
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;
+ ast_log(LOG_ERROR, "Unable to create dahdi conference for tapping\n");
+ ast_mutex_unlock(&peerpvt->lock);
+ ast_mutex_unlock(&masterpvt->lock);
+ ast_hangup(c);
+ break;
+ }
+ masterpvt->passiveconf = dahdic.confno;
+ masterpvt->passivefd = fd;
/* add both parties to the conference */
dahdic.chan = 0;
- dahdic.confno = pri->pvts[chanpos]->passiveconf;
+ dahdic.confno = masterpvt->passiveconf;
dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER;
- if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_SETCONF, &dahdic)) {
+ if (ioctl(masterpvt->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_mutex_unlock(&peerpvt->lock);
+ ast_mutex_unlock(&masterpvt->lock);
ast_hangup(c);
break;
}
dahdic.chan = 0;
- dahdic.confno = pri->pvts[chanpos]->passiveconf;
+ dahdic.confno = masterpvt->passiveconf;
dahdic.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER;
- if (ioctl(peerpri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_SETCONF, &dahdic)) {
+ if (ioctl(peerpvt->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_mutex_unlock(&peerpvt->lock);
+ ast_mutex_unlock(&masterpvt->lock);
ast_hangup(c);
break;
}
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,
+ masterpvt->passiveconf,
+ masterpvt->passivefd,
+ masterpvt->channel,
+ peerpvt->channel,
c->name);
/* from now on, reading from the conference has the mix of both tapped channels, we can now launch the pbx thread */
@@ -12628,6 +12660,8 @@
ast_log(LOG_ERROR, "Failed to launch PBX thread for passive channel %s\n", c->name);
ast_hangup(c);
}
+ ast_mutex_unlock(&peerpvt->lock);
+ ast_mutex_unlock(&masterpvt->lock);
break;
case PRI_EVENT_ANSWER:
@@ -12640,21 +12674,19 @@
PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
break;
}
-
- if (!pri->pvts[chanpos]->owner) {
+ masterpvt = pri->pvts[chanpos];
+ ast_mutex_lock(&masterpvt->lock);
+ if (!masterpvt->owner) {
+ ast_mutex_unlock(&masterpvt->lock);
/* 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);
+ /* queue needanswer */
+ masterpvt->subs[SUB_REAL].needanswer = 1;
+ ast_mutex_unlock(&masterpvt->lock);
break;
case PRI_EVENT_HANGUP:
@@ -12670,29 +12702,22 @@
* 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) {
+ /* now try to hangup if needed */
+ masterpvt = pri->pvts[chanpos];
+ ast_mutex_lock(&masterpvt->lock);
+ while (masterpvt->owner && ast_channel_trylock(masterpvt->owner)) {
+ DEADLOCK_AVOIDANCE(&masterpvt->lock);
+ }
+ if (!masterpvt->owner) {
+ ast_mutex_unlock(&masterpvt->lock);
/* 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);
-
+ ast_queue_hangup(masterpvt->owner);
+ ast_channel_unlock(masterpvt->owner);
+ ast_mutex_unlock(&masterpvt->lock);
break;
case PRI_EVENT_HANGUP_ACK:
More information about the asterisk-commits
mailing list