OpenVPN
compat-gettimeofday.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2024 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#ifndef HAVE_GETTIMEOFDAY
29
30#include "compat.h"
31
32#ifdef _WIN32
33/*
34 * NOTICE: mingw has much faster gettimeofday!
35 * autoconf will set HAVE_GETTIMEOFDAY
36 */
37
38#include <windows.h>
39#include <time.h>
40
41static time_t gtc_base = 0;
42static DWORD gtc_last = 0;
43static time_t last_sec = 0;
44static unsigned int last_msec = 0;
45static int bt_last = 0;
46
47static void
48gettimeofday_calibrate(void)
49{
50 const time_t t = time(NULL);
51 const DWORD gtc = GetTickCount();
52 gtc_base = t - gtc/1000;
53 gtc_last = gtc;
54}
55
56/*
57 * Rewritten by JY for OpenVPN 2.1, after I realized that
58 * QueryPerformanceCounter takes nearly 2 orders of magnitude
59 * more processor cycles than GetTickCount.
60 */
61int
62gettimeofday(struct timeval *tv, void *tz)
63{
64 const DWORD gtc = GetTickCount();
65 int bt = 0;
66 time_t sec;
67 unsigned int msec;
68 const int backtrack_hold_seconds = 10;
69
70 (void)tz;
71
72 /* recalibrate at the dreaded 49.7 day mark */
73 if (!gtc_base || gtc < gtc_last)
74 {
75 gettimeofday_calibrate();
76 }
77 gtc_last = gtc;
78
79 sec = gtc_base + gtc / 1000;
80 msec = gtc % 1000;
81
82 if (sec == last_sec)
83 {
84 if (msec < last_msec)
85 {
86 msec = last_msec;
87 bt = 1;
88 }
89 }
90 else if (sec < last_sec)
91 {
92 /* We try to dampen out backtracks of less than backtrack_hold_seconds.
93 * Larger backtracks will be passed through and dealt with by the
94 * TIME_BACKTRACK_PROTECTION code */
95 if (sec > last_sec - backtrack_hold_seconds)
96 {
97 sec = last_sec;
98 msec = last_msec;
99 }
100 bt = 1;
101 }
102
103 last_sec = sec;
104 tv->tv_sec = (long)sec;
105 tv->tv_usec = (last_msec = msec) * 1000;
106
107 if (bt && !bt_last)
108 {
109 gettimeofday_calibrate();
110 }
111 bt_last = bt;
112
113 return 0;
114}
115
116#else /* ifdef _WIN32 */
117
118#include <time.h>
119
120int
121gettimeofday(struct timeval *tv, void *tz)
122{
123 (void)tz;
124 tv->tv_sec = time(NULL);
125 tv->tv_usec = 0;
126 return 0;
127}
128
129#endif /* _WIN32 */
130
131#endif /* HAVE_GETTIMEOFDAY */