Index: channels/chan_dahdi.c =================================================================== --- channels/chan_dahdi.c (revision 234818) +++ channels/chan_dahdi.c (working copy) @@ -10366,6 +10366,21 @@ } +static int pri_find_principle_by_call(struct dahdi_pri *pri, q931_call *call) +{ + int x; + int principle = -1; + + for (x = 0; x < pri->numchans; x++) { + if (pri->pvts[x] && (pri->pvts[x]->call == call)) { + principle = x; + break; + } + } + + return principle; +} + static int pri_find_principle(struct dahdi_pri *pri, int channel) { int x; @@ -10443,8 +10458,13 @@ /* Copy any DSP that may be present */ new->dsp = old->dsp; new->dsp_features = old->dsp_features; + new->alreadyhungup = old->alreadyhungup; + new->dialing = old->dialing; + old->dsp = NULL; old->dsp_features = 0; + old->alreadyhungup = 0; + old->dialing = 0; } return principle; } @@ -11552,173 +11572,161 @@ } break; case PRI_EVENT_HANGUP: - chanpos = pri_find_principle(pri, e->hangup.channel); + chanpos = pri_find_principle_by_call(pri, e->hangup.call); if (chanpos < 0) { - ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", + ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d. Hanging up anyway\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); + pri_hangup(pri->pri, e->hangup.call, e->hangup.cause); } else { - chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); - if (chanpos > -1) { - ast_mutex_lock(&pri->pvts[chanpos]->lock); - if (!pri->pvts[chanpos]->alreadyhungup) { - /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ - pri->pvts[chanpos]->alreadyhungup = 1; - if (pri->pvts[chanpos]->realcall) - pri_hangup_all(pri->pvts[chanpos]->realcall, pri); - else if (pri->pvts[chanpos]->owner) { - /* Queue a BUSY instead of a hangup if our cause is appropriate */ - pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; - switch (pri->pvts[chanpos]->owner->_state) { - case AST_STATE_BUSY: - case AST_STATE_UP: - pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; + ast_mutex_lock(&pri->pvts[chanpos]->lock); + if (!pri->pvts[chanpos]->alreadyhungup) { + /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ + pri->pvts[chanpos]->alreadyhungup = 1; + if (pri->pvts[chanpos]->realcall) + pri_hangup_all(pri->pvts[chanpos]->realcall, pri); + else if (pri->pvts[chanpos]->owner) { + /* Queue a BUSY instead of a hangup if our cause is appropriate */ + pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; + switch (pri->pvts[chanpos]->owner->_state) { + case AST_STATE_BUSY: + case AST_STATE_UP: + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; + break; + default: + switch (e->hangup.cause) { + case PRI_CAUSE_USER_BUSY: + pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 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->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; + break; default: - switch (e->hangup.cause) { - case PRI_CAUSE_USER_BUSY: - pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; - 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->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; - break; - default: - pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; - } - break; + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; } + break; } - ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n", - pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); - } else { - pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); - pri->pvts[chanpos]->call = NULL; } - if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { - ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n", - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); - pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); - pri->pvts[chanpos]->resetting = 1; - } - if (e->hangup.aoc_units > -1) - ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", - pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); + ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n", + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); + } else { + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); + pri->pvts[chanpos]->call = NULL; + } + if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { + ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n", + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); + pri->pvts[chanpos]->resetting = 1; + } + if (e->hangup.aoc_units > -1) + ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); #ifdef SUPPORT_USERUSER - if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { - struct ast_channel *owner = pri->pvts[chanpos]->owner; - ast_mutex_unlock(&pri->pvts[chanpos]->lock); - pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); - ast_mutex_lock(&pri->pvts[chanpos]->lock); - } + if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { + struct ast_channel *owner = pri->pvts[chanpos]->owner; + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); + ast_mutex_lock(&pri->pvts[chanpos]->lock); + } #endif - ast_mutex_unlock(&pri->pvts[chanpos]->lock); - } else { - ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); - } + ast_mutex_unlock(&pri->pvts[chanpos]->lock); } break; #ifndef PRI_EVENT_HANGUP_REQ #error please update libpri #endif case PRI_EVENT_HANGUP_REQ: - chanpos = pri_find_principle(pri, e->hangup.channel); + chanpos = pri_find_principle_by_call(pri, e->hangup.call); if (chanpos < 0) { - ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", + ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d - Hanging up anyways\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); + pri_hangup(pri->pri, e->hangup.call, e->hangup.cause); } else { - chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); - if (chanpos > -1) { - ast_mutex_lock(&pri->pvts[chanpos]->lock); - if (pri->pvts[chanpos]->realcall) - pri_hangup_all(pri->pvts[chanpos]->realcall, pri); - else if (pri->pvts[chanpos]->owner) { - pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; - switch (pri->pvts[chanpos]->owner->_state) { - case AST_STATE_BUSY: - case AST_STATE_UP: - pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; - break; - default: - switch (e->hangup.cause) { - case PRI_CAUSE_USER_BUSY: - pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; - 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->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; - break; - default: - pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; - } - break; + ast_mutex_lock(&pri->pvts[chanpos]->lock); + if (pri->pvts[chanpos]->realcall) + pri_hangup_all(pri->pvts[chanpos]->realcall, pri); + else if (pri->pvts[chanpos]->owner) { + pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; + switch (pri->pvts[chanpos]->owner->_state) { + case AST_STATE_BUSY: + case AST_STATE_UP: + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; + break; + default: + switch (e->hangup.cause) { + case PRI_CAUSE_USER_BUSY: + pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; + 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->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; + break; + default: + pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; } - ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause); - if (e->hangup.aoc_units > -1) - ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", - pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); - } else { - pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); - pri->pvts[chanpos]->call = NULL; + break; } - if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { - ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n", - PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); - pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); - pri->pvts[chanpos]->resetting = 1; - } + ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause); + if (e->hangup.aoc_units > -1) + ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", + pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); + } else { + pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); + pri->pvts[chanpos]->call = NULL; + } + if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { + ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n", + PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); + pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); + pri->pvts[chanpos]->resetting = 1; + } #ifdef SUPPORT_USERUSER - if (!ast_strlen_zero(e->hangup.useruserinfo)) { - struct ast_channel *owner = pri->pvts[chanpos]->owner; - ast_mutex_unlock(&pri->pvts[chanpos]->lock); - pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); - ast_mutex_lock(&pri->pvts[chanpos]->lock); - } + if (!ast_strlen_zero(e->hangup.useruserinfo)) { + struct ast_channel *owner = pri->pvts[chanpos]->owner; + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); + ast_mutex_lock(&pri->pvts[chanpos]->lock); + } #endif - ast_mutex_unlock(&pri->pvts[chanpos]->lock); - } else { - 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); - } + ast_mutex_unlock(&pri->pvts[chanpos]->lock); } break; case PRI_EVENT_HANGUP_ACK: - chanpos = pri_find_principle(pri, e->hangup.channel); + chanpos = pri_find_principle_by_call(pri, e->hangup.call); if (chanpos < 0) { ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); } else { - chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); - if (chanpos > -1) { - ast_mutex_lock(&pri->pvts[chanpos]->lock); - pri->pvts[chanpos]->call = NULL; - pri->pvts[chanpos]->resetting = 0; - if (pri->pvts[chanpos]->owner) { - ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); - } + ast_mutex_lock(&pri->pvts[chanpos]->lock); + pri->pvts[chanpos]->call = NULL; + pri->pvts[chanpos]->resetting = 0; + if (pri->pvts[chanpos]->owner) { + ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); + } #ifdef SUPPORT_USERUSER - if (!ast_strlen_zero(e->hangup.useruserinfo)) { - struct ast_channel *owner = pri->pvts[chanpos]->owner; - ast_mutex_unlock(&pri->pvts[chanpos]->lock); - pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); - ast_mutex_lock(&pri->pvts[chanpos]->lock); - } + if (!ast_strlen_zero(e->hangup.useruserinfo)) { + struct ast_channel *owner = pri->pvts[chanpos]->owner; + ast_mutex_unlock(&pri->pvts[chanpos]->lock); + pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); + ast_mutex_lock(&pri->pvts[chanpos]->lock); + } #endif - ast_mutex_unlock(&pri->pvts[chanpos]->lock); - } + ast_mutex_unlock(&pri->pvts[chanpos]->lock); } break; case PRI_EVENT_CONFIG_ERR: