diff options
author | jpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-02-17 21:54:34 +0000 |
---|---|---|
committer | jpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-02-17 21:54:34 +0000 |
commit | 039864f4847dc5fcb2c26e236e5a8f4aa876f57d (patch) | |
tree | 6d9cf4d3d35924dc9b641732ea157a388a09b2b2 | |
parent | f2fd2b4b98978b606df45cb83e966fd0986bb315 (diff) |
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: http://svn.digium.com/svn/asterisk/branches/1.4@176701 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | include/asterisk/channel.h | 2 | ||||
-rw-r--r-- | main/channel.c | 36 | ||||
-rw-r--r-- | res/res_features.c | 10 |
3 files changed, 33 insertions, 15 deletions
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 957d95d5c..f7718684b 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -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; diff --git a/main/channel.c b/main/channel.c index 159de4c0b..25d45ec0d 100644 --- a/main/channel.c +++ b/main/channel.c @@ -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); diff --git a/res/res_features.c b/res/res_features.c index 7fadaa61a..05bbd7fe4 100644 --- a/res/res_features.c +++ b/res/res_features.c @@ -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 |