Merged revisions 303769 via svnmerge from

https://origsvn.digium.com/svn/asterisk/branches/1.6.2

................
  r303769 | rmudgett | 2011-01-25 11:42:42 -0600 (Tue, 25 Jan 2011) | 47 lines
  
  Merged revisions 303765 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.4
  
  ........
    r303765 | rmudgett | 2011-01-25 11:36:50 -0600 (Tue, 25 Jan 2011) | 40 lines
    
    Sending out unnecessary PROCEEDING messages breaks overlap dialing.
    
    Issue #16789 was a good idea.  Unfortunately, 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 in
    non-dial through extensions.
    
    * Effectively revert issue #16789.
    
    * Allow outgoing overlap dialing to hear dialtone and other early media.
    A PROGRESS "inband-information is now available" message is now sent after
    the SETUP_ACKNOWLEDGE message for non-digital calls.  An
    AST_CONTROL_PROGRESS is now generated for incoming SETUP_ACKNOWLEDGE
    messages for non-digital calls.
    
    * Handling of the AST_CONTROL_CONGESTION in chan_dahdi/sig_pri was
    inconsistent with the cause codes.
    
    * Added better protection from sending out of sequence messages by
    combining several flags into a single enum value representing call
    progress level.
    
    * Added diagnostic messages for deferred overlap digits handling corner
    cases.
    
    (closes issue #17085)
    Reported by: shawkris
    
    (closes issue #18509)
    Reported by: wimpy
    Patches:
          issue18509_early_media_v1.8_v3.patch uploaded by rmudgett (license 664)
          Expanded upon issue18509_early_media_v1.8_v3.patch to include analog
          and SS7 because of backporting requirements.
    Tested by: wimpy, rmudgett
  ........
................


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@303771 65c4cc65-6c06-0410-ace0-fbb531ad65f3
certified/1.8.6
Richard Mudgett 15 years ago
parent b18db77287
commit 8e51d30b67

@ -7660,7 +7660,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 */
@ -7680,7 +7680,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 */
@ -8931,7 +8931,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)))) {
@ -9164,7 +9164,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);

@ -1223,12 +1223,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)
@ -1240,12 +1237,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)
@ -1253,6 +1247,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) */
@ -1637,12 +1633,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);
@ -1650,6 +1662,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);
@ -4837,13 +4850,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 */
@ -4927,6 +4941,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",
@ -5085,7 +5114,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
@ -5172,11 +5203,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
@ -5311,7 +5342,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 */
@ -5734,16 +5767,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);
@ -5874,10 +5927,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';
@ -6437,6 +6488,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;
@ -6453,10 +6506,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);
@ -6474,11 +6530,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
@ -6487,13 +6548,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);
@ -6502,7 +6562,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) {
@ -6512,12 +6571,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);
}
@ -6533,8 +6592,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 */
@ -6546,22 +6607,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
@ -6570,8 +6654,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:
@ -6689,7 +6771,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);
@ -6818,22 +6902,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;
}

@ -83,6 +83,22 @@ enum sig_pri_law {
SIG_PRI_ALAW
};
/*! 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 {
@ -210,13 +226,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;
@ -232,6 +245,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 */

@ -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);

@ -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??? */

Loading…
Cancel
Save