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-2018 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 #elif defined(_MSC_VER)
27 #include "config-msvc.h"
28 #endif
29 
30 #ifndef HAVE_GETTIMEOFDAY
31 
32 #include "compat.h"
33 
34 #ifdef _WIN32
35 /*
36  * NOTICE: mingw has much faster gettimeofday!
37  * autoconf will set HAVE_GETTIMEOFDAY
38  */
39 
40 #include <windows.h>
41 #include <time.h>
42 
43 static time_t gtc_base = 0;
44 static DWORD gtc_last = 0;
45 static time_t last_sec = 0;
46 static unsigned int last_msec = 0;
47 static int bt_last = 0;
48 
49 static void
50 gettimeofday_calibrate(void)
51 {
52  const time_t t = time(NULL);
53  const DWORD gtc = GetTickCount();
54  gtc_base = t - gtc/1000;
55  gtc_last = gtc;
56 }
57 
58 /*
59  * Rewritten by JY for OpenVPN 2.1, after I realized that
60  * QueryPerformanceCounter takes nearly 2 orders of magnitude
61  * more processor cycles than GetTickCount.
62  */
63 int
64 gettimeofday(struct timeval *tv, void *tz)
65 {
66  const DWORD gtc = GetTickCount();
67  int bt = 0;
68  time_t sec;
69  unsigned int msec;
70  const int backtrack_hold_seconds = 10;
71 
72  (void)tz;
73 
74  /* recalibrate at the dreaded 49.7 day mark */
75  if (!gtc_base || gtc < gtc_last)
76  {
77  gettimeofday_calibrate();
78  }
79  gtc_last = gtc;
80 
81  sec = gtc_base + gtc / 1000;
82  msec = gtc % 1000;
83 
84  if (sec == last_sec)
85  {
86  if (msec < last_msec)
87  {
88  msec = last_msec;
89  bt = 1;
90  }
91  }
92  else if (sec < last_sec)
93  {
94  /* We try to dampen out backtracks of less than backtrack_hold_seconds.
95  * Larger backtracks will be passed through and dealt with by the
96  * TIME_BACKTRACK_PROTECTION code (if enabled) */
97  if (sec > last_sec - backtrack_hold_seconds)
98  {
99  sec = last_sec;
100  msec = last_msec;
101  }
102  bt = 1;
103  }
104 
105  tv->tv_sec = (long)last_sec = (long)sec;
106  tv->tv_usec = (last_msec = msec) * 1000;
107 
108  if (bt && !bt_last)
109  {
110  gettimeofday_calibrate();
111  }
112  bt_last = bt;
113 
114  return 0;
115 }
116 
117 #else /* ifdef _WIN32 */
118 
119 #ifdef HAVE_TIME_H
120 #include <time.h>
121 #endif
122 
123 int
124 gettimeofday(struct timeval *tv, void *tz)
125 {
126  (void)tz;
127  tv->tv_sec = time(NULL);
128  tv->tv_usec = 0;
129  return 0;
130 }
131 
132 #endif /* _WIN32 */
133 
134 #endif /* HAVE_GETTIMEOFDAY */