summaryrefslogtreecommitdiff
path: root/main/channel.c
diff options
context:
space:
mode:
authorTilghman Lesher <tilghman@meg.abyt.es>2008-05-01 23:06:23 +0000
committerTilghman Lesher <tilghman@meg.abyt.es>2008-05-01 23:06:23 +0000
commitb5a127daac81d625b5968068b2e0406a3dc2e0e9 (patch)
tree3df7d1e791a878179b45272be0b3f3cccf8eeee0 /main/channel.c
parent44af1e23d05a2b9005a4be408978a2263bf7f1a7 (diff)
Modify TIMEOUT() to be accurate down to the millisecond.
(closes issue #10540) Reported by: spendergrass Patches: 20080417__bug10540.diff.txt uploaded by Corydon76 (license 14) Tested by: blitzrage git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@115076 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/channel.c')
-rw-r--r--main/channel.c103
1 files changed, 53 insertions, 50 deletions
diff --git a/main/channel.c b/main/channel.c
index 351d64198..2cb2bc336 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -464,9 +464,9 @@ int ast_check_hangup(struct ast_channel *chan)
return 1;
if (!chan->tech_pvt) /* yes if no technology private data */
return 1;
- if (!chan->whentohangup) /* no if no hangup scheduled */
+ if (ast_tvzero(chan->whentohangup)) /* no if no hangup scheduled */
return 0;
- if (chan->whentohangup > time(NULL)) /* no if hangup time has not come yet. */
+ if (ast_tvdiff_ms(chan->whentohangup, ast_tvnow()) > 0) /* no if hangup time has not come yet. */
return 0;
chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT; /* record event */
return 1;
@@ -519,32 +519,39 @@ int ast_shutting_down(void)
}
/*! \brief Set when to hangup channel */
-void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
+void ast_channel_setwhentohangup_tv(struct ast_channel *chan, struct timeval offset)
{
- chan->whentohangup = offset ? time(NULL) + offset : 0;
+ chan->whentohangup = ast_tvzero(offset) ? offset : ast_tvadd(offset, ast_tvnow());
ast_queue_frame(chan, &ast_null_frame);
return;
}
+void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
+{
+ struct timeval tv = { offset, };
+ ast_channel_setwhentohangup_tv(chan, tv);
+}
+
/*! \brief Compare a offset with when to hangup channel */
-int ast_channel_cmpwhentohangup(struct ast_channel *chan, time_t offset)
+int ast_channel_cmpwhentohangup_tv(struct ast_channel *chan, struct timeval offset)
{
- time_t whentohangup;
+ struct timeval whentohangup;
- if (!chan->whentohangup)
- return (offset == 0) ? 0 : -1;
+ if (ast_tvzero(chan->whentohangup))
+ return ast_tvzero(offset) ? 0 : -1;
- if (!offset) /* XXX why is this special? */
+ if (ast_tvzero(offset))
return 1;
- whentohangup = offset + time(NULL);
+ whentohangup = ast_tvadd(offset, ast_tvnow());
- if (chan->whentohangup < whentohangup)
- return 1;
- else if (chan->whentohangup == whentohangup)
- return 0;
- else
- return -1;
+ return ast_tvdiff_ms(whentohangup, chan->whentohangup);
+}
+
+int ast_channel_cmpwhentohangup(struct ast_channel *chan, time_t offset)
+{
+ struct timeval tv = { offset, };
+ return ast_channel_cmpwhentohangup_tv(chan, tv);
}
/*! \brief Register a new telephony channel in Asterisk */
@@ -1793,8 +1800,8 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
long rms;
int x, y, max;
int sz;
- time_t now = 0;
- long whentohangup = 0, diff;
+ struct timeval now = { 0, 0 };
+ struct timeval whentohangup = { 0, 0 }, diff;
struct ast_channel *winner = NULL;
struct fdmap {
int chan;
@@ -1820,25 +1827,25 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
ast_channel_unlock(c[x]);
return NULL;
}
- if (c[x]->whentohangup) {
- if (!whentohangup)
- time(&now);
- diff = c[x]->whentohangup - now;
- if (diff < 1) {
+ if (!ast_tvzero(c[x]->whentohangup)) {
+ if (ast_tvzero(whentohangup))
+ now = ast_tvnow();
+ diff = ast_tvsub(c[x]->whentohangup, now);
+ if (diff.tv_sec < 0 || ast_tvzero(diff)) {
/* Should already be hungup */
c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
ast_channel_unlock(c[x]);
return c[x];
}
- if (!whentohangup || (diff < whentohangup))
+ if (ast_tvzero(whentohangup) || ast_tvcmp(diff, whentohangup) < 0)
whentohangup = diff;
}
ast_channel_unlock(c[x]);
}
/* Wait full interval */
rms = *ms;
- if (whentohangup) {
- rms = whentohangup * 1000; /* timeout in milliseconds */
+ if (!ast_tvzero(whentohangup)) {
+ rms = whentohangup.tv_sec * 1000 + whentohangup.tv_usec / 1000; /* timeout in milliseconds */
if (*ms >= 0 && *ms < rms) /* original *ms still smaller */
rms = *ms;
}
@@ -1884,10 +1891,10 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
*ms = -1;
return NULL;
}
- if (whentohangup) { /* if we have a timeout, check who expired */
- time(&now);
+ if (!ast_tvzero(whentohangup)) { /* if we have a timeout, check who expired */
+ now = ast_tvnow();
for (x = 0; x < n; x++) {
- if (c[x]->whentohangup && now >= c[x]->whentohangup) {
+ if (!ast_tvzero(c[x]->whentohangup) && ast_tvcmp(c[x]->whentohangup, now) <= 0) {
c[x]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
if (winner == NULL)
winner = c[x];
@@ -1936,8 +1943,7 @@ static struct ast_channel *ast_waitfor_nandfds_simple(struct ast_channel *chan,
struct timeval start = { 0 , 0 };
int res = 0;
struct epoll_event ev[1];
- long whentohangup = 0, rms = *ms;
- time_t now;
+ long diff, rms = *ms;
struct ast_channel *winner = NULL;
struct ast_epoll_data *aed = NULL;
@@ -1952,18 +1958,16 @@ static struct ast_channel *ast_waitfor_nandfds_simple(struct ast_channel *chan,
}
/* Figure out their timeout */
- if (chan->whentohangup) {
- time(&now);
- if ((whentohangup = chan->whentohangup - now) < 1) {
+ if (!ast_tvzero(chan->whentohangup)) {
+ if ((diff = ast_tvdiff_ms(chan->whentohangup, ast_tvnow())) < 0) {
/* They should already be hungup! */
chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
ast_channel_unlock(chan);
return NULL;
}
/* If this value is smaller then the current one... make it priority */
- whentohangup *= 1000;
- if (rms > whentohangup)
- rms = whentohangup;
+ if (rms > diff)
+ rms = diff;
}
ast_channel_unlock(chan);
@@ -1988,9 +1992,8 @@ static struct ast_channel *ast_waitfor_nandfds_simple(struct ast_channel *chan,
}
/* If this channel has a timeout see if it expired */
- if (chan->whentohangup) {
- time(&now);
- if (now >= chan->whentohangup) {
+ if (!ast_tvzero(chan->whentohangup)) {
+ if (ast_tvdiff_ms(ast_tvnow(), chan->whentohangup) >= 0) {
chan->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
winner = chan;
}
@@ -2024,8 +2027,8 @@ static struct ast_channel *ast_waitfor_nandfds_complex(struct ast_channel **c, i
struct timeval start = { 0 , 0 };
int res = 0, i;
struct epoll_event ev[25] = { { 0, } };
- long whentohangup = 0, diff, rms = *ms;
- time_t now;
+ struct timeval now = { 0, 0 };
+ long whentohangup = 0, diff = 0, rms = *ms;
struct ast_channel *winner = NULL;
for (i = 0; i < n; i++) {
@@ -2036,15 +2039,15 @@ static struct ast_channel *ast_waitfor_nandfds_complex(struct ast_channel **c, i
ast_channel_unlock(c[i]);
return NULL;
}
- if (c[i]->whentohangup) {
- if (!whentohangup)
- time(&now);
- if ((diff = c[i]->whentohangup - now) < 1) {
+ if (!ast_tvzero(c[i]->whentohangup)) {
+ if (whentohangup == 0)
+ now = ast_tvnow();
+ if ((diff = ast_tvdiff_ms(c[i]->whentohangup, now)) < 0) {
c[i]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
ast_channel_unlock(c[i]);
return c[i];
}
- if (!whentohangup || (diff < whentohangup))
+ if (!whentohangup || whentohangup > diff)
whentohangup = diff;
}
ast_channel_unlock(c[i]);
@@ -2053,7 +2056,7 @@ static struct ast_channel *ast_waitfor_nandfds_complex(struct ast_channel **c, i
rms = *ms;
if (whentohangup) {
- rms = whentohangup * 1000;
+ rms = whentohangup;
if (*ms >= 0 && *ms < rms)
rms = *ms;
}
@@ -2073,9 +2076,9 @@ static struct ast_channel *ast_waitfor_nandfds_complex(struct ast_channel **c, i
}
if (whentohangup) {
- time(&now);
+ now = ast_tvnow();
for (i = 0; i < n; i++) {
- if (c[i]->whentohangup && now >= c[i]->whentohangup) {
+ if (!ast_tvzero(c[i]->whentohangup) && ast_tvdiff_ms(now, c[i]->whentohangup) >= 0) {
c[i]->_softhangup |= AST_SOFTHANGUP_TIMEOUT;
if (!winner)
winner = c[i];