summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_dial.c14
-rw-r--r--apps/app_jack.c4
-rw-r--r--apps/app_meetme.c2
-rw-r--r--apps/app_queue.c24
-rw-r--r--apps/app_record.c27
-rw-r--r--apps/app_waitforring.c25
-rw-r--r--channels/chan_agent.c14
-rw-r--r--channels/chan_dahdi.c42
-rw-r--r--channels/chan_iax2.c14
-rw-r--r--channels/sig_analog.c22
-rw-r--r--channels/sig_pri.c12
-rw-r--r--include/asterisk/channel.h4
-rw-r--r--include/asterisk/time.h14
-rw-r--r--main/channel.c76
-rw-r--r--main/pbx.c10
-rw-r--r--main/rtp_engine.c16
-rw-r--r--main/utils.c17
-rw-r--r--res/res_fax.c127
18 files changed, 306 insertions, 158 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c
index 310326dc1..b162a4127 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -1116,6 +1116,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
int is_cc_recall;
int cc_frame_received = 0;
int num_ringing = 0;
+ struct timeval start = ast_tvnow();
ast_party_connected_line_init(&connected_caller);
if (single) {
@@ -1158,7 +1159,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
}
#endif
- while (*to && !peer) {
+ while ((*to = ast_remaining_ms(start, orig)) && !peer) {
struct chanlist *o;
int pos = 0; /* how many channels do we handle */
int numlines = prestart;
@@ -1702,10 +1703,13 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
skip_frame:;
ast_frfree(f);
}
- if (!*to)
- ast_verb(3, "Nobody picked up in %d ms\n", orig);
- if (!*to || ast_check_hangup(in))
- ast_cdr_noanswer(ast_channel_cdr(in));
+ }
+
+ if (!*to) {
+ ast_verb(3, "Nobody picked up in %d ms\n", orig);
+ }
+ if (!*to || ast_check_hangup(in)) {
+ ast_cdr_noanswer(ast_channel_cdr(in));
}
#ifdef HAVE_EPOLL
diff --git a/apps/app_jack.c b/apps/app_jack.c
index 10964f462..d1bdfa38f 100644
--- a/apps/app_jack.c
+++ b/apps/app_jack.c
@@ -768,7 +768,9 @@ static int jack_exec(struct ast_channel *chan, const char *data)
while (!jack_data->stop) {
struct ast_frame *f;
- ast_waitfor(chan, -1);
+ if (ast_waitfor(chan, -1) < 0) {
+ break;
+ }
f = ast_read(chan);
if (!f) {
diff --git a/apps/app_meetme.c b/apps/app_meetme.c
index c2bfccd03..da66c5941 100644
--- a/apps/app_meetme.c
+++ b/apps/app_meetme.c
@@ -1917,7 +1917,7 @@ static void conf_flush(int fd, struct ast_channel *chan)
/* when no frames are available, this will wait
for 1 millisecond maximum
*/
- while (ast_waitfor(chan, 1)) {
+ while (ast_waitfor(chan, 1) > 0) {
f = ast_read(chan);
if (f)
ast_frfree(f);
diff --git a/apps/app_queue.c b/apps/app_queue.c
index a6ec76616..775f34348 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -4052,6 +4052,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
#endif
struct ast_party_connected_line connected_caller;
char *inchan_name;
+ struct timeval start_time_tv = ast_tvnow();
ast_party_connected_line_init(&connected_caller);
@@ -4068,7 +4069,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
}
#endif
- while (*to && !peer) {
+ while ((*to = ast_remaining_ms(start_time_tv, orig)) && !peer) {
int numlines, retry, pos = 1;
struct ast_channel *watchers[AST_MAX_WATCHERS];
watchers[0] = in;
@@ -4341,10 +4342,10 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
rna(endtime * 1000, qe, on, membername, qe->parent->autopausebusy);
if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
if (qe->parent->timeoutrestart) {
- *to = orig;
+ start_time_tv = ast_tvnow();
}
/* Have enough time for a queue member to answer? */
- if (*to > 500) {
+ if (ast_remaining_ms(start_time_tv, orig) > 500) {
ring_one(qe, outgoing, &numbusies);
starttime = (long) time(NULL);
}
@@ -4362,9 +4363,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
do_hang(o);
if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
if (qe->parent->timeoutrestart) {
- *to = orig;
+ start_time_tv = ast_tvnow();
}
- if (*to > 500) {
+ if (ast_remaining_ms(start_time_tv, orig) > 500) {
ring_one(qe, outgoing, &numbusies);
starttime = (long) time(NULL);
}
@@ -4457,9 +4458,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
do_hang(o);
if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
if (qe->parent->timeoutrestart) {
- *to = orig;
+ start_time_tv = ast_tvnow();
}
- if (*to > 500) {
+ if (ast_remaining_ms(start_time_tv, orig) > 500) {
ring_one(qe, outgoing, &numbusies);
starttime = (long) time(NULL);
}
@@ -4538,10 +4539,11 @@ skip_frame:;
ast_frfree(f);
}
- if (!*to) {
- for (o = start; o; o = o->call_next) {
- rna(orig, qe, o->interface, o->member->membername, 1);
- }
+ }
+
+ if (!*to) {
+ for (o = start; o; o = o->call_next) {
+ rna(orig, qe, o->interface, o->member->membername, 1);
}
if (ast_channel_cdr(in)
diff --git a/apps/app_record.c b/apps/app_record.c
index ff233d6a9..051f97bb8 100644
--- a/apps/app_record.c
+++ b/apps/app_record.c
@@ -160,7 +160,6 @@ static int record_exec(struct ast_channel *chan, const char *data)
int terminator = '#';
struct ast_format rfmt;
int ioflags;
- int waitres;
struct ast_silence_generator *silgen = NULL;
struct ast_flags flags = { 0, };
AST_DECLARE_APP_ARGS(args,
@@ -169,8 +168,11 @@ static int record_exec(struct ast_channel *chan, const char *data)
AST_APP_ARG(maxduration);
AST_APP_ARG(options);
);
+ int ms;
+ struct timeval start;
ast_format_clear(&rfmt);
+
/* The next few lines of code parse out the filename and header from the input string */
if (ast_strlen_zero(data)) { /* no data implies no filename or anything is present */
ast_log(LOG_WARNING, "Record requires an argument (filename)\n");
@@ -331,14 +333,15 @@ static int record_exec(struct ast_channel *chan, const char *data)
if (maxduration <= 0)
maxduration = -1;
- while ((waitres = ast_waitfor(chan, maxduration)) > -1) {
- if (maxduration > 0) {
- if (waitres == 0) {
- gottimeout = 1;
- pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "TIMEOUT");
- break;
- }
- maxduration = waitres;
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, maxduration))) {
+ ms = ast_waitfor(chan, ms);
+ if (ms < 0) {
+ break;
+ }
+
+ if (maxduration > 0 && ms == 0) {
+ break;
}
f = ast_read(chan);
@@ -390,6 +393,12 @@ static int record_exec(struct ast_channel *chan, const char *data)
}
ast_frfree(f);
}
+
+ if (maxduration > 0 && !ms) {
+ gottimeout = 1;
+ pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "TIMEOUT");
+ }
+
if (!f) {
ast_debug(1, "Got hangup\n");
res = -1;
diff --git a/apps/app_waitforring.c b/apps/app_waitforring.c
index bd0353b07..fc02de303 100644
--- a/apps/app_waitforring.c
+++ b/apps/app_waitforring.c
@@ -63,22 +63,29 @@ static int waitforring_exec(struct ast_channel *chan, const char *data)
struct ast_silence_generator *silgen = NULL;
int res = 0;
double s;
+ int timeout_ms;
int ms;
+ struct timeval start = ast_tvnow();
if (!data || (sscanf(data, "%30lg", &s) != 1)) {
ast_log(LOG_WARNING, "WaitForRing requires an argument (minimum seconds)\n");
return 0;
}
+ if (s < 0.0) {
+ ast_log(LOG_WARNING, "Invalid timeout provided for WaitForRing (%lg)\n", s);
+ return 0;
+ }
+
if (ast_opt_transmit_silence) {
silgen = ast_channel_start_silence_generator(chan);
}
- ms = s * 1000.0;
- while (ms > 0) {
+ timeout_ms = s * 1000.0;
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
ms = ast_waitfor(chan, ms);
if (ms < 0) {
- res = ms;
+ res = -1;
break;
}
if (ms > 0) {
@@ -95,14 +102,12 @@ static int waitforring_exec(struct ast_channel *chan, const char *data)
}
/* Now we're really ready for the ring */
if (!res) {
- ms = 99999999;
- while(ms > 0) {
- ms = ast_waitfor(chan, ms);
- if (ms < 0) {
- res = ms;
+ for (;;) {
+ int wait_res = ast_waitfor(chan, -1);
+ if (wait_res < 0) {
+ res = -1;
break;
- }
- if (ms > 0) {
+ } else {
f = ast_read(chan);
if (!f) {
res = -1;
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index 1c68d1187..0f0c4d288 100644
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -1046,6 +1046,8 @@ static int agent_ack_sleep(void *data)
int res=0;
int to = 1000;
struct ast_frame *f;
+ struct timeval start = ast_tvnow();
+ int ms;
/* Wait a second and look for something */
@@ -1053,12 +1055,14 @@ static int agent_ack_sleep(void *data)
if (!p->chan)
return -1;
- for(;;) {
- to = ast_waitfor(p->chan, to);
- if (to < 0)
+ while ((ms = ast_remaining_ms(start, to))) {
+ ms = ast_waitfor(p->chan, ms);
+ if (ms < 0) {
return -1;
- if (!to)
+ }
+ if (ms == 0) {
return 0;
+ }
f = ast_read(p->chan);
if (!f)
return -1;
@@ -1078,7 +1082,7 @@ static int agent_ack_sleep(void *data)
ast_mutex_unlock(&p->lock);
res = 0;
}
- return res;
+ return 0;
}
static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index b69bf3f07..ce2d23325 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -6240,6 +6240,7 @@ static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
if (res == 0) {
continue;
}
+ res = 0;
f = ast_read(chan);
if (!f) {
ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
@@ -7411,6 +7412,7 @@ static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_ch
int priority = 0;
struct ast_channel *oc0, *oc1;
enum ast_bridge_result res;
+ struct timeval start = ast_tvnow();
#ifdef PRI_2BCT
int triedtopribridge = 0;
q931_call *q931c0;
@@ -7629,6 +7631,7 @@ static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_ch
for (;;) {
struct ast_channel *c0_priority[2] = {c0, c1};
struct ast_channel *c1_priority[2] = {c1, c0};
+ int ms;
/* Here's our main loop... Start by locking things, looking for private parts,
and then balking if anything is wrong */
@@ -7645,8 +7648,8 @@ static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_ch
ast_channel_unlock(c0);
ast_channel_unlock(c1);
-
- if (!timeoutms ||
+ ms = ast_remaining_ms(start, timeoutms);
+ if (!ms ||
(op0 != p0) ||
(op1 != p1) ||
(ofd0 != ast_channel_fd(c0, 0)) ||
@@ -7694,7 +7697,7 @@ static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_ch
}
#endif
- who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
+ who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
if (!who) {
ast_debug(1, "Ooh, empty read...\n");
continue;
@@ -10756,6 +10759,9 @@ static void *analog_ss_thread(void *data)
/* If set to use DTMF CID signalling, listen for DTMF */
if (p->cid_signalling == CID_SIG_DTMF) {
int k = 0;
+ int off_ms;
+ struct timeval start = ast_tvnow();
+ int ms;
cs = NULL;
ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
dahdi_setlinear(p->subs[idx].dfd, 0);
@@ -10766,10 +10772,12 @@ static void *analog_ss_thread(void *data)
* can drop some of them.
*/
ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
- res = 4000;/* This is a typical OFF time between rings. */
+ off_ms = 4000;/* This is a typical OFF time between rings. */
for (;;) {
struct ast_frame *f;
- res = ast_waitfor(chan, res);
+
+ ms = ast_remaining_ms(start, off_ms);
+ res = ast_waitfor(chan, ms);
if (res <= 0) {
/*
* We do not need to restore the dahdi_setlinear()
@@ -10789,7 +10797,7 @@ static void *analog_ss_thread(void *data)
dtmfbuf[k++] = f->subclass.integer;
}
ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
- res = 4000;/* This is a typical OFF time between rings. */
+ start = ast_tvnow();
}
ast_frfree(f);
if (ast_channel_state(chan) == AST_STATE_RING ||
@@ -10812,6 +10820,9 @@ static void *analog_ss_thread(void *data)
} else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
cs = callerid_new(p->cid_signalling);
if (cs) {
+ int off_ms;
+ struct timeval start;
+ int ms;
samples = 0;
#if 1
bump_gains(p);
@@ -10888,10 +10899,13 @@ static void *analog_ss_thread(void *data)
}
/* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
- res = 4000;/* This is a typical OFF time between rings. */
+ start = ast_tvnow();
+ off_ms = 4000;/* This is a typical OFF time between rings. */
for (;;) {
struct ast_frame *f;
- res = ast_waitfor(chan, res);
+
+ ms = ast_remaining_ms(start, off_ms);
+ res = ast_waitfor(chan, ms);
if (res <= 0) {
ast_log(LOG_WARNING, "CID timed out waiting for ring. "
"Exiting simple switch\n");
@@ -11019,12 +11033,18 @@ static void *analog_ss_thread(void *data)
} else if (p->use_callerid && p->cid_start == CID_START_RING) {
if (p->cid_signalling == CID_SIG_DTMF) {
int k = 0;
+ int off_ms;
+ struct timeval start;
+ int ms;
cs = NULL;
dahdi_setlinear(p->subs[idx].dfd, 0);
- res = 2000;
+ off_ms = 2000;
+ start = ast_tvnow();
for (;;) {
struct ast_frame *f;
- res = ast_waitfor(chan, res);
+
+ ms = ast_remaining_ms(start, off_ms);
+ res = ast_waitfor(chan, ms);
if (res <= 0) {
ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
"Exiting simple switch\n");
@@ -11040,7 +11060,7 @@ static void *analog_ss_thread(void *data)
if (f->frametype == AST_FRAME_DTMF) {
dtmfbuf[k++] = f->subclass.integer;
ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
- res = 2000;
+ start = ast_tvnow();
}
ast_frfree(f);
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 272ad832b..758b2bca2 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -5627,6 +5627,11 @@ static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_cha
}
to = 1000;
who = ast_waitfor_n(cs, 2, &to);
+ /* XXX This will need to be updated to calculate
+ * timeout correctly once timeoutms is allowed to be
+ * > 0. Right now, this can go badly if the waitfor
+ * times out in less than a millisecond
+ */
if (timeoutms > -1) {
timeoutms -= (1000 - to);
if (timeoutms < 0)
@@ -13893,6 +13898,8 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
/* By here we must have a dp */
if (dp->flags & CACHE_FLAG_PENDING) {
+ struct timeval start;
+ int ms;
/* Okay, here it starts to get nasty. We need a pipe now to wait
for a reply to come back so long as it's pending */
for (x = 0; x < ARRAY_LEN(dp->waiters); x++) {
@@ -13917,8 +13924,9 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
if (chan)
old = ast_channel_defer_dtmf(chan);
doabort = 0;
- while(timeout) {
- c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout))) {
+ c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &ms);
if (outfd > -1)
break;
if (!c)
@@ -13929,7 +13937,7 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
}
ast_frfree(f);
}
- if (!timeout) {
+ if (!ms) {
ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
}
AST_LIST_LOCK(&dpcache);
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index 395f1a520..593d033b4 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -2391,6 +2391,9 @@ static void *__analog_ss_thread(void *data)
if (p->cid_signalling == CID_SIG_DTMF) {
int k = 0;
int oldlinearity;
+ int timeout_ms;
+ int ms;
+ struct timeval start = ast_tvnow();
cs = NULL;
ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
@@ -2403,10 +2406,12 @@ static void *__analog_ss_thread(void *data)
* can drop some of them.
*/
ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
- res = 4000;/* This is a typical OFF time between rings. */
+ timeout_ms = 4000;/* This is a typical OFF time between rings. */
for (;;) {
struct ast_frame *f;
- res = ast_waitfor(chan, res);
+
+ ms = ast_remaining_ms(start, timeout_ms);
+ res = ast_waitfor(chan, ms);
if (res <= 0) {
/*
* We do not need to restore the analog_set_linear_mode()
@@ -2427,7 +2432,7 @@ static void *__analog_ss_thread(void *data)
dtmfbuf[k++] = f->subclass.integer;
}
ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
- res = 4000;/* This is a typical OFF time between rings. */
+ start = ast_tvnow();
}
ast_frfree(f);
if (ast_channel_state(chan) == AST_STATE_RING ||
@@ -2461,6 +2466,9 @@ static void *__analog_ss_thread(void *data)
numbuf[0] = 0;
if (!analog_start_cid_detect(p, p->cid_signalling)) {
+ int off_ms;
+ int ms;
+ struct timeval off_start;
while (1) {
res = analog_get_callerid(p, namebuf, numbuf, &ev, timeout - ast_tvdiff_ms(ast_tvnow(), start));
@@ -2498,10 +2506,12 @@ static void *__analog_ss_thread(void *data)
}
/* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
- res = 4000;/* This is a typical OFF time between rings. */
- for (;;) {
+ off_start = ast_tvnow();
+ off_ms = 4000;/* This is a typical OFF time between rings. */
+ while ((ms = ast_remaining_ms(off_start, off_ms))) {
struct ast_frame *f;
- res = ast_waitfor(chan, res);
+
+ res = ast_waitfor(chan, ms);
if (res <= 0) {
ast_log(LOG_WARNING, "CID timed out waiting for ring. "
"Exiting simple switch\n");
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index 93a77efd7..e01ceadd3 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -1881,7 +1881,9 @@ static void *do_idle_thread(void *v_pvt)
struct ast_frame *f;
char ex[80];
/* Wait up to 30 seconds for an answer */
- int newms, ms = 30000;
+ int timeout_ms = 30000;
+ int ms;
+ struct timeval start;
struct ast_callid *callid;
if ((callid = ast_channel_callid(chan))) {
@@ -1896,7 +1898,12 @@ static void *do_idle_thread(void *v_pvt)
ast_hangup(chan);
return NULL;
}
- while ((newms = ast_waitfor(chan, ms)) > 0) {
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
+ if (ast_waitfor(chan, ms) <= 0) {
+ break;
+ }
+
f = ast_read(chan);
if (!f) {
/* Got hangup */
@@ -1922,7 +1929,6 @@ static void *do_idle_thread(void *v_pvt)
};
}
ast_frfree(f);
- ms = newms;
}
/* Hangup the channel since nothing happend */
ast_hangup(chan);
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index ce9ef7aa2..0157d761e 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -1680,7 +1680,7 @@ int ast_is_deferrable_frame(const struct ast_frame *frame);
/*!
* \brief Wait for a specified amount of time, looking for hangups
* \param chan channel to wait for
- * \param ms length of time in milliseconds to sleep
+ * \param ms length of time in milliseconds to sleep. This should never be less than zero.
* \details
* Waits for a specified amount of time, servicing the channel as required.
* \return returns -1 on hangup, otherwise 0.
@@ -1690,7 +1690,7 @@ int ast_safe_sleep(struct ast_channel *chan, int ms);
/*!
* \brief Wait for a specified amount of time, looking for hangups and a condition argument
* \param chan channel to wait for
- * \param ms length of time in milliseconds to sleep
+ * \param ms length of time in milliseconds to sleep.
* \param cond a function pointer for testing continue condition
* \param data argument to be passed to the condition test function
* \return returns -1 on hangup, otherwise 0.
diff --git a/include/asterisk/time.h b/include/asterisk/time.h
index 4fa08723b..dd68db704 100644
--- a/include/asterisk/time.h
+++ b/include/asterisk/time.h
@@ -152,6 +152,20 @@ struct timeval ast_tvadd(struct timeval a, struct timeval b);
struct timeval ast_tvsub(struct timeval a, struct timeval b);
/*!
+ * \brief Calculate remaining milliseconds given a starting timestamp
+ * and upper bound
+ *
+ * If the upper bound is negative, then this indicates that there is no
+ * upper bound on the amount of time to wait. This will result in a
+ * negative return.
+ *
+ * \param start When timing started being calculated
+ * \param max_ms The maximum number of milliseconds to wait from start. May be negative.
+ * \return The number of milliseconds left to wait for. May be negative.
+ */
+int ast_remaining_ms(struct timeval start, int max_ms);
+
+/*!
* \brief Returns a timeval from sec, usec
*/
AST_INLINE_API(
diff --git a/main/channel.c b/main/channel.c
index 126e44cf6..9998225f0 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -1669,11 +1669,13 @@ int ast_is_deferrable_frame(const struct ast_frame *frame)
}
/*! \brief Wait, look for hangups and condition arg */
-int ast_safe_sleep_conditional(struct ast_channel *chan, int ms, int (*cond)(void*), void *data)
+int ast_safe_sleep_conditional(struct ast_channel *chan, int timeout_ms, int (*cond)(void*), void *data)
{
struct ast_frame *f;
struct ast_silence_generator *silgen = NULL;
int res = 0;
+ struct timeval start;
+ int ms;
AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
@@ -1683,8 +1685,10 @@ int ast_safe_sleep_conditional(struct ast_channel *chan, int ms, int (*cond)(voi
silgen = ast_channel_start_silence_generator(chan);
}
- while (ms > 0) {
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
struct ast_frame *dup_f = NULL;
+
if (cond && ((*cond)(data) == 0)) {
break;
}
@@ -3005,12 +3009,15 @@ int __ast_answer(struct ast_channel *chan, unsigned int delay, int cdr_answer)
do {
AST_LIST_HEAD_NOLOCK(, ast_frame) frames;
struct ast_frame *cur, *new;
- int ms = MAX(delay, 500);
+ int timeout_ms = MAX(delay, 500);
unsigned int done = 0;
+ struct timeval start;
AST_LIST_HEAD_INIT_NOLOCK(&frames);
+ start = ast_tvnow();
for (;;) {
+ int ms = ast_remaining_ms(start, timeout_ms);
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_log(LOG_WARNING, "Error condition occurred when polling channel %s for a voice frame: %s\n", ast_channel_name(chan), strerror(errno));
@@ -3568,11 +3575,13 @@ struct ast_channel *ast_waitfor_n(struct ast_channel **c, int n, int *ms)
int ast_waitfor(struct ast_channel *c, int ms)
{
- int oldms = ms; /* -1 if no timeout */
-
- ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms);
- if ((ms < 0) && (oldms < 0)) {
- ms = 0;
+ if (ms < 0) {
+ do {
+ ms = 100000;
+ ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms);
+ } while (!ms);
+ } else {
+ ast_waitfor_nandfds(&c, 1, NULL, 0, NULL, NULL, &ms);
}
return ms;
}
@@ -3628,6 +3637,7 @@ int ast_settimeout(struct ast_channel *c, unsigned int rate, int (*func)(const v
int ast_waitfordigit_full(struct ast_channel *c, int timeout_ms, int audiofd, int cmdfd)
{
struct timeval start = ast_tvnow();
+ int ms;
/* Stop if we're a zombie or need a soft hangup */
if (ast_test_flag(ast_channel_flags(c), AST_FLAG_ZOMBIE) || ast_check_hangup(c))
@@ -3639,19 +3649,9 @@ int ast_waitfordigit_full(struct ast_channel *c, int timeout_ms, int audiofd, in
/* Wait for a digit, no more than timeout_ms milliseconds total.
* Or, wait indefinitely if timeout_ms is <0.
*/
- while (ast_tvdiff_ms(ast_tvnow(), start) < timeout_ms || timeout_ms < 0) {
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
struct ast_channel *rchan;
- int outfd=-1;
- int ms;
-
- if (timeout_ms < 0) {
- ms = timeout_ms;
- } else {
- ms = timeout_ms - ast_tvdiff_ms(ast_tvnow(), start);
- if (ms < 0) {
- ms = 0;
- }
- }
+ int outfd = -1;
errno = 0;
/* While ast_waitfor_nandfds tries to help by reducing the timeout by how much was waited,
@@ -4690,25 +4690,32 @@ int ast_recvchar(struct ast_channel *chan, int timeout)
char *ast_recvtext(struct ast_channel *chan, int timeout)
{
- int res, done = 0;
+ int res;
char *buf = NULL;
+ struct timeval start = ast_tvnow();
+ int ms;
- while (!done) {
+ while ((ms = ast_remaining_ms(start, timeout))) {
struct ast_frame *f;
- if (ast_check_hangup(chan))
+
+ if (ast_check_hangup(chan)) {
break;
- res = ast_waitfor(chan, timeout);
- if (res <= 0) /* timeout or error */
+ }
+ res = ast_waitfor(chan, ms);
+ if (res <= 0) {/* timeout or error */
break;
- timeout = res; /* update timeout */
+ }
f = ast_read(chan);
- if (f == NULL)
+ if (f == NULL) {
break; /* no frame */
- if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP)
- done = 1; /* force a break */
- else if (f->frametype == AST_FRAME_TEXT) { /* what we want */
+ }
+ if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
+ ast_frfree(f);
+ break;
+ } else if (f->frametype == AST_FRAME_TEXT) { /* what we want */
buf = ast_strndup((char *) f->data.ptr, f->datalen); /* dup and break */
- done = 1;
+ ast_frfree(f);
+ break;
}
ast_frfree(f);
}
@@ -5724,18 +5731,19 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c
if (ast_call(chan, addr, 0)) { /* ast_call failed... */
ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, addr);
} else {
+ struct timeval start = ast_tvnow();
res = 1; /* mark success in case chan->_state is already AST_STATE_UP */
while (timeout && ast_channel_state(chan) != AST_STATE_UP) {
struct ast_frame *f;
- res = ast_waitfor(chan, timeout);
+ int ms = ast_remaining_ms(start, timeout);
+
+ res = ast_waitfor(chan, ms);
if (res == 0) { /* timeout, treat it like ringing */
*outstate = AST_CONTROL_RINGING;
break;
}
if (res < 0) /* error or done */
break;
- if (timeout > -1)
- timeout = res;
if (!ast_strlen_zero(ast_channel_call_forward(chan))) {
if (!(chan = ast_call_forward(NULL, chan, NULL, cap, oh, outstate))) {
return NULL;
diff --git a/main/pbx.c b/main/pbx.c
index 375c232ea..ba66fcac5 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -9767,6 +9767,8 @@ static void *async_wait(void *data)
struct ast_frame *f;
struct ast_app *app;
int have_early_media = 0;
+ struct timeval start = ast_tvnow();
+ int ms;
if (chan) {
struct ast_callid *callid = ast_channel_callid(chan);
@@ -9776,12 +9778,12 @@ static void *async_wait(void *data)
}
}
- while (timeout && (ast_channel_state(chan) != AST_STATE_UP)) {
- res = ast_waitfor(chan, timeout);
+ while ((ms = ast_remaining_ms(start, timeout)) &&
+ ast_channel_state(chan) != AST_STATE_UP) {
+ res = ast_waitfor(chan, ms);
if (res < 1)
break;
- if (timeout > -1)
- timeout = res;
+
f = ast_read(chan);
if (!f)
break;
diff --git a/main/rtp_engine.c b/main/rtp_engine.c
index 55ca0f2b7..29c9286a1 100644
--- a/main/rtp_engine.c
+++ b/main/rtp_engine.c
@@ -949,6 +949,7 @@ static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct a
enum ast_bridge_result res = AST_BRIDGE_FAILED;
struct ast_channel *who = NULL, *other = NULL, *cs[3] = { NULL, };
struct ast_frame *fr = NULL;
+ struct timeval start;
/* Start locally bridging both instances */
if (instance0->engine->local_bridge && instance0->engine->local_bridge(instance0, instance1)) {
@@ -979,7 +980,9 @@ static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct a
cs[0] = c0;
cs[1] = c1;
cs[2] = NULL;
+ start = ast_tvnow();
for (;;) {
+ int ms;
/* If the underlying formats have changed force this bridge to break */
if ((ast_format_cmp(ast_channel_rawreadformat(c0), ast_channel_rawwriteformat(c1)) == AST_FORMAT_CMP_NOT_EQUAL) ||
(ast_format_cmp(ast_channel_rawreadformat(c1), ast_channel_rawwriteformat(c0)) == AST_FORMAT_CMP_NOT_EQUAL)) {
@@ -1005,8 +1008,9 @@ static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct a
break;
}
/* Wait on a channel to feed us a frame */
- if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
- if (!timeoutms) {
+ ms = ast_remaining_ms(start, timeoutms);
+ if (!(who = ast_waitfor_n(cs, 2, &ms))) {
+ if (!ms) {
res = AST_BRIDGE_RETRY;
break;
}
@@ -1145,6 +1149,7 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0,
struct ast_sockaddr ac1 = {{0,}}, vac1 = {{0,}}, tac1 = {{0,}}, ac0 = {{0,}}, vac0 = {{0,}}, tac0 = {{0,}};
struct ast_sockaddr t1 = {{0,}}, vt1 = {{0,}}, tt1 = {{0,}}, t0 = {{0,}}, vt0 = {{0,}}, tt0 = {{0,}};
struct ast_frame *fr = NULL;
+ struct timeval start;
if (!oldcap0 || !oldcap1) {
ast_channel_unlock(c0);
@@ -1189,7 +1194,9 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0,
cs[0] = c0;
cs[1] = c1;
cs[2] = NULL;
+ start = ast_tvnow();
for (;;) {
+ int ms;
/* Check if anything changed */
if ((ast_channel_tech_pvt(c0) != pvt0) ||
(ast_channel_tech_pvt(c1) != pvt1) ||
@@ -1284,9 +1291,10 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0,
ast_format_cap_copy(oldcap0, cap0);
}
+ ms = ast_remaining_ms(start, timeoutms);
/* Wait for frame to come in on the channels */
- if (!(who = ast_waitfor_n(cs, 2, &timeoutms))) {
- if (!timeoutms) {
+ if (!(who = ast_waitfor_n(cs, 2, &ms))) {
+ if (!ms) {
res = AST_BRIDGE_RETRY;
break;
}
diff --git a/main/utils.c b/main/utils.c
index 0ff33cba2..3476729ce 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -1470,6 +1470,23 @@ struct timeval ast_tvsub(struct timeval a, struct timeval b)
}
return a;
}
+
+int ast_remaining_ms(struct timeval start, int max_ms)
+{
+ int ms;
+
+ if (max_ms < 0) {
+ ms = max_ms;
+ } else {
+ ms = max_ms - ast_tvdiff_ms(ast_tvnow(), start);
+ if (ms < 0) {
+ ms = 0;
+ }
+ }
+
+ return ms;
+}
+
#undef ONE_MILLION
/*! \brief glibc puts a lock inside random(3), so that the results are thread-safe.
diff --git a/res/res_fax.c b/res/res_fax.c
index cc3e23fe6..32225d32d 100644
--- a/res/res_fax.c
+++ b/res/res_fax.c
@@ -1262,9 +1262,11 @@ static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_det
static int disable_t38(struct ast_channel *chan)
{
- int ms;
+ int timeout_ms;
struct ast_frame *frame = NULL;
struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
+ struct timeval start;
+ int ms;
ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(chan));
if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
@@ -1273,20 +1275,19 @@ static int disable_t38(struct ast_channel *chan)
}
/* wait up to five seconds for negotiation to complete */
- ms = 5000;
-
- while (ms > 0) {
+ timeout_ms = 5000;
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
ms = ast_waitfor(chan, ms);
+
+ if (ms == 0) {
+ break;
+ }
if (ms < 0) {
ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
return -1;
}
- if (ms == 0) { /* all done, nothing happened */
- ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", ast_channel_name(chan));
- break;
- }
-
if (!(frame = ast_read(chan))) {
return -1;
}
@@ -1314,6 +1315,10 @@ static int disable_t38(struct ast_channel *chan)
ast_frfree(frame);
}
+ if (ms == 0) { /* all done, nothing happened */
+ ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", ast_channel_name(chan));
+ }
+
return 0;
}
@@ -1322,7 +1327,7 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
{
int ms;
int timeout = RES_FAX_TIMEOUT;
- int res = 0, chancount;
+ int res, chancount;
unsigned int expected_frametype = -1;
union ast_frame_subclass expected_framesubclass = { .integer = -1 };
unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
@@ -1333,6 +1338,8 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
struct ast_channel *c = chan;
struct ast_format orig_write_format;
struct ast_format orig_read_format;
+ int remaining_time;
+ struct timeval start;
ast_format_clear(&orig_write_format);
ast_format_clear(&orig_read_format);
@@ -1413,8 +1420,9 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
ast_debug(5, "channel %s will wait on FAX fd %d\n", ast_channel_name(chan), fax->fd);
/* handle frames for the session */
- ms = 1000;
- while ((res > -1) && (ms > -1) && (timeout > 0)) {
+ remaining_time = timeout;
+ start = ast_tvnow();
+ while (remaining_time > 0) {
struct ast_channel *ready_chan;
int ofd, exception;
@@ -1431,7 +1439,7 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
c = NULL;
chancount = 0;
- timeout -= (1000 - ms);
+ remaining_time = ast_remaining_ms(start, timeout);
fax->tech->cancel_session(fax);
if (fax->tech->generate_silence) {
fax->tech->generate_silence(fax);
@@ -1500,7 +1508,7 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
fax->tech->write(fax, frame);
fax->frames_received++;
}
- timeout = RES_FAX_TIMEOUT;
+ start = ast_tvnow();
}
ast_frfree(frame);
} else if (ofd == fax->fd) {
@@ -1517,36 +1525,30 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
ast_write(chan, frame);
fax->frames_sent++;
ast_frfree(frame);
- timeout = RES_FAX_TIMEOUT;
+ start = ast_tvnow();
} else {
if (ms && (ofd < 0)) {
if ((errno == 0) || (errno == EINTR)) {
- timeout -= (1000 - ms);
- if (timeout <= 0)
+ remaining_time = ast_remaining_ms(start, timeout);
+ if (remaining_time <= 0)
GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
continue;
} else {
ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(chan));
GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
- res = ms;
break;
}
} else {
/* nothing happened */
- if (timeout > 0) {
- timeout -= 1000;
- if (timeout <= 0)
- GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
- continue;
- } else {
- ast_log(LOG_WARNING, "channel '%s' timed-out during the FAX transmission.\n", ast_channel_name(chan));
+ remaining_time = ast_remaining_ms(start, timeout);
+ if (remaining_time <= 0) {
GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
break;
}
}
}
}
- ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, ms: %d, res: %d }\n", ast_channel_name(chan), timeout, ms, res);
+ ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
set_channel_variables(chan, details);
@@ -1580,9 +1582,11 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
{
- int ms;
+ int timeout_ms;
struct ast_frame *frame = NULL;
struct ast_control_t38_parameters t38_parameters;
+ struct timeval start;
+ int ms;
/* don't send any audio if we've already received a T.38 reinvite */
if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
@@ -1592,9 +1596,11 @@ static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_
return -1;
}
- ms = 3000;
- while (ms > 0) {
+ timeout_ms = 3000;
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
ms = ast_waitfor(chan, ms);
+
if (ms < 0) {
ast_log(LOG_ERROR, "error while generating CED tone on %s\n", ast_channel_name(chan));
ast_playtones_stop(chan);
@@ -1651,7 +1657,7 @@ static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_
ast_debug(1, "Negotiating T.38 for receive on %s\n", ast_channel_name(chan));
/* wait up to five seconds for negotiation to complete */
- ms = 5000;
+ timeout_ms = 5000;
/* set parameters based on the session's parameters */
t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
@@ -1660,13 +1666,15 @@ static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_
return -1;
}
- while (ms > 0) {
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
+ int break_loop = 0;
+
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
return -1;
}
-
if (ms == 0) { /* all done, nothing happened */
ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
details->caps &= ~AST_FAX_TECH_T38;
@@ -1694,21 +1702,24 @@ static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
- ms = 0;
+ break_loop = 1;
break;
case AST_T38_REFUSED:
ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
details->caps &= ~AST_FAX_TECH_T38;
- ms = 0;
+ break_loop = 1;
break;
default:
ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
details->caps &= ~AST_FAX_TECH_T38;
- ms = 0;
+ break_loop = 1;
break;
}
}
ast_frfree(frame);
+ if (break_loop) {
+ break;
+ }
}
/* if T.38 was negotiated, we are done initializing */
@@ -1976,9 +1987,11 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
{
- int ms;
+ int timeout_ms;
struct ast_frame *frame = NULL;
struct ast_control_t38_parameters t38_parameters;
+ struct timeval start;
+ int ms;
/* send CNG tone while listening for the receiver to initiate a switch
* to T.38 mode; if they do, stop sending the CNG tone and proceed with
@@ -1986,7 +1999,7 @@ static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_det
*
* 10500 is enough time for 3 CNG tones
*/
- ms = 10500;
+ timeout_ms = 10500;
/* don't send any audio if we've already received a T.38 reinvite */
if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
@@ -1996,8 +2009,11 @@ static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_det
}
}
- while (ms > 0) {
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
+ int break_loop = 0;
ms = ast_waitfor(chan, ms);
+
if (ms < 0) {
ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", ast_channel_name(chan));
ast_playtones_stop(chan);
@@ -2034,13 +2050,16 @@ static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_det
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
- ms = 0;
+ break_loop = 1;
break;
default:
break;
}
}
ast_frfree(frame);
+ if (break_loop) {
+ break;
+ }
}
ast_playtones_stop(chan);
@@ -2054,7 +2073,7 @@ static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_det
ast_debug(1, "Negotiating T.38 for send on %s\n", ast_channel_name(chan));
/* wait up to five seconds for negotiation to complete */
- ms = 5000;
+ timeout_ms = 5000;
/* set parameters based on the session's parameters */
t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
@@ -2063,13 +2082,15 @@ static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_det
return -1;
}
- while (ms > 0) {
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
+ int break_loop = 0;
+
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
return -1;
}
-
if (ms == 0) { /* all done, nothing happened */
ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
details->caps &= ~AST_FAX_TECH_T38;
@@ -2097,21 +2118,24 @@ static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_det
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
- ms = 0;
+ break_loop = 1;
break;
case AST_T38_REFUSED:
ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
details->caps &= ~AST_FAX_TECH_T38;
- ms = 0;
+ break_loop = 1;
break;
default:
ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
details->caps &= ~AST_FAX_TECH_T38;
- ms = 0;
+ break_loop = 1;
break;
}
}
ast_frfree(frame);
+ if (break_loop) {
+ break;
+ }
}
/* if T.38 was negotiated, we are done initializing */
@@ -2127,15 +2151,17 @@ static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_det
return -1;
}
- ms = 3500;
- while (ms > 0) {
+ timeout_ms = 3500;
+ start = ast_tvnow();
+ while ((ms = ast_remaining_ms(start, timeout_ms))) {
+ int break_loop = 0;
+
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", ast_channel_name(chan));
ast_playtones_stop(chan);
return -1;
}
-
if (ms == 0) { /* all done, nothing happened */
break;
}
@@ -2166,13 +2192,16 @@ static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_det
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
- ms = 0;
+ break_loop = 1;
break;
default:
break;
}
}
ast_frfree(frame);
+ if (break_loop) {
+ break;
+ }
}
ast_playtones_stop(chan);