chan_dahdi: Add the chan_dahdi.conf force_restart_unavailable_chans option.

Some telco switches occasionally ignore ISDN RESTART requests.  The fix
for ASTERISK-19608 added an escape clause for B channels in the restarting
state if the telco ignores a RESTART request.  If the telco fails to
acknowledge the RESTART then Asterisk will assume the telco acknowledged
the RESTART on the second call attempt requesting the B channel by the
telco.  The escape clause is good for dealing with RESTART requests in
general but it does cause the next call for the restarting B channel to be
rejected if the telco insists the call must go on that B channel.

chan_dahdi doesn't really need to issue a RESTART request in response to
receiving a cause 44 (Requested channel not available) code.  Sending the
RESTART in such a situation is not required (nor prohibited) by the
standards.  I think chan_dahdi does this for historical reasons to deal
with buggy peers to get channels unstuck in a similar fashion as the
chan_dahdi.conf resetinterval option.

* Add the chan_dahdi.conf force_restart_unavailable_chans compatability
option that when disabled will prevent chan_dahdi from trying to RESTART
the channel in response to a cause 44 code.

ASTERISK-25034 #close
Reported by: Richard Mudgett

Change-Id: Ib8b17a438799920f4a2038826ff99a1884042f65
changes/04/304/2
Richard Mudgett 11 years ago committed by Joshua Colp
parent 37a193da18
commit d3c310a28c

@ -40,6 +40,13 @@ CLI:
by the CLI command is always the Asterisk version. This CLI command by the CLI command is always the Asterisk version. This CLI command
will be removed in Asterisk 14. will be removed in Asterisk 14.
chan_dahdi:
- Added the force_restart_unavailable_chans compatibility option. When
enabled it causes Asterisk to restart the ISDN B channel if an outgoing
call receives cause 44 (Requested channel not available). The new option
is enabled by default in current release branches for backward
compatibility.
res_pjsip: res_pjsip:
- The dtmf_mode now supports a new option, 'auto'. This mode will attempt to - The dtmf_mode now supports a new option, 'auto'. This mode will attempt to
detect if the device supports RFC4733 DTMF. If so, it will choose that detect if the device supports RFC4733 DTMF. If so, it will choose that

