aboutsummaryrefslogtreecommitdiffstats
path: root/main/channel.c
diff options
context:
space:
mode:
authorjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2009-04-08 21:00:39 +0000
committerjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2009-04-08 21:00:39 +0000
commit91ed7a2ff8a1e10abd2c37ab6c8cf119923b002a (patch)
tree816c68983296dd69b77d7b177dd8a14564f01ddb /main/channel.c
parentbaa1151d7ea9ed724443e88d8573503eb6235418 (diff)
Add timer for features so that backup bridge config can go away
The biggest change done here was elimination of the backup_config for use with features. Previously, the bridging code upon detecting a feature would set the start time of the bridge to the start time of the feature. Then after the feature had either expired or timed out the start time would be reset to the true bridge start time from the backup_config. Now, the time differences are calculated with respect to the newly added feature_start_time timeval instead. There should be no behavior changes from the previous functionality aside from the bridge timing being unaffected by either valid or partial feature matches. Previously the timing would be increased by the length of time configured for featuredigittimeout, which was probably never noticed. (closes issue #14503) Reported by: KNK Tested by: jpeeler Review: http://reviewboard.digium.com/r/179/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@187211 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/channel.c')
-rw-r--r--main/channel.c90
1 files changed, 52 insertions, 38 deletions
diff --git a/main/channel.c b/main/channel.c
index 4fa5ae7ea..acf3f557b 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -4814,7 +4814,7 @@ static void bridge_playfile(struct ast_channel *chan, struct ast_channel *peer,
static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct ast_channel *c1,
struct ast_bridge_config *config, struct ast_frame **fo,
- struct ast_channel **rc, struct timeval bridge_end)
+ struct ast_channel **rc)
{
/* Copy voice back and forth between the two channels. */
struct ast_channel *cs[3];
@@ -4856,13 +4856,17 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
res = AST_BRIDGE_RETRY;
break;
}
- if (bridge_end.tv_sec) {
- to = ast_tvdiff_ms(bridge_end, ast_tvnow());
+ if (config->nexteventts.tv_sec) {
+ to = ast_tvdiff_ms(config->nexteventts, ast_tvnow());
if (to <= 0) {
- if (config->timelimit) {
+ if (config->timelimit && !config->feature_timer && !ast_test_flag(config, AST_FEATURE_WARNING_ACTIVE)) {
res = AST_BRIDGE_RETRY;
/* generic bridge ending to play warning */
ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE);
+ } else if (config->feature_timer) {
+ /* feature timer expired - make sure we do not play warning */
+ ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE);
+ res = AST_BRIDGE_RETRY;
} else {
res = AST_BRIDGE_COMPLETE;
}
@@ -4939,8 +4943,8 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct
/* monitored dtmf causes exit from bridge */
int monitored_source = (who == c0) ? watch_c0_dtmf : watch_c1_dtmf;
- if (monitored_source &&
- (f->frametype == AST_FRAME_DTMF_END ||
+ if (monitored_source &&
+ (f->frametype == AST_FRAME_DTMF_END ||
f->frametype == AST_FRAME_DTMF_BEGIN)) {
*fo = f;
*rc = who;
@@ -4994,13 +4998,13 @@ static void manager_bridge_event(int onoff, int type, struct ast_channel *c0, st
{
manager_event(EVENT_FLAG_CALL, "Bridge",
"Bridgestate: %s\r\n"
- "Bridgetype: %s\r\n"
- "Channel1: %s\r\n"
- "Channel2: %s\r\n"
- "Uniqueid1: %s\r\n"
- "Uniqueid2: %s\r\n"
- "CallerID1: %s\r\n"
- "CallerID2: %s\r\n",
+ "Bridgetype: %s\r\n"
+ "Channel1: %s\r\n"
+ "Channel2: %s\r\n"
+ "Uniqueid1: %s\r\n"
+ "Uniqueid2: %s\r\n"
+ "CallerID1: %s\r\n"
+ "CallerID2: %s\r\n",
onoff ? "Link" : "Unlink",
type == 1 ? "core" : "native",
c0->name, c1->name, c0->uniqueid, c1->uniqueid,
@@ -5079,7 +5083,6 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
struct ast_channel *who = NULL;
enum ast_bridge_result res = AST_BRIDGE_COMPLETE;
int nativefailed=0;
- int firstpass;
int o0nativeformats;
int o1nativeformats;
long time_left_ms=0;
@@ -5103,21 +5106,17 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
return -1;
*fo = NULL;
- firstpass = config->firstpass;
- config->firstpass = 0;
- if (ast_tvzero(config->start_time))
+ if (ast_tvzero(config->start_time)) {
config->start_time = ast_tvnow();
- time_left_ms = config->timelimit;
-
- caller_warning = ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING);
- callee_warning = ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING);
-
- if (config->start_sound && firstpass) {
- if (caller_warning)
- bridge_playfile(c0, c1, config->start_sound, time_left_ms / 1000);
- if (callee_warning)
- bridge_playfile(c1, c0, config->start_sound, time_left_ms / 1000);
+ if (config->start_sound) {
+ if (caller_warning) {
+ bridge_playfile(c0, c1, config->start_sound, config->timelimit / 1000);
+ }
+ if (callee_warning) {
+ bridge_playfile(c1, c0, config->start_sound, config->timelimit / 1000);
+ }
+ }
}
/* Keep track of bridge */
@@ -5129,11 +5128,26 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
o1nativeformats = c1->nativeformats;
if (config->feature_timer && !ast_tvzero(config->nexteventts)) {
- config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->feature_timer, 1000));
- } else if (config->timelimit && firstpass) {
+ config->nexteventts = ast_tvadd(config->feature_start_time, ast_samp2tv(config->feature_timer, 1000));
+ } else if (config->timelimit) {
+ time_left_ms = config->timelimit - ast_tvdiff_ms(ast_tvnow(), config->start_time);
+ caller_warning = ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING);
+ callee_warning = ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING);
config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
- if (caller_warning || callee_warning)
- config->nexteventts = ast_tvsub(config->nexteventts, ast_samp2tv(config->play_warning, 1000));
+ if ((caller_warning || callee_warning) && config->play_warning) {
+ long next_warn = config->play_warning;
+ if (time_left_ms < config->play_warning) {
+ /* At least one warning was played, which means we are returning after feature */
+ long warns_passed = (config->play_warning - time_left_ms) / config->warning_freq;
+ /* It is 'warns_passed * warning_freq' NOT '(warns_passed + 1) * warning_freq',
+ because nexteventts will be updated once again in the 'if (!to)' block */
+ next_warn = config->play_warning - warns_passed * config->warning_freq;
+ }
+ config->nexteventts = ast_tvsub(config->nexteventts, ast_samp2tv(next_warn, 1000));
+ }
+ } else {
+ config->nexteventts.tv_sec = 0;
+ config->nexteventts.tv_usec = 0;
}
if (!c0->tech->send_digit_begin)
@@ -5189,10 +5203,12 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
if (callee_warning)
bridge_playfile(c1, c0, config->warning_sound, t);
}
- if (config->warning_freq && (time_left_ms > (config->warning_freq + 5000)))
+
+ if (config->warning_freq && (time_left_ms > (config->warning_freq + 5000))) {
config->nexteventts = ast_tvadd(config->nexteventts, ast_samp2tv(config->warning_freq, 1000));
- else
+ } else {
config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
+ }
}
ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE);
}
@@ -5237,7 +5253,6 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
ast_set_flag(c0, AST_FLAG_NBRIDGE);
ast_set_flag(c1, AST_FLAG_NBRIDGE);
if ((res = c0->tech->bridge(c0, c1, config->flags, fo, rc, to)) == AST_BRIDGE_COMPLETE) {
- /* \todo XXX here should check that cid_num is not NULL */
manager_event(EVENT_FLAG_CALL, "Unlink",
"Channel1: %s\r\n"
"Channel2: %s\r\n"
@@ -5245,7 +5260,7 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
"Uniqueid2: %s\r\n"
"CallerID1: %s\r\n"
"CallerID2: %s\r\n",
- c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num);
+ c0->name, c1->name, c0->uniqueid, c1->uniqueid, S_OR(c0->cid.cid_num, "<unknown>"), S_OR(c1->cid.cid_num, "<unknown>"));
ast_debug(1, "Returning from native bridge, channels: %s, %s\n", c0->name, c1->name);
ast_clear_flag(c0, AST_FLAG_NBRIDGE);
@@ -5291,7 +5306,7 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
update_bridge_vars(c0, c1);
- res = ast_generic_bridge(c0, c1, config, fo, rc, config->nexteventts);
+ res = ast_generic_bridge(c0, c1, config, fo, rc);
if (res != AST_BRIDGE_RETRY) {
break;
} else if (config->feature_timer) {
@@ -5310,7 +5325,6 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
c0->_bridge = NULL;
c1->_bridge = NULL;
- /* \todo XXX here should check that cid_num is not NULL */
manager_event(EVENT_FLAG_CALL, "Unlink",
"Channel1: %s\r\n"
"Channel2: %s\r\n"
@@ -5318,7 +5332,7 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
"Uniqueid2: %s\r\n"
"CallerID1: %s\r\n"
"CallerID2: %s\r\n",
- c0->name, c1->name, c0->uniqueid, c1->uniqueid, c0->cid.cid_num, c1->cid.cid_num);
+ c0->name, c1->name, c0->uniqueid, c1->uniqueid, S_OR(c0->cid.cid_num, "<unknown>"), S_OR(c1->cid.cid_num, "<unknown>"));
ast_debug(1, "Bridge stops bridging channels %s and %s\n", c0->name, c1->name);
return res;