diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2005-10-13 18:27:54 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2005-10-13 18:27:54 +0000 |
commit | 9ebd430cd31aa8d6e76c75db03d77ce0025637b9 (patch) | |
tree | b5afd966e15542b9db79d321c8bae141fe961d5f | |
parent | 5a5fc722ebbfa54d4fc8f8bdb61efb29d0f1f0f6 (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
-rwxr-xr-x | channel.c | 97 | ||||
-rwxr-xr-x | channels/chan_iax2.c | 9 | ||||
-rwxr-xr-x | channels/chan_vpb.c | 7 | ||||
-rwxr-xr-x | channels/chan_zap.c | 8 | ||||
-rwxr-xr-x | include/asterisk/channel.h | 2 | ||||
-rwxr-xr-x | include/asterisk/rtp.h | 2 | ||||
-rwxr-xr-x | rtp.c | 6 |
7 files changed, 55 insertions, 76 deletions
@@ -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; } diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 4dae850b8..33d90b90a 100755 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -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; diff --git a/channels/chan_vpb.c b/channels/chan_vpb.c index 948b5e61c..cebe6e2f7 100755 --- a/channels/chan_vpb.c +++ b/channels/chan_vpb.c @@ -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 */ diff --git a/channels/chan_zap.c b/channels/chan_zap.c index c8ab2473b..077eba2f6 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -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; diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 0d7cb6b05..4e6328754 100755 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -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); diff --git a/include/asterisk/rtp.h b/include/asterisk/rtp.h index fd6503c05..a5c3014ea 100755 --- a/include/asterisk/rtp.h +++ b/include/asterisk/rtp.h @@ -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"); |