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
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.
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.
44 #define WIN32_LEAN_AND_MEAN
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
)
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;
72 now
->tv_sec
= (long)(*time64
/ 1000000);
73 now
->tv_usec
= *time64
% 1000000;
75 #if defined (_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0)
77 if (!clock_gettime (CLOCK_MONOTONIC
, &spec
)) {
78 now
->tv_sec
= spec
.tv_sec
;
79 now
->tv_usec
= spec
.tv_nsec
/ 1000;
82 { // fallback to wall clock
83 gettimeofday (now
, NULL
);
89 static void add_delay (struct timeval
*ts
, unsigned delay
)
91 div_t d
= div (delay
, 1000);
93 ts
->tv_usec
+= d
.rem
* 1000;
95 while (ts
->tv_usec
> 1000000)
97 ts
->tv_usec
-= 1000000;
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
)
127 if (now
.tv_sec
> timer
->deadline
.tv_sec
)
130 delay
= timer
->deadline
.tv_sec
- now
.tv_sec
;
131 if ((delay
== 0) && (now
.tv_usec
>= timer
->deadline
.tv_usec
))
135 delay
+= ((signed)(timer
->deadline
.tv_usec
- now
.tv_usec
)) / 1000;
140 StunUsageTimerReturn
stun_timer_refresh (StunTimer
*timer
)
142 unsigned delay
= stun_timer_remainder (timer
);
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
;