@ -919,6 +919,7 @@ static struct dahdi_chan_conf dahdi_chan_conf_default(void)
.privateprefix = "", .privateprefix = "",
.unknownprefix = "", .unknownprefix = "",
.colp_send = SIG_PRI_COLP_UPDATE, .colp_send = SIG_PRI_COLP_UPDATE,
.force_restart_unavailable_chans = 1,
.resetinterval = -1, .resetinterval = -1,
}, },
#endif #endif
@ -12346,6 +12347,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
#if defined(HAVE_PRI_MCID) #if defined(HAVE_PRI_MCID)
pris[span].pri.mcid_send = conf->pri.pri.mcid_send; pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
#endif /* defined(HAVE_PRI_MCID) */ #endif /* defined(HAVE_PRI_MCID) */
pris[span].pri.force_restart_unavailable_chans = conf->pri.pri.force_restart_unavailable_chans;
#if defined(HAVE_PRI_DATETIME_SEND) #if defined(HAVE_PRI_DATETIME_SEND)
pris[span].pri.datetime_send = conf->pri.pri.datetime_send; pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
#endif /* defined(HAVE_PRI_DATETIME_SEND) */ #endif /* defined(HAVE_PRI_DATETIME_SEND) */
@ -18258,6 +18260,8 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
else else
ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
v->value, v->lineno); v->value, v->lineno);
} else if (!strcasecmp(v->name, "force_restart_unavailable_chans")) {
confp->pri.pri.force_restart_unavailable_chans = ast_true(v->value);
} else if (!strcasecmp(v->name, "minunused")) { } else if (!strcasecmp(v->name, "minunused")) {
confp->pri.pri.minunused = atoi(v->value); confp->pri.pri.minunused = atoi(v->value);
} else if (!strcasecmp(v->name, "minidle")) { } else if (!strcasecmp(v->name, "minidle")) {

@ -133,15 +133,6 @@
*/ */
//#define ALWAYS_PICK_CHANNEL 1 //#define ALWAYS_PICK_CHANNEL 1
/*!
* Define to force a RESTART on a channel that returns a cause
* code of PRI_CAUSE_REQUESTED_CHAN_UNAVAIL(44). If the cause
* is because of a stuck channel on the peer and the channel is
* always the next channel we pick for an outgoing call then
* this can help.
*/
#define FORCE_RESTART_UNAVAIL_CHANS 1
#if defined(HAVE_PRI_CCSS) #if defined(HAVE_PRI_CCSS)
struct sig_pri_cc_agent_prv { struct sig_pri_cc_agent_prv {
/*! Asterisk span D channel control structure. */ /*! Asterisk span D channel control structure. */
@ -7170,9 +7161,9 @@ static void *pri_dchannel(void *vpri)
pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
pri->pvts[chanpos]->call = NULL; pri->pvts[chanpos]->call = NULL;
} }
#if defined(FORCE_RESTART_UNAVAIL_CHANS)
if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
&& pri->sig != SIG_BRI_PTMP && !pri->resetting && pri->sig != SIG_BRI_PTMP && !pri->resetting
&& pri->force_restart_unavailable_chans
&& pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) { && pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) {
ast_verb(3, ast_verb(3,
"Span %d: Forcing restart of channel %d/%d since channel reported in use\n", "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
@ -7181,7 +7172,6 @@ static void *pri_dchannel(void *vpri)
pri->pvts[chanpos]->resetting = SIG_PRI_RESET_ACTIVE; pri->pvts[chanpos]->resetting = SIG_PRI_RESET_ACTIVE;
pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
} }
#endif /* defined(FORCE_RESTART_UNAVAIL_CHANS) */
if (e->hangup.aoc_units > -1) if (e->hangup.aoc_units > -1)
ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 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"); pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
@ -7319,9 +7309,9 @@ static void *pri_dchannel(void *vpri)
pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
pri->pvts[chanpos]->call = NULL; pri->pvts[chanpos]->call = NULL;
} }
#if defined(FORCE_RESTART_UNAVAIL_CHANS)
if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
&& pri->sig != SIG_BRI_PTMP && !pri->resetting && pri->sig != SIG_BRI_PTMP && !pri->resetting
&& pri->force_restart_unavailable_chans
&& pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) { && pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) {
ast_verb(3, ast_verb(3,
"Span %d: Forcing restart of channel %d/%d since channel reported in use\n", "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
@ -7330,7 +7320,6 @@ static void *pri_dchannel(void *vpri)
pri->pvts[chanpos]->resetting = SIG_PRI_RESET_ACTIVE; pri->pvts[chanpos]->resetting = SIG_PRI_RESET_ACTIVE;
pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
} }
#endif /* defined(FORCE_RESTART_UNAVAIL_CHANS) */
#ifdef SUPPORT_USERUSER #ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->hangup.useruserinfo)) { if (!ast_strlen_zero(e->hangup.useruserinfo)) {

@ -496,6 +496,8 @@ struct sig_pri_span {
#if defined(HAVE_PRI_MCID) #if defined(HAVE_PRI_MCID)
/*! \brief TRUE if allow sending MCID request on this span. */ /*! \brief TRUE if allow sending MCID request on this span. */
unsigned int mcid_send:1; unsigned int mcid_send:1;
/*! \brief TRUE if forcing RESTART when receive cause 44 on this span. */
unsigned int force_restart_unavailable_chans:1;
#endif /* defined(HAVE_PRI_MCID) */ #endif /* defined(HAVE_PRI_MCID) */
#if defined(HAVE_PRI_DATETIME_SEND) #if defined(HAVE_PRI_DATETIME_SEND)
/*! \brief Configured date/time ie send policy option. */ /*! \brief Configured date/time ie send policy option. */

@ -196,6 +196,20 @@ context=public
; ;
;resetinterval = 3600 ;resetinterval = 3600
; ;
; Enable per span to force a RESTART on a channel that returns a cause
; code of PRI_CAUSE_REQUESTED_CHAN_UNAVAIL(44). If the cause is because
; of a stuck channel on the peer and the channel is always the next
; channel we pick for an outgoing call then this might help.
;
; NOTE: Sending a RESTART in response to a cause 44 is not required
; (nor prohibited) by the standards and is likely a primitive chan_dahdi
; response to call collisions (glare) and buggy peers. However, there
; are telco switches out there that ignore the RESTART and continue to
; send calls to the channel in the restarting state.
; Default yes in current release branches for backward compatibility.
;
;force_restart_unavailable_chans=yes
;
; Assume inband audio may be present when a SETUP ACK message is received. ; Assume inband audio may be present when a SETUP ACK message is received.
; Q.931 Section 5.1.3 says that in scenarios with overlap dialing, when a ; Q.931 Section 5.1.3 says that in scenarios with overlap dialing, when a
; dialtone is sent from the network side, progress indicator 8 "Inband info ; dialtone is sent from the network side, progress indicator 8 "Inband info

Loading…
Cancel
Save