Recognize a matching check if it's an INVALID message (error with no error-code)
[sipe-libnice.git] / stun / usages / timer.c
blobce711c2c099ea9c65e15058d9d61bfd96143f1d9
1 /*
2 * This file is part of the Nice GLib ICE library.
4 * (C) 2008-2009 Collabora Ltd.
5 * Contact: Youness Alaoui
6 * (C) 2007-2009 Nokia Corporation. All rights reserved.
7 * Contact: Rémi Denis-Courmont
9 * The contents of this file are subject to the Mozilla Public License Version
10 * 1.1 (the "License"); you may not use this file except in compliance with
11 * the License. You may obtain a copy of the License at
12 * http://www.mozilla.org/MPL/
14 * Software distributed under the License is distributed on an "AS IS" basis,
15 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16 * for the specific language governing rights and limitations under the
17 * License.
19 * The Original Code is the Nice GLib ICE library.
21 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22 * Corporation. All Rights Reserved.
24 * Contributors:
25 * Youness Alaoui, Collabora Ltd.
26 * Rémi Denis-Courmont, Nokia
28 * Alternatively, the contents of this file may be used under the terms of the
29 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
30 * case the provisions of LGPL are applicable instead of those above. If you
31 * wish to allow use of your version of this file only under the terms of the
32 * LGPL and not to allow others to use your version of this file under the
33 * MPL, indicate your decision by deleting the provisions above and replace
34 * them with the notice and other provisions required by the LGPL. If you do
35 * not delete the provisions above, a recipient may use your version of this
36 * file under either the MPL or the LGPL.
39 #ifdef HAVE_CONFIG_H
40 # include <config.h>
41 #endif
43 #ifdef _WIN32
44 #define WIN32_LEAN_AND_MEAN
45 #include <windows.h>
46 #else
47 #include <unistd.h>
48 #endif
50 #include "timer.h"
52 #include <stdlib.h> /* div() */
55 * Clock used throughout the STUN code.
56 * STUN requires a monotonic 1kHz clock to operate properly.
58 static void stun_gettime (struct timeval *now)
60 #ifdef _WIN32
61 FILETIME ft;
62 unsigned long long *time64 = (unsigned long long *) &ft;
64 GetSystemTimeAsFileTime (&ft);
66 /* Convert from 100s of nanoseconds since 1601-01-01
67 * to Unix epoch. Yes, this is Y2038 unsafe.
69 *time64 -= (unsigned long long) 116444736000000000;
70 *time64 /= 10;
72 now->tv_sec = (long)(*time64 / 1000000);
73 now->tv_usec = *time64 % 1000000;
74 #else
75 #if defined (_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0)
76 struct timespec spec;
77 if (!clock_gettime (CLOCK_MONOTONIC, &spec)) {
78 now->tv_sec = spec.tv_sec;
79 now->tv_usec = spec.tv_nsec / 1000;
80 } else
81 #endif
82 { // fallback to wall clock
83 gettimeofday (now, NULL);
85 #endif
89 static void add_delay (struct timeval *ts, unsigned delay)
91 div_t d = div (delay, 1000);
92 ts->tv_sec += d.quot;
93 ts->tv_usec += d.rem * 1000;
95 while (ts->tv_usec > 1000000)
97 ts->tv_usec -= 1000000;
98 ts->tv_sec++;
103 void stun_timer_start (StunTimer *timer, unsigned int initial_timeout,
104 unsigned int max_retransmissions)
106 stun_gettime (&timer->deadline);
107 timer->retransmissions = 0;
108 timer->delay = initial_timeout;
109 timer->max_retransmissions = max_retransmissions;
110 add_delay (&timer->deadline, timer->delay);
114 void stun_timer_start_reliable (StunTimer *timer, unsigned int initial_timeout)
116 stun_timer_start (timer, initial_timeout, 0);
121 unsigned stun_timer_remainder (const StunTimer *timer)
123 unsigned delay;
124 struct timeval now;
126 stun_gettime (&now);
127 if (now.tv_sec > timer->deadline.tv_sec)
128 return 0;
130 delay = timer->deadline.tv_sec - now.tv_sec;
131 if ((delay == 0) && (now.tv_usec >= timer->deadline.tv_usec))
132 return 0;
134 delay *= 1000;
135 delay += ((signed)(timer->deadline.tv_usec - now.tv_usec)) / 1000;
136 return delay;
140 StunUsageTimerReturn stun_timer_refresh (StunTimer *timer)
142 unsigned delay = stun_timer_remainder (timer);
143 if (delay == 0)
145 if (timer->retransmissions >= timer->max_retransmissions)
146 return STUN_USAGE_TIMER_RETURN_TIMEOUT;
148 add_delay (&timer->deadline, timer->delay *= 2);
149 timer->retransmissions++;
150 return STUN_USAGE_TIMER_RETURN_RETRANSMIT;
153 return STUN_USAGE_TIMER_RETURN_SUCCESS;