diff options
Diffstat (limited to 'main/channel.c')
-rw-r--r-- | main/channel.c | 90 |
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; |