cosmetics
[tomato.git] / release / src / router / openvpn / otime.c
blobcba953d8f35737e3b15e83848a7db9d14f5d8670
1 /*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
8 * Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
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.
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.
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
25 #include "syshead.h"
27 #include "otime.h"
29 #include "memdbg.h"
31 time_t now = 0; /* GLOBAL */
33 #if TIME_BACKTRACK_PROTECTION && defined(HAVE_GETTIMEOFDAY)
35 static time_t now_adj = 0; /* GLOBAL */
36 time_t now_usec = 0; /* GLOBAL */
39 * Try to filter out time instability caused by the system
40 * clock backtracking or jumping forward.
43 void
44 update_now (const time_t system_time)
46 const int forward_threshold = 86400; /* threshold at which to dampen forward jumps */
47 const int backward_trigger = 10; /* backward jump must be >= this many seconds before we adjust */
48 time_t real_time = system_time + now_adj;
50 if (real_time > now)
52 const time_t overshoot = real_time - now - 1;
53 if (overshoot > forward_threshold && now_adj >= overshoot)
55 now_adj -= overshoot;
56 real_time -= overshoot;
58 now = real_time;
60 else if (real_time < now - backward_trigger)
61 now_adj += (now - real_time);
64 void
65 update_now_usec (struct timeval *tv)
67 const time_t last = now;
68 update_now (tv->tv_sec);
69 if (now > last || (now == last && tv->tv_usec > now_usec))
70 now_usec = tv->tv_usec;
73 #endif /* TIME_BACKTRACK_PROTECTION && defined(HAVE_GETTIMEOFDAY) */
75 /*
76 * Return a numerical string describing a struct timeval.
78 const char *
79 tv_string (const struct timeval *tv, struct gc_arena *gc)
81 struct buffer out = alloc_buf_gc (64, gc);
82 buf_printf (&out, "[%d/%d]",
83 (int) tv->tv_sec,
84 (int )tv->tv_usec);
85 return BSTR (&out);
88 /*
89 * Return an ascii string describing an absolute
90 * date/time in a struct timeval.
93 const char *
94 tv_string_abs (const struct timeval *tv, struct gc_arena *gc)
96 return time_string ((time_t) tv->tv_sec,
97 (int) tv->tv_usec,
98 true,
99 gc);
102 /* format a time_t as ascii, or use current time if 0 */
104 const char *
105 time_string (time_t t, int usec, bool show_usec, struct gc_arena *gc)
107 struct buffer out = alloc_buf_gc (64, gc);
108 struct timeval tv;
110 if (t)
112 tv.tv_sec = t;
113 tv.tv_usec = usec;
115 else
117 #ifdef HAVE_GETTIMEOFDAY
118 if (gettimeofday (&tv, NULL))
119 #endif
121 tv.tv_sec = time (NULL);
122 tv.tv_usec = 0;
126 mutex_lock_static (L_CTIME);
127 t = tv.tv_sec;
128 buf_printf (&out, "%s", ctime(&t));
129 mutex_unlock_static (L_CTIME);
130 buf_rmtail (&out, '\n');
132 if (show_usec && tv.tv_usec)
133 buf_printf (&out, " us=%d", (int)tv.tv_usec);
135 return BSTR (&out);
139 * Limit the frequency of an event stream.
141 * Used to control maximum rate of new
142 * incoming connections.
145 struct frequency_limit *
146 frequency_limit_init (int max, int per)
148 struct frequency_limit *f;
150 ASSERT (max >= 0 && per >= 0);
152 ALLOC_OBJ (f, struct frequency_limit);
153 f->max = max;
154 f->per = per;
155 f->n = 0;
156 f->reset = 0;
157 return f;
160 void
161 frequency_limit_free (struct frequency_limit *f)
163 free (f);
166 bool
167 frequency_limit_event_allowed (struct frequency_limit *f)
169 if (f->per)
171 bool ret;
172 if (now >= f->reset + f->per)
174 f->reset = now;
175 f->n = 0;
177 ret = (++f->n <= f->max);
178 return ret;
180 else
181 return true;
184 #ifdef WIN32
186 static time_t gtc_base = 0;
187 static DWORD gtc_last = 0;
188 static time_t last_sec = 0;
189 static unsigned int last_msec = 0;
190 static bool bt_last = false;
192 static void
193 gettimeofday_calibrate (void)
195 const time_t t = time(NULL);
196 const DWORD gtc = GetTickCount();
197 gtc_base = t - gtc/1000;
198 gtc_last = gtc;
202 * Rewritten by JY for OpenVPN 2.1, after I realized that
203 * QueryPerformanceCounter takes nearly 2 orders of magnitude
204 * more processor cycles than GetTickCount.
207 gettimeofday (struct timeval *tv, void *tz)
209 const DWORD gtc = GetTickCount();
210 bool bt = false;
211 time_t sec;
212 unsigned int msec;
213 const int backtrack_hold_seconds = 10;
215 /* recalibrate at the dreaded 49.7 day mark */
216 if (!gtc_base || gtc < gtc_last)
217 gettimeofday_calibrate ();
218 gtc_last = gtc;
220 sec = gtc_base + gtc / 1000;
221 msec = gtc % 1000;
223 if (sec == last_sec)
225 if (msec < last_msec)
227 msec = last_msec;
228 bt = true;
231 else if (sec < last_sec)
233 /* We try to dampen out backtracks of less than backtrack_hold_seconds.
234 Larger backtracks will be passed through and dealt with by the
235 TIME_BACKTRACK_PROTECTION code (if enabled) */
236 if (sec > last_sec - backtrack_hold_seconds)
238 sec = last_sec;
239 msec = last_msec;
241 bt = true;
244 tv->tv_sec = last_sec = sec;
245 tv->tv_usec = (last_msec = msec) * 1000;
247 if (bt && !bt_last)
248 gettimeofday_calibrate ();
249 bt_last = bt;
251 return 0;
254 #endif /* WIN32 */
256 #ifdef TIME_TEST
257 void
258 time_test (void)
260 struct timeval tv;
261 time_t t;
262 int i;
263 for (i = 0; i < 10000; ++i)
265 t = time(NULL);
266 gettimeofday (&tv, NULL);
267 #if 1
268 msg (M_INFO, "t=%u s=%u us=%u",
269 (unsigned int)t,
270 (unsigned int)tv.tv_sec,
271 (unsigned int)tv.tv_usec);
272 #endif
275 #endif