diff options
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_dahdi.c | 18 | ||||
-rw-r--r-- | channels/sig_pri.c | 207 | ||||
-rw-r--r-- | channels/sig_pri.h | 23 | ||||
-rw-r--r-- | channels/sig_ss7.c | 48 | ||||
-rw-r--r-- | channels/sig_ss7.h | 26 |
5 files changed, 234 insertions, 88 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index dd3366ed4..328ec8b39 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -7705,7 +7705,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); #if defined(HAVE_PRI) if (dahdi_sig_pri_lib_handles(p->sig) - && !((struct sig_pri_chan *) p->sig_pvt)->proceeding + && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { /* absorb event */ @@ -7725,7 +7725,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) ast_debug(1, "DTMF Down '%c'\n", res & 0xff); #if defined(HAVE_PRI) if (dahdi_sig_pri_lib_handles(p->sig) - && !((struct sig_pri_chan *) p->sig_pvt)->proceeding + && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { /* absorb event */ @@ -8976,7 +8976,7 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) || f->frametype == AST_FRAME_DTMF_END) { #ifdef HAVE_PRI if (dahdi_sig_pri_lib_handles(p->sig) - && !((struct sig_pri_chan *) p->sig_pvt)->proceeding + && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING && p->pri && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { @@ -9209,7 +9209,17 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d res = 0; break; case AST_CONTROL_CONGESTION: - chan->hangupcause = AST_CAUSE_CONGESTION; + /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */ + switch (chan->hangupcause) { + case AST_CAUSE_USER_BUSY: + case AST_CAUSE_NORMAL_CLEARING: + case 0:/* Cause has not been set. */ + /* Supply a more appropriate cause. */ + chan->hangupcause = AST_CAUSE_CONGESTION; + break; + default: + break; + } break; case AST_CONTROL_HOLD: ast_moh_start(chan, data, p->mohinterpret); diff --git a/channels/sig_pri.c b/channels/sig_pri.c index a858ef20f..27e5dcf0b 100644 --- a/channels/sig_pri.c +++ b/channels/sig_pri.c @@ -1242,12 +1242,9 @@ static int pri_fixup_principle(struct sig_pri_span *pri, int principle, q931_cal new_chan->waiting_for_aoce = old_chan->waiting_for_aoce; new_chan->holding_aoce = old_chan->holding_aoce; #endif /* defined(HAVE_PRI_AOC_EVENTS) */ - new_chan->alerting = old_chan->alerting; new_chan->alreadyhungup = old_chan->alreadyhungup; new_chan->isidlecall = old_chan->isidlecall; - new_chan->proceeding = old_chan->proceeding; new_chan->progress = old_chan->progress; - new_chan->setup_ack = old_chan->setup_ack; new_chan->outgoing = old_chan->outgoing; new_chan->digital = old_chan->digital; #if defined(HAVE_PRI_CALL_WAITING) @@ -1259,12 +1256,9 @@ static int pri_fixup_principle(struct sig_pri_span *pri, int principle, q931_cal old_chan->waiting_for_aoce = 0; old_chan->holding_aoce = 0; #endif /* defined(HAVE_PRI_AOC_EVENTS) */ - old_chan->alerting = 0; old_chan->alreadyhungup = 0; old_chan->isidlecall = 0; - old_chan->proceeding = 0; old_chan->progress = 0; - old_chan->setup_ack = 0; old_chan->outgoing = 0; old_chan->digital = 0; #if defined(HAVE_PRI_CALL_WAITING) @@ -1272,6 +1266,8 @@ static int pri_fixup_principle(struct sig_pri_span *pri, int principle, q931_cal #endif /* defined(HAVE_PRI_CALL_WAITING) */ /* More stuff to transfer to the new channel. */ + new_chan->call_level = old_chan->call_level; + old_chan->call_level = SIG_PRI_CALL_LEVEL_IDLE; #if defined(HAVE_PRI_REVERSE_CHARGE) new_chan->reverse_charging_indication = old_chan->reverse_charging_indication; #endif /* defined(HAVE_PRI_REVERSE_CHARGE) */ @@ -1632,12 +1628,28 @@ static void *pri_ss_thread(void *data) /* Start the real PBX */ ast_copy_string(chan->exten, exten, sizeof(chan->exten)); sig_pri_dsp_reset_and_flush_digits(p); - if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) { +#if defined(ISSUE_16789) + /* + * Conditionaled out this code to effectively revert the Mantis + * issue 16789 change. It breaks overlap dialing through + * Asterisk. There is not enough information available at this + * point to know if dialing is complete. The + * ast_exists_extension(), ast_matchmore_extension(), and + * ast_canmatch_extension() calls are not adequate to detect a + * dial through extension pattern of "_9!". + * + * Workaround is to use the dialplan Proceeding() application + * early on non-dial through extensions. + */ + if ((p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) + && !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { sig_pri_lock_private(p); - if (p->pri->pri) { + if (p->pri->pri) { if (!pri_grab(p, p->pri)) { + if (p->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) { + p->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING; + } pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0); - p->proceeding = 1; pri_rel(p->pri); } else { ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span); @@ -1645,6 +1657,7 @@ static void *pri_ss_thread(void *data) } sig_pri_unlock_private(p); } +#endif /* defined(ISSUE_16789) */ sig_pri_set_echocanceller(p, 1); ast_setstate(chan, AST_STATE_RING); @@ -5696,13 +5709,14 @@ static void *pri_dchannel(void *vpri) /* Setup law */ if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { /* Just announce proceeding */ - pri->pvts[chanpos]->proceeding = 1; + pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING; pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); + } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) { + pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_CONNECT; + pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); } else { - if (pri->switchtype != PRI_SWITCH_GR303_TMC) - pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); - else - pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); + pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_OVERLAP; + pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); } /* Start PBX */ @@ -5786,6 +5800,21 @@ static void *pri_dchannel(void *vpri) sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel, e->ring.subcmds, e->ring.call); + if (!pri->pvts[chanpos]->digital + && !pri->pvts[chanpos]->no_b_channel) { + /* + * Call has a channel. + * Indicate that we are providing dialtone. + */ + pri->pvts[chanpos]->progress = 1;/* No need to send plain PROGRESS again. */ +#ifdef HAVE_PRI_PROG_W_CAUSE + pri_progress_with_cause(pri->pri, e->ring.call, + PVT_TO_CHANNEL(pri->pvts[chanpos]), 1, -1);/* no cause at all */ +#else + pri_progress(pri->pri, e->ring.call, + PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); +#endif + } } if (c && !ast_pthread_create_detached(&threadid, NULL, pri_ss_thread, pri->pvts[chanpos])) { ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", @@ -5944,7 +5973,9 @@ static void *pri_dchannel(void *vpri) sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCNR); sig_pri_set_echocanceller(pri->pvts[chanpos], 1); pri_queue_control(pri, chanpos, AST_CONTROL_RINGING); - pri->pvts[chanpos]->alerting = 1; + if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_ALERTING) { + pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_ALERTING; + } if ( #ifdef PRI_PROGRESS_MASK @@ -6031,11 +6062,11 @@ static void *pri_dchannel(void *vpri) sig_pri_lock_private(pri->pvts[chanpos]); sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel, e->proceeding.subcmds, e->proceeding.call); - if (!pri->pvts[chanpos]->proceeding) { + if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) { + pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING; ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); pri_queue_control(pri, chanpos, AST_CONTROL_PROCEEDING); - pri->pvts[chanpos]->proceeding = 1; } if (!pri->pvts[chanpos]->progress && !pri->pvts[chanpos]->no_b_channel @@ -6170,7 +6201,9 @@ static void *pri_dchannel(void *vpri) #endif /* defined(HAVE_PRI_CALL_WAITING) */ sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel, e->answer.subcmds, e->answer.call); - pri->pvts[chanpos]->proceeding = 1; + if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_CONNECT) { + pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_CONNECT; + } sig_pri_open_media(pri->pvts[chanpos]); pri_queue_control(pri, chanpos, AST_CONTROL_ANSWER); /* Enable echo cancellation if it's not on already */ @@ -6593,16 +6626,36 @@ static void *pri_dchannel(void *vpri) } else { chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); if (chanpos > -1) { + unsigned int len; + sig_pri_lock_private(pri->pvts[chanpos]); sig_pri_handle_subcmds(pri, chanpos, e->e, e->setup_ack.channel, e->setup_ack.subcmds, e->setup_ack.call); - pri->pvts[chanpos]->setup_ack = 1; + if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_OVERLAP) { + pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_OVERLAP; + } + /* Send any queued digits */ - for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { + len = strlen(pri->pvts[chanpos]->dialdest); + for (x = 0; x < len; ++x) { ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); pri_information(pri->pri, pri->pvts[chanpos]->call, pri->pvts[chanpos]->dialdest[x]); } + + if (!pri->pvts[chanpos]->progress + && (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING) + && !pri->pvts[chanpos]->digital + && !pri->pvts[chanpos]->no_b_channel) { + /* + * Call has a channel. + * Indicate for overlap dialing that dialtone may be present. + */ + pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS); + pri->pvts[chanpos]->progress = 1;/* Claim to have seen inband-information */ + sig_pri_set_dialing(pri->pvts[chanpos], 0); + sig_pri_open_media(pri->pvts[chanpos]); + } sig_pri_unlock_private(pri->pvts[chanpos]); } else ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); @@ -6738,10 +6791,8 @@ int sig_pri_hangup(struct sig_pri_chan *p, struct ast_channel *ast) ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1); } #endif /* defined(HAVE_PRI_CALL_WAITING) */ - p->proceeding = 0; + p->call_level = SIG_PRI_CALL_LEVEL_IDLE; p->progress = 0; - p->alerting = 0; - p->setup_ack = 0; p->cid_num[0] = '\0'; p->cid_subaddr[0] = '\0'; p->cid_name[0] = '\0'; @@ -7302,6 +7353,8 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i ast_log(LOG_WARNING, "Unable to setup CC recall call to device %s\n", device_name); ao2_ref(monitor, -1); + pri_destroycall(p->pri->pri, p->call); + p->call = NULL; pri_rel(p->pri); pri_sr_free(sr); return -1; @@ -7318,10 +7371,13 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i if (core_id == -1 && pri_setup(p->pri->pri, p->call, sr)) { ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); + pri_destroycall(p->pri->pri, p->call); + p->call = NULL; pri_rel(p->pri); pri_sr_free(sr); return -1; } + p->call_level = SIG_PRI_CALL_LEVEL_SETUP; pri_sr_free(sr); ast_setstate(ast, AST_STATE_DIALING); sig_pri_set_dialing(p, 1); @@ -7339,11 +7395,16 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi chan->hangupcause = AST_CAUSE_USER_BUSY; chan->_softhangup |= AST_SOFTHANGUP_DEV; res = 0; - } else if (!p->progress && p->pri && !p->outgoing) { - if (p->pri->pri) { + break; + } + res = sig_pri_play_tone(p, SIG_PRI_TONE_BUSY); + if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) { + chan->hangupcause = AST_CAUSE_USER_BUSY; + p->progress = 1;/* No need to send plain PROGRESS after this. */ + if (p->pri && p->pri->pri) { if (!pri_grab(p, p->pri)) { #ifdef HAVE_PRI_PROG_W_CAUSE - pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_USER_BUSY); /* cause = 17 */ + pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause); #else pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); #endif @@ -7352,13 +7413,12 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span); } } - p->progress = 1; - res = sig_pri_play_tone(p, SIG_PRI_TONE_BUSY); } break; case AST_CONTROL_RINGING: - if ((!p->alerting) && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { - if (p->pri->pri) { + if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) { + p->call_level = SIG_PRI_CALL_LEVEL_ALERTING; + if (p->pri && p->pri->pri) { if (!pri_grab(p, p->pri)) { pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), p->no_b_channel || p->digital ? 0 : 1); @@ -7367,7 +7427,6 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span); } } - p->alerting = 1; } res = sig_pri_play_tone(p, SIG_PRI_TONE_RINGTONE); if (chan->_state != AST_STATE_UP) { @@ -7377,12 +7436,12 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi break; case AST_CONTROL_PROCEEDING: ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); - if (!p->proceeding && p->pri && !p->outgoing) { - if (p->pri->pri) { + if (p->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING && !p->outgoing) { + p->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING; + if (p->pri && p->pri->pri) { if (!pri_grab(p, p->pri)) { pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), p->no_b_channel || p->digital ? 0 : 1); - p->proceeding = 1; if (!p->no_b_channel && !p->digital) { sig_pri_set_dialing(p, 0); } @@ -7398,8 +7457,10 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi case AST_CONTROL_PROGRESS: ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); sig_pri_set_digital(p, 0); /* Digital-only calls isn't allowing any inband progress messages */ - if (!p->progress && !p->alerting && p->pri && !p->outgoing && !p->no_b_channel) { - if (p->pri->pri) { + if (!p->progress && p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing + && !p->no_b_channel) { + p->progress = 1;/* No need to send plain PROGRESS again. */ + if (p->pri && p->pri->pri) { if (!pri_grab(p, p->pri)) { #ifdef HAVE_PRI_PROG_W_CAUSE pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1); /* no cause at all */ @@ -7411,22 +7472,45 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span); } } - p->progress = 1; } /* don't continue in ast_indicate */ res = 0; break; case AST_CONTROL_CONGESTION: - chan->hangupcause = AST_CAUSE_CONGESTION; if (p->priindication_oob || p->no_b_channel) { - chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; + /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */ + switch (chan->hangupcause) { + case AST_CAUSE_USER_BUSY: + case AST_CAUSE_NORMAL_CLEARING: + case 0:/* Cause has not been set. */ + /* Supply a more appropriate cause. */ + chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; + break; + default: + break; + } chan->_softhangup |= AST_SOFTHANGUP_DEV; res = 0; - } else if (!p->progress && p->pri && !p->outgoing) { - if (p->pri->pri) { + break; + } + res = sig_pri_play_tone(p, SIG_PRI_TONE_CONGESTION); + if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) { + /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */ + switch (chan->hangupcause) { + case AST_CAUSE_USER_BUSY: + case AST_CAUSE_NORMAL_CLEARING: + case 0:/* Cause has not been set. */ + /* Supply a more appropriate cause. */ + chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; + break; + default: + break; + } + p->progress = 1;/* No need to send plain PROGRESS after this. */ + if (p->pri && p->pri->pri) { if (!pri_grab(p, p->pri)) { #ifdef HAVE_PRI_PROG_W_CAUSE - pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION); /* cause = 42 */ + pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause); #else pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); #endif @@ -7435,8 +7519,6 @@ int sig_pri_indicate(struct sig_pri_chan *p, struct ast_channel *chan, int condi ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span); } } - p->progress = 1; - res = sig_pri_play_tone(p, SIG_PRI_TONE_CONGESTION); } break; case AST_CONTROL_HOLD: @@ -7561,7 +7643,9 @@ int sig_pri_answer(struct sig_pri_chan *p, struct ast_channel *ast) p->aoc_s_request_invoke_id_valid = 0; } #endif /* defined(HAVE_PRI_AOC_EVENTS) */ - p->proceeding = 1; + if (p->call_level < SIG_PRI_CALL_LEVEL_CONNECT) { + p->call_level = SIG_PRI_CALL_LEVEL_CONNECT; + } sig_pri_set_dialing(p, 0); sig_pri_open_media(p); res = pri_answer(p->pri->pri, p->call, 0, !p->digital); @@ -7690,22 +7774,37 @@ int sig_pri_available(struct sig_pri_chan **pvt, int is_specific_channel) * functions should handle it normally (generate inband DTMF) */ int sig_pri_digit_begin(struct sig_pri_chan *pvt, struct ast_channel *ast, char digit) { - if ((ast->_state == AST_STATE_DIALING) && !pvt->proceeding) { - if (pvt->setup_ack) { + if (ast->_state == AST_STATE_DIALING) { + if (pvt->call_level < SIG_PRI_CALL_LEVEL_OVERLAP) { + unsigned int len; + + len = strlen(pvt->dialdest); + if (len < sizeof(pvt->dialdest) - 1) { + ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", + digit); + pvt->dialdest[len++] = digit; + pvt->dialdest[len] = '\0'; + } else { + ast_log(LOG_WARNING, + "Span %d: Deferred digit buffer overflow for digit '%c'.\n", + pvt->pri->span, digit); + } + return 0; + } + if (pvt->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) { if (!pri_grab(pvt, pvt->pri)) { pri_information(pvt->pri->pri, pvt->call, digit); pri_rel(pvt->pri); } else { ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->pri->span); } - } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { - int res; - ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit); - res = strlen(pvt->dialdest); - pvt->dialdest[res++] = digit; - pvt->dialdest[res] = '\0'; + return 0; + } + if (pvt->call_level < SIG_PRI_CALL_LEVEL_CONNECT) { + ast_log(LOG_WARNING, + "Span %d: Digit '%c' may be ignored by peer. (Call level:%d)\n", + pvt->pri->span, digit, pvt->call_level); } - return 0; } return 1; } diff --git a/channels/sig_pri.h b/channels/sig_pri.h index 2832bd5d3..1c3750800 100644 --- a/channels/sig_pri.h +++ b/channels/sig_pri.h @@ -144,6 +144,22 @@ enum sig_pri_moh_event { SIG_PRI_MOH_EVENT_NUM }; +/*! Call establishment life cycle level for simple comparisons. */ +enum sig_pri_call_level { + /*! Call does not exist. */ + SIG_PRI_CALL_LEVEL_IDLE, + /*! Call is present but has no response yet. (SETUP) */ + SIG_PRI_CALL_LEVEL_SETUP, + /*! Call is collecting digits for overlap dialing. (SETUP ACKNOWLEDGE) */ + SIG_PRI_CALL_LEVEL_OVERLAP, + /*! Call routing is happening. (PROCEEDING) */ + SIG_PRI_CALL_LEVEL_PROCEEDING, + /*! Called party is being alerted of the call. (ALERTING) */ + SIG_PRI_CALL_LEVEL_ALERTING, + /*! Call is connected/answered. (CONNECT) */ + SIG_PRI_CALL_LEVEL_CONNECT, +}; + struct sig_pri_span; struct sig_pri_callback { @@ -274,13 +290,10 @@ struct sig_pri_chan { unsigned int holding_aoce:1; /*!< received AOC-E msg from asterisk. holding for disconnect/release */ #endif /* defined(HAVE_PRI_AOC_EVENTS) */ unsigned int inalarm:1; - unsigned int alerting:1; /*!< TRUE if channel is alerting/ringing */ unsigned int alreadyhungup:1; /*!< TRUE if the call has already gone/hungup */ unsigned int isidlecall:1; /*!< TRUE if this is an idle call */ - unsigned int proceeding:1; /*!< TRUE if call is in a proceeding state */ - unsigned int progress:1; /*!< TRUE if the call has seen progress through the network */ + unsigned int progress:1; /*!< TRUE if the call has seen inband-information progress through the network */ unsigned int resetting:1; /*!< TRUE if this channel is being reset/restarted */ - unsigned int setup_ack:1; /*!< TRUE if this channel has received a SETUP_ACKNOWLEDGE */ unsigned int outgoing:1; unsigned int digital:1; @@ -296,6 +309,8 @@ struct sig_pri_chan { struct sig_pri_span *pri; q931_call *call; /*!< opaque libpri call control structure */ + /*! Call establishment life cycle level for simple comparisons. */ + enum sig_pri_call_level call_level; int prioffset; /*!< channel number in span */ int logicalspan; /*!< logical span number within trunk group */ int mastertrunkgroup; /*!< what trunk group is our master */ diff --git a/channels/sig_ss7.c b/channels/sig_ss7.c index 7e1f76aa4..68ebc5a10 100644 --- a/channels/sig_ss7.c +++ b/channels/sig_ss7.c @@ -431,8 +431,10 @@ static void ss7_start_call(struct sig_ss7_chan *p, struct sig_ss7_linkset *links char tmp[256]; if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) { - p->proceeding = 1; + p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING; isup_acm(ss7, p->ss7call); + } else { + p->call_level = SIG_SS7_CALL_LEVEL_SETUP; } if (linkset->type == SS7_ITU) { @@ -451,7 +453,7 @@ static void ss7_start_call(struct sig_ss7_chan *p, struct sig_ss7_linkset *links ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic); ast_mutex_lock(&linkset->lock); isup_rel(linkset->ss7, p->ss7call, -1); - p->proceeding = 0; + p->call_level = SIG_SS7_CALL_LEVEL_IDLE; p->alreadyhungup = 1; return; } @@ -682,7 +684,9 @@ void *ss7_linkset(void *data) sig_ss7_lock_private(p); switch (e->cpg.event) { case CPG_EVENT_ALERTING: - p->alerting = 1; + if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING) { + p->call_level = SIG_SS7_CALL_LEVEL_ALERTING; + } sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_RINGING); break; case CPG_EVENT_PROGRESS: @@ -925,11 +929,15 @@ void *ss7_linkset(void *data) sig_ss7_lock_private(p); sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_PROCEEDING); - p->proceeding = 1; + if (p->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING) { + p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING; + } sig_ss7_set_dialing(p, 0); /* Send alerting if subscriber is free */ if (e->acm.called_party_status_ind == 1) { - p->alerting = 1; + if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING) { + p->call_level = SIG_SS7_CALL_LEVEL_ALERTING; + } sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_RINGING); } sig_ss7_unlock_private(p); @@ -1033,6 +1041,9 @@ void *ss7_linkset(void *data) } else { p = linkset->pvts[chanpos]; sig_ss7_lock_private(p); + if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) { + p->call_level = SIG_SS7_CALL_LEVEL_CONNECT; + } sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_ANSWER); #if 0 /* This code no longer seems to be necessary so I did not convert it. */ if (p->dsp && p->dsp_features) { @@ -1361,6 +1372,7 @@ int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, char *rdest) if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 )) (isup_far(p->ss7->ss7, p->ss7call)); + p->call_level = SIG_SS7_CALL_LEVEL_SETUP; isup_iam(p->ss7->ss7, p->ss7call); sig_ss7_set_dialing(p, 1); ast_setstate(ast, AST_STATE_DIALING); @@ -1389,10 +1401,9 @@ int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast) p->owner = NULL; sig_ss7_set_dialing(p, 0); + p->call_level = SIG_SS7_CALL_LEVEL_IDLE; p->outgoing = 0; - p->proceeding = 0; p->progress = 0; - p->alerting = 0; p->rlt = 0; p->exten[0] = '\0'; /* Perform low level hangup if no owner left */ @@ -1435,7 +1446,9 @@ int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast) int res; if (!ss7_grab(p, p->ss7)) { - p->proceeding = 1; + if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) { + p->call_level = SIG_SS7_CALL_LEVEL_CONNECT; + } res = isup_anm(p->ss7->ss7, p->ss7call); ss7_rel(p->ss7); } else { @@ -1484,15 +1497,14 @@ int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condi res = sig_ss7_play_tone(p, SIG_SS7_TONE_BUSY); break; case AST_CONTROL_RINGING: - if ((!p->alerting) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) { - if (p->ss7->ss7) { + if (p->call_level < SIG_SS7_CALL_LEVEL_ALERTING && !p->outgoing) { + p->call_level = SIG_SS7_CALL_LEVEL_ALERTING; + if (p->ss7 && p->ss7->ss7) { ss7_grab(p, p->ss7); - if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) p->rlt = 1; if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */ isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING); - p->alerting = 1; ss7_rel(p->ss7); } } @@ -1511,11 +1523,11 @@ int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condi p->rlt = 1; } - if (!p->proceeding && p->ss7 && !p->outgoing) { - if (p->ss7->ss7) { + if (p->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING && !p->outgoing) { + p->call_level = SIG_SS7_CALL_LEVEL_PROCEEDING; + if (p->ss7 && p->ss7->ss7) { ss7_grab(p, p->ss7); isup_acm(p->ss7->ss7, p->ss7call); - p->proceeding = 1; ss7_rel(p->ss7); } } @@ -1524,11 +1536,11 @@ int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condi break; case AST_CONTROL_PROGRESS: ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); - if (!p->progress && p->ss7 && !p->outgoing) { - if (p->ss7->ss7) { + if (!p->progress && p->call_level < SIG_SS7_CALL_LEVEL_ALERTING && !p->outgoing) { + p->progress = 1;/* No need to send inband-information progress again. */ + if (p->ss7 && p->ss7->ss7) { ss7_grab(p, p->ss7); isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO); - p->progress = 1; ss7_rel(p->ss7); /* enable echo canceler here on SS7 calls */ sig_ss7_set_echocanceller(p, 1); diff --git a/channels/sig_ss7.h b/channels/sig_ss7.h index a4cee5211..15b4a2a89 100644 --- a/channels/sig_ss7.h +++ b/channels/sig_ss7.h @@ -84,6 +84,20 @@ enum sig_ss7_law { SIG_SS7_ALAW }; +/*! Call establishment life cycle level for simple comparisons. */ +enum sig_ss7_call_level { + /*! Call does not exist. */ + SIG_SS7_CALL_LEVEL_IDLE, + /*! Call is present but has no response yet. (SETUP) */ + SIG_SS7_CALL_LEVEL_SETUP, + /*! Call routing is happening. (PROCEEDING) */ + SIG_SS7_CALL_LEVEL_PROCEEDING, + /*! Called party is being alerted of the call. (ALERTING) */ + SIG_SS7_CALL_LEVEL_ALERTING, + /*! Call is connected/answered. (CONNECT) */ + SIG_SS7_CALL_LEVEL_CONNECT, +}; + struct sig_ss7_linkset; struct sig_ss7_callback { @@ -120,6 +134,9 @@ struct sig_ss7_chan { /*! \brief Opaque libss7 call control structure */ struct isup_call *ss7call; + /*! Call establishment life cycle level for simple comparisons. */ + enum sig_ss7_call_level call_level; + int channel; /*!< Channel Number */ int cic; /*!< CIC associated with channel */ unsigned int dpc; /*!< CIC's DPC */ @@ -192,15 +209,8 @@ struct sig_ss7_chan { unsigned int inalarm:1; /*! TRUE if this channel is being used for an outgoing call. */ unsigned int outgoing:1; - /*! - * \brief TRUE if call is in a proceeding state. - * The call has started working its way through the network. - */ - unsigned int proceeding:1; - /*! \brief TRUE if the call has seen progress through the network. */ + /*! \brief TRUE if the call has seen inband-information progress through the network. */ unsigned int progress:1; - /*! \brief TRUE if channel is alerting/ringing */ - unsigned int alerting:1; /*! \brief TRUE if the call has already gone/hungup */ unsigned int alreadyhungup:1; /*! \brief XXX BOOLEAN Purpose??? */ |