Index: channels/chan_dahdi.c =================================================================== --- channels/chan_dahdi.c (revision 129801) +++ channels/chan_dahdi.c (working copy) @@ -333,6 +333,7 @@ int resetpos; time_t lastreset; /*!< time when unused channels were last reset */ long resetinterval; /*!< Interval (in seconds) for resetting unused channels */ + long resettimeout; /*!< Timeout (in seconds) before a reset request expires */ struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */ struct dahdi_pvt *crvs; /*!< Member CRV structs */ struct dahdi_pvt *crvend; /*!< Pointer to end of CRV structs */ @@ -485,7 +486,7 @@ unsigned int isidlecall:1; unsigned int proceeding:1; unsigned int progress:1; - unsigned int resetting:1; + struct timeval resetting; /* Time when a restart request was last sent */ unsigned int setup_ack:1; #endif unsigned int use_smdi:1; /* Whether to use SMDI on this channel */ @@ -620,7 +621,8 @@ .privateprefix = "", .unknownprefix = "", - .resetinterval = 3600 + .resetinterval = 3600, + .resettimeout = 3, }, #endif .chan = { @@ -7357,6 +7359,7 @@ ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); pris[span].resetinterval = conf->pri.resetinterval; + pris[span].resettimeout = conf->pri.resettimeout; tmp->pri = &pris[span]; tmp->prioffset = offset; @@ -7664,7 +7667,7 @@ #ifdef HAVE_PRI /* Trust PRI */ if (p->pri) { - if (p->resetting || p->call) + if (!ast_tvzero(p->resetting) || p->call) return 0; else return 1; @@ -8285,18 +8288,19 @@ static int pri_check_restart(struct dahdi_pri *pri) { + struct timeval tv = ast_tvnow(); do { pri->resetpos++; } while ((pri->resetpos < pri->numchans) && (!pri->pvts[pri->resetpos] || pri->pvts[pri->resetpos]->call || - pri->pvts[pri->resetpos]->resetting)); + !ast_tvzero(pri->pvts[pri->resetpos]->resetting))); if (pri->resetpos < pri->numchans) { /* Mark the channel as resetting and restart it */ - pri->pvts[pri->resetpos]->resetting = 1; + pri->pvts[pri->resetpos]->resetting = tv; pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); } else { - pri->resetting = 0; + pri->resetting = ast_tv(0, 0); time(&pri->lastreset); } return 0; @@ -8394,7 +8398,7 @@ char idlen[80]; struct ast_channel *idle; pthread_t p; - time_t t; + struct timeval tv; int i, which=-1; int numdchans; int cause=0; @@ -8433,15 +8437,24 @@ fds[i].revents = 0; } numdchans = i; - time(&t); + tv = ast_tvnow(); ast_mutex_lock(&pri->lock); if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { - if (pri->resetting && pri_is_up(pri)) { + if (!ast_tvzero(pri->resetting) && pri_is_up(pri)) { + if (pri->resetpos >= 0 && + pri->pvts[pri->resetpos] && + pri->pvts[pri->resetpos]->resetting.tv_sec > 1000 && + ast_tvdiff_ms(tv, ast_tvadd(pri->pvts[pri->resetpos]->resetting, ast_tv(pri->resettimeout, 0))) > 0) { + ast_verbose(VERBOSE_PREFIX_3 "Span %d - Reset of B-channel %d timed out\n", pri->span, pri->resetpos + 1); + pri->pvts[pri->resetpos]->resetting = ast_tv(0, 0); + pri_check_restart(pri); + } + if (pri->resetpos < 0) pri_check_restart(pri); } else { - if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { - pri->resetting = 1; + if (ast_tvzero(pri->resetting) && (tv.tv_sec - pri->lastreset) >= pri->resetinterval) { + pri->resetting = ast_tv(1, 0); pri->resetpos = -1; } } @@ -8456,7 +8469,7 @@ !pri->pvts[x]->call) { if (haveidles < pri->minunused) { haveidles++; - } else if (!pri->pvts[x]->resetting) { + } else if (!pri->pvts[x]->resetting.tv_sec) { nextidle = x; break; } @@ -8508,7 +8521,7 @@ if (tv.tv_sec < 0) { tv = ast_tv(0,0); } - if (doidling || pri->resetting) { + if (doidling || pri->resetting.tv_sec) { if (tv.tv_sec > 1) { tv = ast_tv(1, 0); } @@ -8517,7 +8530,7 @@ tv = ast_tv(60, 0); } } - } else if (doidling || pri->resetting) { + } else if (doidling || pri->resetting.tv_sec) { /* Make sure we stop at least once per second if we're monitoring idle channels */ tv = ast_tv(1,0); @@ -8608,7 +8621,7 @@ pri->lastreset -= pri->resetinterval; pri->lastreset += 5; } - pri->resetting = 0; + pri->resetting = ast_tv(0, 0); /* Take the channels from inalarm condition */ for (i = 0; i < pri->numchans; i++) if (pri->pvts[i]) { @@ -8618,7 +8631,7 @@ case PRI_EVENT_DCHAN_DOWN: pri_find_dchan(pri); if (!pri_is_up(pri)) { - pri->resetting = 0; + pri->resetting = ast_tv(0, 0); /* Hangup active channels and put them in alarm mode */ for (i = 0; i < pri->numchans; i++) { struct dahdi_pvt *p = pri->pvts[i]; @@ -9246,7 +9259,7 @@ ast_verbose(VERBOSE_PREFIX_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; + pri->pvts[chanpos]->resetting = ast_tv(1, 0); } if (e->hangup.aoc_units > -1) if (option_verbose > 2) @@ -9319,7 +9332,7 @@ ast_verbose(VERBOSE_PREFIX_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; + pri->pvts[chanpos]->resetting = ast_tv(1, 0); } #ifdef SUPPORT_USERUSER @@ -9347,7 +9360,7 @@ if (chanpos > -1) { ast_mutex_lock(&pri->pvts[chanpos]->lock); pri->pvts[chanpos]->call = NULL; - pri->pvts[chanpos]->resetting = 0; + pri->pvts[chanpos]->resetting = ast_tv(0, 0); if (pri->pvts[chanpos]->owner) { if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); @@ -9376,7 +9389,7 @@ channel number, so we have to figure it out... This must be why everybody resets exactly a channel at a time. */ for (x = 0; x < pri->numchans; x++) { - if (pri->pvts[x] && pri->pvts[x]->resetting) { + if (pri->pvts[x] && !ast_tvzero(pri->pvts[x]->resetting)) { chanpos = x; ast_mutex_lock(&pri->pvts[chanpos]->lock); ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, @@ -9388,12 +9401,12 @@ pri->pvts[chanpos]->prioffset, pri->span); pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; } - pri->pvts[chanpos]->resetting = 0; + pri->pvts[chanpos]->resetting = ast_tv(0, 0); if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); ast_mutex_unlock(&pri->pvts[chanpos]->lock); - if (pri->resetting) + if (!ast_tvzero(pri->resetting)) pri_check_restart(pri); break; } @@ -9412,12 +9425,12 @@ PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; } - pri->pvts[chanpos]->resetting = 0; + pri->pvts[chanpos]->resetting = ast_tv(0, 0); if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); ast_mutex_unlock(&pri->pvts[chanpos]->lock); - if (pri->resetting) + if (!ast_tvzero(pri->resetting)) pri_check_restart(pri); } } @@ -10089,7 +10102,7 @@ #ifdef HAVE_PRI if (tmp->pri) { ast_cli(fd, "PRI Flags: "); - if (tmp->resetting) + if (!ast_tvzero(tmp->resetting)) ast_cli(fd, "Resetting "); if (tmp->call) ast_cli(fd, "Call "); @@ -11143,6 +11156,14 @@ else 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); + } else if (!strcasecmp(v->name, "resettimeout")) { + if (!strcasecmp(v->value, "never")) + confp->pri.resettimeout = -1; + else if (atoi(v->value) != 0) + confp->pri.resettimeout = atoi(v->value); + else + ast_log(LOG_WARNING, "'%s' is not a valid reset timeout, should be >= 1 seconds or 'never' at line %d\n", + v->value, v->lineno); } else if (!strcasecmp(v->name, "minunused")) { confp->pri.minunused = atoi(v->value); } else if (!strcasecmp(v->name, "minidle")) {