OpenVPN 3 Core Library
Loading...
Searching...
No Matches
time.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#pragma once
13
14#include <chrono>
15#include <cstdint> // for std::uint32_t, uint64_t
16#include <limits>
17
23
24
25#ifdef OPENVPN_PLATFORM_WIN
26#include <time.h> // for ::time() on Windows
27#include <windows.h> // for GetTickCount64
28#else
29#include <sys/time.h> // for ::time() and ::gettimeofday()
30#endif
31
32namespace openvpn {
34
56template <typename T>
58{
59 public:
60 enum
61 {
62 prec = 1024
63 };
64 typedef ::time_t base_type;
65 typedef T type;
66
68 {
69 friend class TimeType;
70
71 public:
72 static Duration seconds(const T v)
73 {
74 return Duration(v * prec);
75 }
76 static Duration binary_ms(const T v)
77 {
78 return Duration(v);
79 }
81 {
82 return Duration(std::numeric_limits<T>::max());
83 }
84
85 static Duration milliseconds(const T v)
86 {
87 // NOTE: assumes that prec == 1024
88 // Also note that this might wrap if v is larger than 1/3 of max size of T
89 return Duration(v + (v * T(3) / T(128)));
90 }
91
92 static Duration milliseconds(std::chrono::milliseconds ms)
93 {
94 /* Windows on 32 bit platforms warns about loss of precision otherwise */
95 return milliseconds(openvpn::numeric_util::numeric_cast<T>(ms.count()));
96 }
97
98 Duration() noexcept
99 : duration_(T(0))
100 {
101 }
102
103 bool defined() const
104 {
105 return duration_ != T(0);
106 }
107 bool operator!() const
108 {
109 return duration_ == T(0);
110 }
111 bool is_infinite() const
112 {
113 return duration_ == std::numeric_limits<T>::max();
114 }
115 bool enabled() const
116 {
117 return defined() && !is_infinite();
118 }
120 {
121 duration_ = std::numeric_limits<T>::max();
122 }
123 void set_zero()
124 {
125 duration_ = T(0);
126 }
127
129 {
130 if (is_infinite() || d.is_infinite())
131 return infinite();
132 else
133 return Duration(duration_ + d.duration_);
134 }
135
136 Duration operator+(const int delta) const
137 {
138 if (is_infinite())
139 return infinite();
140 T duration = duration_;
141 if (delta >= 0)
142 duration += delta;
143 else
144 {
145 const unsigned int ndelta = -delta;
146 if (duration_ >= ndelta)
147 duration -= ndelta;
148 else
149 duration = 0;
150 }
151 return Duration(duration);
152 }
153
154 Duration operator*(const unsigned int mult) const
155 {
156 return Duration(duration_ * mult);
157 }
158
160 {
161 if (is_infinite() || d.is_infinite())
162 set_infinite();
163 else
164 duration_ += d.duration_;
165 return *this;
166 }
167
168 void min(const Duration &d)
169 {
170 if (d.duration_ < duration_)
172 }
173
174 void max(const Duration &d)
175 {
176 if (d.duration_ > duration_)
178 }
179
181 {
182 if (d.duration_ >= duration_)
183 return Duration(0);
184 else if (is_infinite())
185 return Duration::infinite();
186 else
187 return Duration(duration_ - d.duration_);
188 }
189
191 {
192 if (d.duration_ >= duration_)
193 set_zero();
194 else if (!is_infinite())
195 duration_ -= d.duration_;
196 return *this;
197 }
198
199 T to_seconds() const
200 {
201 return duration_ / prec;
202 }
203 T to_binary_ms() const
204 {
205 return duration_;
206 }
207
209 {
210 // NOTE: assumes that prec == 1024
211 // Also note that this might wrap if duration_ is larger than 1/3 of max size of T
212 return duration_ - (duration_ * T(3) / T(128));
213 }
214
215 double to_double() const
216 {
217 return double(duration_) / double(prec);
218 }
219
220 T raw() const
221 {
222 return duration_;
223 }
224
225#define OPENVPN_DURATION_REL(OP) \
226 bool operator OP(const Duration &d) const \
227 { \
228 return duration_ OP d.duration_; \
229 }
236#undef OPENVPN_DURATION_REL
237
238 private:
239 explicit Duration(const T duration)
240 : duration_(duration)
241 {
242 }
243
245 };
246
247 TimeType() noexcept
248 : time_(T(0))
249 {
250 }
251
252 static TimeType zero()
253 {
254 return TimeType(T(0));
255 }
257 {
258 return TimeType(std::numeric_limits<T>::max());
259 }
260
261 static TimeType from_seconds_since_epoch(const time_t t)
262 {
263 if (t <= base_)
264 return TimeType(T(1));
265 else
266 return TimeType(T((t - base_) * prec));
267 }
268
269 bool is_infinite() const
270 {
271 return time_ == std::numeric_limits<T>::max();
272 }
273
274 void reset()
275 {
276 time_ = 0;
277 }
279 {
280 time_ = std::numeric_limits<T>::max();
281 }
282
283 bool defined() const
284 {
285 return time_ != 0;
286 }
287 bool operator!() const
288 {
289 return time_ == 0;
290 }
291
293 {
294 return base_ + time_ / prec;
295 }
296 std::uint64_t nanoseconds_since_epoch() const
297 {
298 return base_ * 1000000000ull + time_ * (1000000000ull / prec);
299 }
301 {
302 return time_ % prec;
303 }
304
305 static TimeType now()
306 {
307 return TimeType(now_());
308 }
309
310 void update()
311 {
312 time_ = now_();
313 }
314
316 {
317 if (is_infinite() || d.is_infinite())
318 return infinite();
319 else
320 return TimeType(time_ + d.duration_);
321 }
322
324 {
325 if (is_infinite() || d.is_infinite())
326 set_infinite();
327 else
328 time_ += d.duration_;
329 return *this;
330 }
331
333 {
334 if (t.time_ >= time_)
335 return Duration(0);
336 else if (is_infinite())
337 return Duration::infinite();
338 else
339 return Duration(time_ - t.time_);
340 }
341
342 void min(const TimeType &t)
343 {
344 if (t.time_ < time_)
345 time_ = t.time_;
346 }
347
348 void max(const TimeType &t)
349 {
350 if (t.time_ > time_)
351 time_ = t.time_;
352 }
353
354 long delta_prec(const TimeType &t) const
355 {
356 return long(time_) - long(t.time_);
357 }
358
359 long delta(const TimeType &t) const
360 {
361 return delta_prec(t) / long(prec);
362 }
363
364 double delta_float(const TimeType &t) const
365 {
366 return (double(time_) - double(t.time_)) / double(prec);
367 }
368
372 std::string delta_str(const TimeType &t) const
373 {
374 if (!defined())
375 return "UNDEF-TIME";
376 if (is_infinite())
377 return "+INF";
378 const double df = delta_float(t);
379 std::string ret;
380 if (df >= 0.0)
381 ret += '+';
382 const int idf = int(df);
383 if (df == static_cast<double>(idf))
384 ret += openvpn::to_string(idf);
385 else
386 ret += openvpn::to_string(df);
387 return ret;
388 }
389
390#define OPENVPN_TIME_REL(OP) \
391 bool operator OP(const TimeType &t) const \
392 { \
393 return time_ OP t.time_; \
394 }
401#undef OPENVPN_TIME_REL
402
403 template <typename HASH>
404 void hash(HASH &h) const
405 {
406 h(time_);
407 }
408
409 T raw() const
410 {
411 return time_;
412 }
413
415 {
416 // on 32-bit systems, reset time base after 30 days
417 if (sizeof(T) == 4)
418 {
419 const base_type newbase = ::time(NULL);
420 if (newbase - base_ >= (60 * 60 * 24 * 30))
421 reset_base();
422 }
423 }
424
425 static void reset_base()
426 {
427#ifdef OPENVPN_TIME_NO_BASE
428 static_assert(sizeof(base_type) >= 8, "OPENVPN_TIME_NO_BASE requires time_t to be 64 bits");
429#else
430 base_ = ::time(NULL);
431#ifdef OPENVPN_PLATFORM_WIN
432 win_recalibrate(::GetTickCount64());
433#endif
434#endif
435 }
436
438 static uint64_t win_time()
439 {
440 // NOTE: assumes that prec == 1024
441 return ((11644473600ULL * uint64_t(prec)) + (uint64_t(base_) * uint64_t(prec)) + uint64_t(now_())) * 78125ULL / 8ULL;
442 }
443
444 private:
445 explicit TimeType(const T time)
446 : time_(time)
447 {
448 }
449
450#ifdef OPENVPN_PLATFORM_WIN
451
452 static void win_recalibrate(const ULONGLONG gtc)
453 {
454 gtc_last = gtc;
455 gtc_base = ::time(NULL) - gtc_last / 1000;
456 }
457
458 static T now_()
459 {
460 const ULONGLONG gtc = ::GetTickCount64();
461 if (gtc < gtc_last)
462 win_recalibrate(gtc);
463 const time_t sec = gtc_base + gtc / 1000;
464 const unsigned int msec = gtc % 1000;
465 return T((sec - base_) * prec + msec * prec / 1000);
466 }
467
468 static inline ULONGLONG gtc_last = 0;
469 static inline time_t gtc_base = 0;
470
471#else
472
473 static T now_()
474 {
475 ::timeval tv;
476 if (::gettimeofday(&tv, nullptr) != 0)
477 throw get_time_error();
478 return T((tv.tv_sec - base_) * prec + tv.tv_usec * prec / 1000000);
479 }
480
481#endif
482
483#ifdef OPENVPN_TIME_NO_BASE
484 static constexpr base_type base_ = 0;
485#else
486 static inline base_type base_ = 0;
487#endif
488
490};
491
493
494typedef Time *TimePtr;
495
496} // namespace openvpn
static Duration binary_ms(const T v)
Definition time.hpp:76
static Duration infinite()
Definition time.hpp:80
void min(const Duration &d)
Definition time.hpp:168
Duration(const T duration)
Definition time.hpp:239
void max(const Duration &d)
Definition time.hpp:174
Duration operator+(const Duration &d) const
Definition time.hpp:128
Duration & operator+=(const Duration &d)
Definition time.hpp:159
double to_double() const
Definition time.hpp:215
Duration operator-(const Duration &d) const
Definition time.hpp:180
Duration operator+(const int delta) const
Definition time.hpp:136
static Duration milliseconds(std::chrono::milliseconds ms)
Definition time.hpp:92
Duration & operator-=(const Duration &d)
Definition time.hpp:190
static Duration milliseconds(const T v)
Definition time.hpp:85
static Duration seconds(const T v)
Definition time.hpp:72
bool is_infinite() const
Definition time.hpp:111
Duration operator*(const unsigned int mult) const
Definition time.hpp:154
static TimeType from_seconds_since_epoch(const time_t t)
Definition time.hpp:261
std::string delta_str(const TimeType &t) const
Definition time.hpp:372
static T now_()
Definition time.hpp:473
TimeType & operator+=(const Duration &d)
Definition time.hpp:323
bool operator!() const
Definition time.hpp:287
T raw() const
Definition time.hpp:409
static TimeType infinite()
Definition time.hpp:256
static void reset_base()
Definition time.hpp:425
::time_t base_type
Definition time.hpp:64
static TimeType zero()
Definition time.hpp:252
void max(const TimeType &t)
Definition time.hpp:348
static base_type base_
Definition time.hpp:486
TimeType(const T time)
Definition time.hpp:445
void min(const TimeType &t)
Definition time.hpp:342
std::uint64_t nanoseconds_since_epoch() const
Definition time.hpp:296
static TimeType now()
Definition time.hpp:305
static uint64_t win_time()
Definition time.hpp:438
base_type seconds_since_epoch() const
Definition time.hpp:292
static void reset_base_conditional()
Definition time.hpp:414
long delta_prec(const TimeType &t) const
Definition time.hpp:354
Duration operator-(const TimeType &t) const
Definition time.hpp:332
long delta(const TimeType &t) const
Definition time.hpp:359
void hash(HASH &h) const
Definition time.hpp:404
TimeType() noexcept
Definition time.hpp:247
TimeType operator+(const Duration &d) const
Definition time.hpp:315
double delta_float(const TimeType &t) const
Definition time.hpp:364
T fractional_binary_ms() const
Definition time.hpp:300
void set_infinite()
Definition time.hpp:278
bool defined() const
Definition time.hpp:283
bool is_infinite() const
Definition time.hpp:269
#define OPENVPN_SIMPLE_EXCEPTION(C)
Definition exception.hpp:75
Support deferred server-side state creation when client connects.
Definition ovpncli.cpp:95
std::string to_string(T value)
Definition to_string.hpp:33
Time * TimePtr
Definition time.hpp:494
TimeType< oulong > Time
Definition time.hpp:492
std::string ret
#define OPENVPN_TIME_REL(OP)
Definition time.hpp:390
#define OPENVPN_DURATION_REL(OP)
Definition time.hpp:225