diff options
author | Tilghman Lesher <tilghman@meg.abyt.es> | 2008-05-01 23:06:23 +0000 |
---|---|---|
committer | Tilghman Lesher <tilghman@meg.abyt.es> | 2008-05-01 23:06:23 +0000 |
commit | b5a127daac81d625b5968068b2e0406a3dc2e0e9 (patch) | |
tree | 3df7d1e791a878179b45272be0b3f3cccf8eeee0 /main/channel.c | |
parent | 44af1e23d05a2b9005a4be408978a2263bf7f1a7 (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.c | 103 |
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]; |