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