Tue May 6 17:00:19 EDT 2008 first.last@nokia.com

* nta.c: use consistently uint32_t when handling millisecond timers inside nta
  
  The timer handling failed miserably on 64-bit platforms each time uint32_t
  counter for milliseconds wrapped around.



git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8287 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Michael Jerris 2008-05-07 12:28:33 +00:00
parent d9f1667944
commit f9af6b4d2d
2 changed files with 73 additions and 52 deletions

View File

@ -734,7 +734,7 @@ static
void agent_timer(su_root_magic_t *rm, su_timer_t *timer, nta_agent_t *agent) void agent_timer(su_root_magic_t *rm, su_timer_t *timer, nta_agent_t *agent)
{ {
su_time_t stamp = su_now(); su_time_t stamp = su_now();
su_duration_t now = su_time_ms(stamp), next; uint32_t now = su_time_ms(stamp), next, latest;
now += now == 0; now += now == 0;
@ -752,10 +752,11 @@ void agent_timer(su_root_magic_t *rm, su_timer_t *timer, nta_agent_t *agent)
agent->sa_in_timer = 0; agent->sa_in_timer = 0;
/* Calculate next timeout */ /* Calculate next timeout */
next = now + SU_DURATION_MAX; next = latest = now + NTA_TIME_MAX + 1;
#define NEXT_TIMEOUT(next, p, f, now) \ #define NEXT_TIMEOUT(next, p, f, now) \
(void)(p && p->f - (next) < 0 && ((next) = (p->f - (now) > 0 ? p->f : (now)))) (void)(p && (int32_t)(p->f - (next)) < 0 && \
((next) = ((int32_t)(p->f - (now)) > 0 ? p->f : (now))))
NEXT_TIMEOUT(next, agent->sa_out.re_list, orq_retry, now); NEXT_TIMEOUT(next, agent->sa_out.re_list, orq_retry, now);
NEXT_TIMEOUT(next, agent->sa_out.inv_completed->q_head, orq_timeout, now); NEXT_TIMEOUT(next, agent->sa_out.inv_completed->q_head, orq_timeout, now);
@ -776,8 +777,8 @@ void agent_timer(su_root_magic_t *rm, su_timer_t *timer, nta_agent_t *agent)
#undef NEXT_TIMEOUT #undef NEXT_TIMEOUT
if (next == now + SU_DURATION_MAX) { if (next == latest) {
/* Do not set timer */ /* Do not set timer? */
SU_DEBUG_9(("nta: timer not set\n")); SU_DEBUG_9(("nta: timer not set\n"));
assert(!agent->sa_out.completed->q_head); assert(!agent->sa_out.completed->q_head);
assert(!agent->sa_out.trying->q_head); assert(!agent->sa_out.trying->q_head);
@ -800,6 +801,22 @@ void agent_timer(su_root_magic_t *rm, su_timer_t *timer, nta_agent_t *agent)
su_timer_set_at(timer, agent_timer, agent, su_time_add(stamp, next - now)); su_timer_set_at(timer, agent_timer, agent, su_time_add(stamp, next - now));
} }
/** Add uin32_t milliseconds to the time. */
static su_time_t add_milliseconds(su_time_t t0, uint32_t ms)
{
unsigned long sec = ms / 1000, usec = (ms % 1000) * 1000;
t0.tv_usec += usec;
t0.tv_sec += sec;
if (t0.tv_usec >= 1000000) {
t0.tv_sec += 1;
t0.tv_usec -= 1000000;
}
return t0;
}
/** Calculate nonzero value for timeout. /** Calculate nonzero value for timeout.
* *
* Sets or adjusts agent timer when needed. * Sets or adjusts agent timer when needed.
@ -808,25 +825,25 @@ void agent_timer(su_root_magic_t *rm, su_timer_t *timer, nta_agent_t *agent)
* @retval timeout (millisecond counter) otherwise * @retval timeout (millisecond counter) otherwise
*/ */
static static
su_duration_t set_timeout(nta_agent_t *agent, su_duration_t offset) uint32_t set_timeout(nta_agent_t *agent, uint32_t offset)
{ {
su_time_t now; su_time_t now;
su_duration_t next, ms; uint32_t next, ms;
if (offset == 0) if (offset == 0)
return 0; return 0;
if (agent->sa_millisec) /* Avoid expensive call to su_timer_ms() */ if (agent->sa_millisec) /* Avoid expensive call to su_now() */
now = agent->sa_now, ms = agent->sa_millisec; now = agent->sa_now, ms = agent->sa_millisec;
else else
now = su_now(), ms = (su_duration_t)su_time_ms(now); now = su_now(), ms = su_time_ms(now);
next = ms + offset; if (next == 0) next = 1; next = ms + offset; if (next == 0) next = 1;
if (agent->sa_in_timer) if (agent->sa_in_timer) /* Currently executing timer */
return next; return next;
if (agent->sa_next == 0 || agent->sa_next - next - 5L > 0) { if (agent->sa_next == 0 || (int32_t)(agent->sa_next - next - 5L) > 0) {
/* Set timer */ /* Set timer */
if (agent->sa_next) if (agent->sa_next)
SU_DEBUG_9(("nta: timer %s to %ld ms\n", "shortened", (long)offset)); SU_DEBUG_9(("nta: timer %s to %ld ms\n", "shortened", (long)offset));
@ -834,7 +851,7 @@ su_duration_t set_timeout(nta_agent_t *agent, su_duration_t offset)
SU_DEBUG_9(("nta: timer %s to %ld ms\n", "set", (long)offset)); SU_DEBUG_9(("nta: timer %s to %ld ms\n", "set", (long)offset));
su_timer_set_at(agent->sa_timer, agent_timer, agent, su_timer_set_at(agent->sa_timer, agent_timer, agent,
su_time_add(now, offset)); add_milliseconds(now, offset));
agent->sa_next = next; agent->sa_next = next;
} }
@ -1093,7 +1110,7 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags)
} }
if (maxsize == 0) maxsize = 2 * 1024 * 1024; if (maxsize == 0) maxsize = 2 * 1024 * 1024;
if (maxsize > NTA_TIME_MAX) maxsize = NTA_TIME_MAX; if (maxsize > UINT32_MAX) maxsize = UINT32_MAX;
agent->sa_maxsize = maxsize; agent->sa_maxsize = maxsize;
if (max_proceeding == 0) max_proceeding = SIZE_MAX; if (max_proceeding == 0) max_proceeding = SIZE_MAX;
@ -4522,7 +4539,7 @@ static void incoming_insert(nta_agent_t *agent,
su_inline int incoming_is_queued(nta_incoming_t const *irq); su_inline int incoming_is_queued(nta_incoming_t const *irq);
su_inline void incoming_queue(incoming_queue_t *queue, nta_incoming_t *); su_inline void incoming_queue(incoming_queue_t *queue, nta_incoming_t *);
su_inline void incoming_remove(nta_incoming_t *irq); su_inline void incoming_remove(nta_incoming_t *irq);
su_inline void incoming_set_timer(nta_incoming_t *, unsigned interval); su_inline void incoming_set_timer(nta_incoming_t *, uint32_t interval);
su_inline void incoming_reset_timer(nta_incoming_t *); su_inline void incoming_reset_timer(nta_incoming_t *);
su_inline size_t incoming_mass_destroy(nta_agent_t *, incoming_queue_t *); su_inline size_t incoming_mass_destroy(nta_agent_t *, incoming_queue_t *);
@ -4856,10 +4873,10 @@ incoming_queue_init(incoming_queue_t *queue, unsigned timeout)
static void static void
incoming_queue_adjust(nta_agent_t *sa, incoming_queue_adjust(nta_agent_t *sa,
incoming_queue_t *queue, incoming_queue_t *queue,
unsigned timeout) uint32_t timeout)
{ {
nta_incoming_t *irq; nta_incoming_t *irq;
su_duration_t latest; uint32_t latest;
if (timeout >= queue->q_timeout || !queue->q_head) { if (timeout >= queue->q_timeout || !queue->q_head) {
queue->q_timeout = timeout; queue->q_timeout = timeout;
@ -4869,7 +4886,7 @@ incoming_queue_adjust(nta_agent_t *sa,
latest = set_timeout(sa, queue->q_timeout = timeout); latest = set_timeout(sa, queue->q_timeout = timeout);
for (irq = queue->q_head; irq; irq = irq->irq_next) { for (irq = queue->q_head; irq; irq = irq->irq_next) {
if (irq->irq_timeout - latest > 0) if ((int32_t)(irq->irq_timeout - latest) > 0)
irq->irq_timeout = latest; irq->irq_timeout = latest;
} }
} }
@ -4934,7 +4951,7 @@ void incoming_remove(nta_incoming_t *irq)
} }
su_inline su_inline
void incoming_set_timer(nta_incoming_t *irq, unsigned interval) void incoming_set_timer(nta_incoming_t *irq, uint32_t interval)
{ {
nta_incoming_t **rq; nta_incoming_t **rq;
@ -4958,10 +4975,10 @@ void incoming_set_timer(nta_incoming_t *irq, unsigned interval)
rq = irq->irq_agent->sa_in.re_t1; rq = irq->irq_agent->sa_in.re_t1;
if (!(*rq) || (*rq)->irq_retry - irq->irq_retry > 0) if (!(*rq) || (int32_t)((*rq)->irq_retry - irq->irq_retry) > 0)
rq = &irq->irq_agent->sa_in.re_list; rq = &irq->irq_agent->sa_in.re_list;
while (*rq && (*rq)->irq_retry - irq->irq_retry <= 0) while (*rq && (int32_t)((*rq)->irq_retry - irq->irq_retry) <= 0)
rq = &(*rq)->irq_rnext; rq = &(*rq)->irq_rnext;
if ((irq->irq_rnext = *rq)) if ((irq->irq_rnext = *rq))
@ -6188,7 +6205,7 @@ enum {
/** @internal Timer routine for the incoming request. */ /** @internal Timer routine for the incoming request. */
static void incoming_timer(nta_agent_t *sa) static void incoming_timer(nta_agent_t *sa)
{ {
su_duration_t now = sa->sa_millisec; uint32_t now = sa->sa_millisec;
nta_incoming_t *irq, *irq_next; nta_incoming_t *irq, *irq_next;
size_t retransmitted = 0, timeout = 0, terminated = 0, destroyed = 0; size_t retransmitted = 0, timeout = 0, terminated = 0, destroyed = 0;
size_t unconfirmed = size_t unconfirmed =
@ -6205,7 +6222,7 @@ static void incoming_timer(nta_agent_t *sa)
/* Handle retry queue */ /* Handle retry queue */
while ((irq = sa->sa_in.re_list)) { while ((irq = sa->sa_in.re_list)) {
if (irq->irq_retry - now > 0) if ((int32_t)(irq->irq_retry - now) > 0)
break; break;
if (retransmitted >= timer_max_retransmit) if (retransmitted >= timer_max_retransmit)
break; break;
@ -6286,7 +6303,7 @@ static void incoming_timer(nta_agent_t *sa)
assert(irq->irq_status < 200); assert(irq->irq_status < 200);
assert(irq->irq_timeout); assert(irq->irq_timeout);
if (irq->irq_timeout - now > 0) if ((int32_t)(irq->irq_timeout - now) > 0)
break; break;
if (timeout >= timer_max_timeout) if (timeout >= timer_max_timeout)
break; break;
@ -6306,7 +6323,7 @@ static void incoming_timer(nta_agent_t *sa)
assert(irq->irq_timeout); assert(irq->irq_timeout);
assert(irq->irq_method == sip_method_invite); assert(irq->irq_method == sip_method_invite);
if (irq->irq_timeout - now > 0 || if ((int32_t)(irq->irq_timeout - now) > 0 ||
timeout >= timer_max_timeout || timeout >= timer_max_timeout ||
terminated >= timer_max_terminate) terminated >= timer_max_terminate)
break; break;
@ -6334,7 +6351,8 @@ static void incoming_timer(nta_agent_t *sa)
assert(irq->irq_status >= 200); assert(irq->irq_status >= 200);
assert(irq->irq_method == sip_method_invite); assert(irq->irq_method == sip_method_invite);
if (irq->irq_timeout - now > 0 || terminated >= timer_max_terminate) if ((int32_t)(irq->irq_timeout - now) > 0 ||
terminated >= timer_max_terminate)
break; break;
/* Timer I */ /* Timer I */
@ -6355,7 +6373,8 @@ static void incoming_timer(nta_agent_t *sa)
assert(irq->irq_timeout); assert(irq->irq_timeout);
assert(irq->irq_method != sip_method_invite); assert(irq->irq_method != sip_method_invite);
if (irq->irq_timeout - now > 0 || terminated >= timer_max_terminate) if ((int32_t)(irq->irq_timeout - now) > 0 ||
terminated >= timer_max_terminate)
break; break;
/* Timer J */ /* Timer J */
@ -6448,24 +6467,24 @@ su_inline int outgoing_is_queued(nta_outgoing_t const *orq);
su_inline void outgoing_queue(outgoing_queue_t *queue, su_inline void outgoing_queue(outgoing_queue_t *queue,
nta_outgoing_t *orq); nta_outgoing_t *orq);
su_inline void outgoing_remove(nta_outgoing_t *orq); su_inline void outgoing_remove(nta_outgoing_t *orq);
su_inline void outgoing_set_timer(nta_outgoing_t *orq, unsigned interval); su_inline void outgoing_set_timer(nta_outgoing_t *orq, uint32_t interval);
su_inline void outgoing_reset_timer(nta_outgoing_t *orq); su_inline void outgoing_reset_timer(nta_outgoing_t *orq);
static size_t outgoing_timer_dk(outgoing_queue_t *q, static size_t outgoing_timer_dk(outgoing_queue_t *q,
char const *timer, char const *timer,
su_duration_t now); uint32_t now);
static size_t outgoing_timer_bf(outgoing_queue_t *q, static size_t outgoing_timer_bf(outgoing_queue_t *q,
char const *timer, char const *timer,
su_duration_t now); uint32_t now);
static size_t outgoing_timer_c(outgoing_queue_t *q, static size_t outgoing_timer_c(outgoing_queue_t *q,
char const *timer, char const *timer,
su_duration_t now); uint32_t now);
static void outgoing_ack(nta_outgoing_t *orq, sip_t *sip); static void outgoing_ack(nta_outgoing_t *orq, sip_t *sip);
static msg_t *outgoing_ackmsg(nta_outgoing_t *, sip_method_t, char const *, static msg_t *outgoing_ackmsg(nta_outgoing_t *, sip_method_t, char const *,
tagi_t const *tags); tagi_t const *tags);
static void outgoing_retransmit(nta_outgoing_t *orq); static void outgoing_retransmit(nta_outgoing_t *orq);
static void outgoing_trying(nta_outgoing_t *orq); static void outgoing_trying(nta_outgoing_t *orq);
static void outgoing_timeout(nta_outgoing_t *orq, su_duration_t now); static void outgoing_timeout(nta_outgoing_t *orq, uint32_t now);
static int outgoing_complete(nta_outgoing_t *orq); static int outgoing_complete(nta_outgoing_t *orq);
static int outgoing_terminate(nta_outgoing_t *orq); static int outgoing_terminate(nta_outgoing_t *orq);
static size_t outgoing_mass_destroy(nta_agent_t *sa, outgoing_queue_t *q); static size_t outgoing_mass_destroy(nta_agent_t *sa, outgoing_queue_t *q);
@ -7707,7 +7726,7 @@ outgoing_queue_adjust(nta_agent_t *sa,
unsigned timeout) unsigned timeout)
{ {
nta_outgoing_t *orq; nta_outgoing_t *orq;
su_duration_t latest; uint32_t latest;
if (timeout >= queue->q_timeout || !queue->q_head) { if (timeout >= queue->q_timeout || !queue->q_head) {
queue->q_timeout = timeout; queue->q_timeout = timeout;
@ -7718,7 +7737,7 @@ outgoing_queue_adjust(nta_agent_t *sa,
for (orq = queue->q_head; orq; orq = orq->orq_next) { for (orq = queue->q_head; orq; orq = orq->orq_next) {
if (orq->orq_timeout == 0 || if (orq->orq_timeout == 0 ||
orq->orq_timeout - latest > 0) (int32_t)(orq->orq_timeout - latest) > 0)
orq->orq_timeout = latest; orq->orq_timeout = latest;
} }
} }
@ -7788,7 +7807,7 @@ void outgoing_remove(nta_outgoing_t *orq)
* Set the retry timer (B/D) on the outgoing request (client transaction). * Set the retry timer (B/D) on the outgoing request (client transaction).
*/ */
su_inline su_inline
void outgoing_set_timer(nta_outgoing_t *orq, unsigned interval) void outgoing_set_timer(nta_outgoing_t *orq, uint32_t interval)
{ {
nta_outgoing_t **rq; nta_outgoing_t **rq;
@ -7815,10 +7834,10 @@ void outgoing_set_timer(nta_outgoing_t *orq, unsigned interval)
/* Shortcut into queue at SIP T1 */ /* Shortcut into queue at SIP T1 */
rq = orq->orq_agent->sa_out.re_t1; rq = orq->orq_agent->sa_out.re_t1;
if (!(*rq) || (*rq)->orq_retry - orq->orq_retry > 0) if (!(*rq) || (int32_t)((*rq)->orq_retry - orq->orq_retry) > 0)
rq = &orq->orq_agent->sa_out.re_list; rq = &orq->orq_agent->sa_out.re_list;
while (*rq && (*rq)->orq_retry - orq->orq_retry <= 0) while (*rq && (int32_t)((*rq)->orq_retry - orq->orq_retry) <= 0)
rq = &(*rq)->orq_rnext; rq = &(*rq)->orq_rnext;
if ((orq->orq_rnext = *rq)) if ((orq->orq_rnext = *rq))
@ -7966,7 +7985,7 @@ void outgoing_destroy(nta_outgoing_t *orq)
*/ */
static void outgoing_timer(nta_agent_t *sa) static void outgoing_timer(nta_agent_t *sa)
{ {
su_duration_t now = sa->sa_millisec; uint32_t now = sa->sa_millisec;
nta_outgoing_t *orq; nta_outgoing_t *orq;
outgoing_queue_t rq[1]; outgoing_queue_t rq[1];
size_t retransmitted = 0, terminated = 0, timeout = 0, destroyed; size_t retransmitted = 0, terminated = 0, timeout = 0, destroyed;
@ -7980,7 +7999,7 @@ static void outgoing_timer(nta_agent_t *sa)
outgoing_queue_init(sa->sa_out.free = rq, 0); outgoing_queue_init(sa->sa_out.free = rq, 0);
while ((orq = sa->sa_out.re_list)) { while ((orq = sa->sa_out.re_list)) {
if (orq->orq_retry - now > 0) if ((int32_t)(orq->orq_retry) - now > 0)
break; break;
if (retransmitted >= timer_max_retransmit) if (retransmitted >= timer_max_retransmit)
break; break;
@ -8076,13 +8095,14 @@ void outgoing_trying(nta_outgoing_t *orq)
static static
size_t outgoing_timer_bf(outgoing_queue_t *q, size_t outgoing_timer_bf(outgoing_queue_t *q,
char const *timer, char const *timer,
su_duration_t now) uint32_t now)
{ {
nta_outgoing_t *orq; nta_outgoing_t *orq;
size_t timeout = 0; size_t timeout = 0;
while ((orq = q->q_head)) { while ((orq = q->q_head)) {
if (orq->orq_timeout - now > 0 || timeout >= timer_max_timeout) if ((int32_t)(orq->orq_timeout - now) > 0 ||
timeout >= timer_max_timeout)
break; break;
timeout++; timeout++;
@ -8097,7 +8117,7 @@ size_t outgoing_timer_bf(outgoing_queue_t *q,
else else
outgoing_terminate(orq); outgoing_terminate(orq);
assert(q->q_head != orq || orq->orq_timeout - now > 0); assert(q->q_head != orq || (int32_t)(orq->orq_timeout - now) > 0);
} }
return timeout; return timeout;
@ -8107,7 +8127,7 @@ size_t outgoing_timer_bf(outgoing_queue_t *q,
static static
size_t outgoing_timer_c(outgoing_queue_t *q, size_t outgoing_timer_c(outgoing_queue_t *q,
char const *timer, char const *timer,
su_duration_t now) uint32_t now)
{ {
nta_outgoing_t *orq; nta_outgoing_t *orq;
size_t timeout = 0; size_t timeout = 0;
@ -8116,7 +8136,7 @@ size_t outgoing_timer_c(outgoing_queue_t *q,
return 0; return 0;
while ((orq = q->q_head)) { while ((orq = q->q_head)) {
if (orq->orq_timeout - now > 0 || timeout >= timer_max_timeout) if ((int32_t)(orq->orq_timeout - now) > 0 || timeout >= timer_max_timeout)
break; break;
timeout++; timeout++;
@ -8136,7 +8156,7 @@ size_t outgoing_timer_c(outgoing_queue_t *q,
} }
/** @internal Signal transaction timeout to the application. */ /** @internal Signal transaction timeout to the application. */
void outgoing_timeout(nta_outgoing_t *orq, su_duration_t now) void outgoing_timeout(nta_outgoing_t *orq, uint32_t now)
{ {
nta_outgoing_t *cancel; nta_outgoing_t *cancel;
@ -8184,13 +8204,14 @@ int outgoing_complete(nta_outgoing_t *orq)
static static
size_t outgoing_timer_dk(outgoing_queue_t *q, size_t outgoing_timer_dk(outgoing_queue_t *q,
char const *timer, char const *timer,
su_duration_t now) uint32_t now)
{ {
nta_outgoing_t *orq; nta_outgoing_t *orq;
size_t terminated = 0; size_t terminated = 0;
while ((orq = q->q_head)) { while ((orq = q->q_head)) {
if (orq->orq_timeout - now > 0 || terminated >= timer_max_terminate) if ((int32_t)(orq->orq_timeout - now) > 0 ||
terminated >= timer_max_terminate)
break; break;
terminated++; terminated++;

View File

@ -102,9 +102,9 @@ struct nta_agent_s
nta_update_magic_t *sa_update_magic; nta_update_magic_t *sa_update_magic;
nta_update_tport_f *sa_update_tport; nta_update_tport_f *sa_update_tport;
su_duration_t sa_next; /**< Timestamp for next agent_timer. */
su_time_t sa_now; /**< Timestamp in microsecond resolution. */ su_time_t sa_now; /**< Timestamp in microsecond resolution. */
uint32_t sa_millisec; /**< Timestamp in milliseconds resolution. */ uint32_t sa_next; /**< Timestamp for next agent_timer. */
uint32_t sa_millisec; /**< Timestamp in milliseconds. */
uint32_t sa_nw_updates; /* Shall we enable network detector? */ uint32_t sa_nw_updates; /* Shall we enable network detector? */
@ -419,8 +419,8 @@ struct nta_incoming_s
sip_timestamp_t *irq_timestamp; sip_timestamp_t *irq_timestamp;
su_time_t irq_received; su_time_t irq_received;
su_duration_t irq_timeout; /**< Timer H, I, J */ uint32_t irq_timeout; /**< Timer H, I, J */
su_duration_t irq_retry; /**< Timer G */ uint32_t irq_retry; /**< Timer G */
unsigned short irq_interval; /**< Next timer */ unsigned short irq_interval; /**< Next timer */
short irq_status; short irq_status;
@ -499,8 +499,8 @@ struct nta_outgoing_s
su_time_t orq_sent; /**< When request was sent? */ su_time_t orq_sent; /**< When request was sent? */
unsigned orq_delay; /**< RTT estimate */ unsigned orq_delay; /**< RTT estimate */
su_duration_t orq_retry; /**< Timer A, E */ uint32_t orq_retry; /**< Timer A, E */
su_duration_t orq_timeout; /**< Timer B, D, F, K */ uint32_t orq_timeout; /**< Timer B, D, F, K */
unsigned short orq_interval; /**< Next timer A/E */ unsigned short orq_interval; /**< Next timer A/E */