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-2023 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 
41 static time_t gtc_base = 0;
42 static DWORD gtc_last = 0;
43 static time_t last_sec = 0;
44 static unsigned int last_msec = 0;
45 static int bt_last = 0;
46 
47 static void
48 gettimeofday_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  */
61 int
62 gettimeofday(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 
120 int
121 gettimeofday(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 */
compat.h
config.h