aboutsummaryrefslogtreecommitdiffstats
path: root/channel.c
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2005-10-13 18:27:54 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2005-10-13 18:27:54 +0000
commit9ebd430cd31aa8d6e76c75db03d77ce0025637b9 (patch)
treeb5afd966e15542b9db79d321c8bae141fe961d5f /channel.c
parent5a5fc722ebbfa54d4fc8f8bdb61efb29d0f1f0f6 (diff)
Fix call timeouts with rtp bridge etc (bug #5252)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@6759 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channel.c')
-rwxr-xr-xchannel.c97
1 files changed, 38 insertions, 59 deletions
diff --git a/channel.c b/channel.c
index 3ffeebaef..cf972e952 100755
--- a/channel.c
+++ b/channel.c
@@ -264,12 +264,14 @@ int ast_shutting_down(void)
void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
{
time_t myt;
+ struct ast_frame fr = { AST_FRAME_NULL, };
time(&myt);
if (offset)
chan->whentohangup = myt + offset;
else
chan->whentohangup = 0;
+ ast_queue_frame(chan, &fr);
return;
}
@@ -2947,18 +2949,16 @@ static void bridge_playfile(struct ast_channel *chan, struct ast_channel *peer,
check = ast_autoservice_stop(peer);
}
-static enum ast_bridge_result ast_generic_bridge(int *playitagain, int *playit, struct ast_channel *c0, struct ast_channel *c1,
- struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
+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, int toms)
{
/* Copy voice back and forth between the two channels. */
struct ast_channel *cs[3];
- int to;
struct ast_frame *f;
struct ast_channel *who = NULL;
enum ast_bridge_result res = AST_BRIDGE_COMPLETE;
int o0nativeformats;
int o1nativeformats;
- long elapsed_ms=0, time_left_ms=0;
int watch_c0_dtmf;
int watch_c1_dtmf;
void *pvt0, *pvt1;
@@ -2980,34 +2980,7 @@ static enum ast_bridge_result ast_generic_bridge(int *playitagain, int *playit,
res = AST_BRIDGE_RETRY;
break;
}
- /* timestamp */
- if (config->timelimit) {
- /* If there is a time limit, return now */
- elapsed_ms = ast_tvdiff_ms(ast_tvnow(), config->start_time);
- time_left_ms = config->timelimit - elapsed_ms;
-
- if (*playitagain &&
- ((ast_test_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING)) ||
- (ast_test_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING))) &&
- (config->play_warning && time_left_ms <= config->play_warning)) {
- if (config->warning_freq == 0 || time_left_ms == config->play_warning || (time_left_ms % config->warning_freq) <= 50) {
- res = AST_BRIDGE_RETRY;
- break;
- }
- }
- if (time_left_ms <= 0) {
- res = AST_BRIDGE_RETRY;
- break;
- }
- if (time_left_ms >= 5000 && *playit) {
- res = AST_BRIDGE_RETRY;
- break;
- }
- to = time_left_ms;
- } else
- to = -1;
-
- who = ast_waitfor_n(cs, 2, &to);
+ who = ast_waitfor_n(cs, 2, &toms);
if (!who) {
ast_log(LOG_DEBUG, "Nobody there, continuing...\n");
if (c0->_softhangup == AST_SOFTHANGUP_UNBRIDGE || c1->_softhangup == AST_SOFTHANGUP_UNBRIDGE) {
@@ -3089,10 +3062,11 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
int firstpass;
int o0nativeformats;
int o1nativeformats;
- long elapsed_ms=0, time_left_ms=0;
- int playit=0, playitagain=1, first_time=1;
+ long time_left_ms=0;
+ struct timeval nexteventts = { 0, };
char caller_warning = 0;
char callee_warning = 0;
+ int to;
if (c0->_bridge) {
ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
@@ -3144,24 +3118,24 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
o0nativeformats = c0->nativeformats;
o1nativeformats = c1->nativeformats;
+ if (config->timelimit) {
+ 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));
+ }
+
for (/* ever */;;) {
+ to = -1;
if (config->timelimit) {
- elapsed_ms = ast_tvdiff_ms(ast_tvnow(), config->start_time);
- time_left_ms = config->timelimit - elapsed_ms;
-
- if (playitagain && (caller_warning || callee_warning) && (config->play_warning && time_left_ms <= config->play_warning)) {
- /* narrowing down to the end */
- if (config->warning_freq == 0) {
- playit = 1;
- first_time = 0;
- playitagain = 0;
- } else if (first_time) {
- playit = 1;
- first_time = 0;
- } else if ((time_left_ms % config->warning_freq) <= 50) {
- playit = 1;
- }
- }
+ struct timeval now;
+ now = ast_tvnow();
+ to = ast_tvdiff_ms(nexteventts, now);
+ if (to < 0)
+ to = 0;
+ time_left_ms = config->timelimit - ast_tvdiff_ms(now, config->start_time);
+ if (time_left_ms < to)
+ to = time_left_ms;
+
if (time_left_ms <= 0) {
if (caller_warning && config->end_sound)
bridge_playfile(c0, c1, config->end_sound, 0);
@@ -3173,12 +3147,18 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
res = 0;
break;
}
- if (time_left_ms >= 5000 && playit) {
- if (caller_warning && config->warning_sound && config->play_warning)
- bridge_playfile(c0, c1, config->warning_sound, time_left_ms / 1000);
- if (callee_warning && config->warning_sound && config->play_warning)
- bridge_playfile(c1, c0, config->warning_sound, time_left_ms / 1000);
- playit = 0;
+
+ if (!to) {
+ if (time_left_ms >= 5000) {
+ if (caller_warning && config->warning_sound && config->play_warning)
+ bridge_playfile(c0, c1, config->warning_sound, time_left_ms / 1000);
+ if (callee_warning && config->warning_sound && config->play_warning)
+ bridge_playfile(c1, c0, config->warning_sound, time_left_ms / 1000);
+ }
+ if (config->warning_freq) {
+ nexteventts = ast_tvadd(nexteventts, ast_samp2tv(config->warning_freq, 1000));
+ } else
+ nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
}
}
@@ -3218,7 +3198,7 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
ast_verbose(VERBOSE_PREFIX_3 "Attempting native bridge of %s and %s\n", c0->name, c1->name);
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)) == AST_BRIDGE_COMPLETE) {
+ if ((res = c0->tech->bridge(c0, c1, config->flags, fo, rc, to)) == AST_BRIDGE_COMPLETE) {
manager_event(EVENT_FLAG_CALL, "Unlink",
"Channel1: %s\r\n"
"Channel2: %s\r\n"
@@ -3275,8 +3255,7 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
o0nativeformats = c0->nativeformats;
o1nativeformats = c1->nativeformats;
}
-
- res = ast_generic_bridge(&playitagain, &playit, c0, c1, config, fo, rc);
+ res = ast_generic_bridge(c0, c1, config, fo, rc, to);
if (res != AST_BRIDGE_RETRY)
break;
}