aboutsummaryrefslogtreecommitdiffstats
path: root/main/channel.c
diff options
context:
space:
mode:
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;