Modify bridging to properly evaluate DTMF after first warning is played

The main problem is currently if the Dial flag L is used with a warning sound,
DTMF is not evaluated after the first warning sound. To fix this, a flag has 
been added in ast_generic_bridge for playing the warning which ensures that if
a scheduled warning is missed, multiple warrnings are not played back (due to a
feature evaluation or waiting for digits). ast_channel_bridge was modified to
store the nexteventts in the ast_bridge_config structure as that information
was lost every time ast_channel_bridge was reentered, causing a hangup due to
incorrect time calculations.

(closes issue #14315)
Reported by: tim_ringenbach

Reviewed on reviewboard:
http://reviewboard.digium.com/r/163/



git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@176701 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Jeff Peeler 17 years ago
parent 7799945eb9
commit de8f6bab86

@ -529,12 +529,14 @@ enum {
AST_FEATURE_AUTOMON = (1 << 4),
AST_FEATURE_PARKCALL = (1 << 5),
AST_FEATURE_NO_H_EXTEN = (1 << 6),
AST_FEATURE_WARNING_ACTIVE = (1 << 7),
};
struct ast_bridge_config {
struct ast_flags features_caller;
struct ast_flags features_callee;
struct timeval start_time;
struct timeval nexteventts;
long feature_timer;
long timelimit;
long play_warning;

@ -3933,10 +3933,13 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
if (bridge_end.tv_sec) {
to = ast_tvdiff_ms(bridge_end, ast_tvnow());
if (to <= 0) {
if (config->timelimit)
if (config->timelimit) {
res = AST_BRIDGE_RETRY;
else
/* generic bridge ending to play warning */
ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE);
} else {
res = AST_BRIDGE_COMPLETE;
}
break;
}
} else
@ -4018,6 +4021,7 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
ast_log(LOG_DEBUG, "Got DTMF %s on channel (%s)\n",
f->frametype == AST_FRAME_DTMF_END ? "end" : "begin",
who->name);
break;
}
/* Write immediately frames, not passed through jb */
@ -4050,7 +4054,6 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
int o0nativeformats;
int o1nativeformats;
long time_left_ms=0;
struct timeval nexteventts = { 0, };
char caller_warning = 0;
char callee_warning = 0;
@ -4106,11 +4109,11 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
o1nativeformats = c1->nativeformats;
if (config->feature_timer) {
nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->feature_timer, 1000));
} else if (config->timelimit) {
nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->feature_timer, 1000));
} else if (config->timelimit && firstpass) {
config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
if (caller_warning || callee_warning)
nexteventts = ast_tvsub(nexteventts, ast_samp2tv(config->play_warning, 1000));
config->nexteventts = ast_tvsub(config->nexteventts, ast_samp2tv(config->play_warning, 1000));
}
if (!c0->tech->send_digit_begin)
@ -4128,9 +4131,9 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
to = -1;
if (!ast_tvzero(nexteventts)) {
if (!ast_tvzero(config->nexteventts)) {
now = ast_tvnow();
to = ast_tvdiff_ms(nexteventts, now);
to = ast_tvdiff_ms(config->nexteventts, now);
if (to <= 0) {
if (!config->timelimit) {
res = AST_BRIDGE_COMPLETE;
@ -4158,7 +4161,7 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
}
if (!to) {
if (time_left_ms >= 5000 && config->warning_sound && config->play_warning) {
if (time_left_ms >= 5000 && config->warning_sound && config->play_warning && ast_test_flag(config, AST_FEATURE_WARNING_ACTIVE)) {
int t = (time_left_ms + 500) / 1000; /* round to nearest second */
if (caller_warning)
bridge_playfile(c0, c1, config->warning_sound, t);
@ -4166,10 +4169,11 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
bridge_playfile(c1, c0, config->warning_sound, t);
}
if (config->warning_freq && (time_left_ms > (config->warning_freq + 5000)))
nexteventts = ast_tvadd(nexteventts, ast_samp2tv(config->warning_freq, 1000));
config->nexteventts = ast_tvadd(config->nexteventts, ast_samp2tv(config->warning_freq, 1000));
else
nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
}
ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE);
}
if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) {
@ -4283,9 +4287,13 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
if (!ast_strlen_zero(pbx_builtin_getvar_helper(c1, "BRIDGEPEER")))
pbx_builtin_setvar_helper(c1, "BRIDGEPEER", c0->name);
res = ast_generic_bridge(c0, c1, config, fo, rc, nexteventts);
if (res != AST_BRIDGE_RETRY)
res = ast_generic_bridge(c0, c1, config, fo, rc, config->nexteventts);
if (res != AST_BRIDGE_RETRY) {
break;
} else if (config->feature_timer) {
/* feature timer expired but has not been updated, sending to ast_bridge_call to do so */
break;
}
}
ast_clear_flag(c0, AST_FLAG_END_DTMF_ONLY);

@ -1730,7 +1730,15 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
if (config->feature_timer) {
/* Update time limit for next pass */
diff = ast_tvdiff_ms(ast_tvnow(), config->start_time);
config->feature_timer -= diff;
if (res == AST_BRIDGE_RETRY) {
/* The feature fully timed out but has not been updated. Skip
* the potential round error from the diff calculation and
* explicitly set to expired. */
config->feature_timer = -1;
} else {
config->feature_timer -= diff;
}
if (hasfeatures) {
/* Running on backup config, meaning a feature might be being
activated, but that's no excuse to keep things going

Loading…
Cancel
Save