mirror of
https://github.com/asterisk/asterisk.git
synced 2026-06-25 18:06:40 -07:00
Fix call timeouts with rtp bridge etc (bug #5252)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6759 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -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;
|
||||
|
||||
for (/* ever */;;) {
|
||||
if (config->timelimit) {
|
||||
elapsed_ms = ast_tvdiff_ms(ast_tvnow(), config->start_time);
|
||||
time_left_ms = config->timelimit - elapsed_ms;
|
||||
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) {
|
||||
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 (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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -725,7 +725,7 @@ static struct ast_frame *iax2_read(struct ast_channel *c);
|
||||
static int iax2_write(struct ast_channel *c, struct ast_frame *f);
|
||||
static int iax2_indicate(struct ast_channel *c, int condition);
|
||||
static int iax2_setoption(struct ast_channel *c, int option, void *data, int datalen);
|
||||
static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
|
||||
static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
|
||||
static int iax2_transfer(struct ast_channel *c, const char *dest);
|
||||
static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan);
|
||||
|
||||
@@ -3082,7 +3082,7 @@ static void unlock_both(unsigned short callno0, unsigned short callno1)
|
||||
ast_mutex_unlock(&iaxsl[callno0]);
|
||||
}
|
||||
|
||||
static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
|
||||
static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
|
||||
{
|
||||
struct ast_channel *cs[3];
|
||||
struct ast_channel *who;
|
||||
@@ -3162,6 +3162,11 @@ static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_cha
|
||||
}
|
||||
to = 1000;
|
||||
who = ast_waitfor_n(cs, 2, &to);
|
||||
if (timeoutms > -1) {
|
||||
timeoutms -= (1000 - to);
|
||||
if (timeoutms < 0)
|
||||
timeoutms = 0;
|
||||
}
|
||||
if (!who) {
|
||||
if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
|
||||
res = AST_BRIDGE_FAILED;
|
||||
|
||||
+3
-4
@@ -337,7 +337,7 @@ static int vpb_hangup(struct ast_channel *ast);
|
||||
static int vpb_answer(struct ast_channel *ast);
|
||||
static struct ast_frame *vpb_read(struct ast_channel *ast);
|
||||
static int vpb_write(struct ast_channel *ast, struct ast_frame *frame);
|
||||
static enum ast_bridge_result vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
|
||||
static enum ast_bridge_result vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
|
||||
static int vpb_indicate(struct ast_channel *ast, int condition);
|
||||
static int vpb_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
|
||||
|
||||
@@ -407,7 +407,7 @@ static struct ast_channel_tech vpb_tech_indicate = {
|
||||
/* #define HALF_DUPLEX_BRIDGE */
|
||||
|
||||
/* This is the Native bridge code, which Asterisk will try before using its own bridging code */
|
||||
static enum ast_bridge_result vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
|
||||
static enum ast_bridge_result vpb_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
|
||||
{
|
||||
struct vpb_pvt *p0 = (struct vpb_pvt *)c0->tech_pvt;
|
||||
struct vpb_pvt *p1 = (struct vpb_pvt *)c1->tech_pvt;
|
||||
@@ -415,7 +415,6 @@ static enum ast_bridge_result vpb_bridge(struct ast_channel *c0, struct ast_chan
|
||||
int res;
|
||||
struct ast_channel *cs[3];
|
||||
struct ast_channel *who;
|
||||
int to = -1;
|
||||
struct ast_frame *f;
|
||||
|
||||
cs[0] = c0;
|
||||
@@ -517,7 +516,7 @@ static enum ast_bridge_result vpb_bridge(struct ast_channel *c0, struct ast_chan
|
||||
/* pthread_cond_wait(&bridges[i].cond, &bridges[i].lock);*/ /* Wait for condition signal. */
|
||||
while( !bridges[i].endbridge ) {
|
||||
/* Are we really ment to be doing nothing ?!?! */
|
||||
who = ast_waitfor_n(cs, 2, &to);
|
||||
who = ast_waitfor_n(cs, 2, &timeoutms);
|
||||
if (!who) {
|
||||
ast_log(LOG_DEBUG, "%s: vpb_bridge: Empty frame read...\n",p0->dev);
|
||||
/* check for hangup / whentohangup */
|
||||
|
||||
+3
-5
@@ -340,7 +340,7 @@ static pthread_t monitor_thread = AST_PTHREADT_NULL;
|
||||
|
||||
static int restart_monitor(void);
|
||||
|
||||
static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
|
||||
static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
|
||||
|
||||
static int zt_sendtext(struct ast_channel *c, const char *text);
|
||||
|
||||
@@ -2940,13 +2940,12 @@ static void enable_dtmf_detect(struct zt_pvt *p)
|
||||
#endif
|
||||
}
|
||||
|
||||
static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
|
||||
static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
|
||||
{
|
||||
struct ast_channel *who;
|
||||
struct zt_pvt *p0, *p1, *op0, *op1;
|
||||
struct zt_pvt *master = NULL, *slave = NULL;
|
||||
struct ast_frame *f;
|
||||
int to;
|
||||
int inconf = 0;
|
||||
int nothingok = 1;
|
||||
int ofd0, ofd1;
|
||||
@@ -3169,8 +3168,7 @@ static enum ast_bridge_result zt_bridge(struct ast_channel *c0, struct ast_chann
|
||||
}
|
||||
#endif
|
||||
|
||||
to = -1;
|
||||
who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &to);
|
||||
who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
|
||||
if (!who) {
|
||||
ast_log(LOG_DEBUG, "Ooh, empty read...\n");
|
||||
continue;
|
||||
|
||||
@@ -145,7 +145,7 @@ struct ast_channel_tech {
|
||||
|
||||
/*! Bridge two channels of the same type together */
|
||||
enum ast_bridge_result (* const bridge)(struct ast_channel *c0, struct ast_channel *c1, int flags,
|
||||
struct ast_frame **fo, struct ast_channel **rc);
|
||||
struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
|
||||
|
||||
/*! Indicate a particular condition (e.g. AST_CONTROL_BUSY or AST_CONTROL_RINGING or AST_CONTROL_CONGESTION */
|
||||
int (* const indicate)(struct ast_channel *c, int condition);
|
||||
|
||||
@@ -148,7 +148,7 @@ char *ast_rtp_lookup_mime_multiple(char *buf, int size, const int capability, co
|
||||
|
||||
void ast_rtp_setnat(struct ast_rtp *rtp, int nat);
|
||||
|
||||
int ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
|
||||
int ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
|
||||
|
||||
int ast_rtp_proto_register(struct ast_rtp_protocol *proto);
|
||||
|
||||
|
||||
@@ -1499,7 +1499,7 @@ static struct ast_rtp_protocol *get_proto(struct ast_channel *chan)
|
||||
/* ast_rtp_bridge: Bridge calls. If possible and allowed, initiate
|
||||
re-invite so the peers exchange media directly outside
|
||||
of Asterisk. */
|
||||
enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc)
|
||||
enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
|
||||
{
|
||||
struct ast_frame *f;
|
||||
struct ast_channel *who, *cs[3];
|
||||
@@ -1513,7 +1513,6 @@ enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel
|
||||
char iabuf[INET_ADDRSTRLEN];
|
||||
|
||||
void *pvt0, *pvt1;
|
||||
int to;
|
||||
int codec0,codec1, oldcodec0, oldcodec1;
|
||||
|
||||
memset(&vt0, 0, sizeof(vt0));
|
||||
@@ -1635,7 +1634,6 @@ enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel
|
||||
}
|
||||
return AST_BRIDGE_RETRY;
|
||||
}
|
||||
to = -1;
|
||||
/* Now check if they have changed address */
|
||||
ast_rtp_get_peer(p1, &t1);
|
||||
ast_rtp_get_peer(p0, &t0);
|
||||
@@ -1677,7 +1675,7 @@ enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel
|
||||
memcpy(&vac0, &vt0, sizeof(vac0));
|
||||
oldcodec0 = codec0;
|
||||
}
|
||||
who = ast_waitfor_n(cs, 2, &to);
|
||||
who = ast_waitfor_n(cs, 2, &timeoutms);
|
||||
if (!who) {
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Ooh, empty read...\n");
|
||||
|
||||
Reference in New Issue
Block a user