mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-04-24 00:00:05 +08:00
Merge commit '86cc97e55fe346502462284d2e636a2b3708163e' as 'Sources/OpenVPN3'
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Create an Asio time_traits class to allow Asio to natively handle
|
||||
// our Time and Time::Duration classes.
|
||||
|
||||
#ifndef OPENVPN_TIME_ASIOTIMER_H
|
||||
#define OPENVPN_TIME_ASIOTIMER_H
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include <openvpn/io/io.hpp> // was: #include <asio/basic_waitable_timer.hpp>
|
||||
|
||||
#include <openvpn/common/olong.hpp>
|
||||
#include <openvpn/time/time.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
struct AsioClock
|
||||
{
|
||||
typedef olong rep;
|
||||
typedef std::ratio<1, 1024> period; // time resolution of openvpn::Time
|
||||
typedef std::chrono::duration<rep, period> duration;
|
||||
typedef std::chrono::time_point<AsioClock> time_point;
|
||||
|
||||
static constexpr bool is_steady()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static time_point now()
|
||||
{
|
||||
return to_time_point(Time::now());
|
||||
}
|
||||
|
||||
static time_point to_time_point(const Time& t)
|
||||
{
|
||||
return time_point(duration(t.raw()));
|
||||
}
|
||||
|
||||
static duration to_duration(const Time::Duration& d)
|
||||
{
|
||||
return duration(d.raw());
|
||||
}
|
||||
};
|
||||
|
||||
class AsioTimer : public openvpn_io::basic_waitable_timer<AsioClock>
|
||||
{
|
||||
public:
|
||||
AsioTimer(openvpn_io::io_context& io_context)
|
||||
: openvpn_io::basic_waitable_timer<AsioClock>(io_context)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t expires_at(const Time& t)
|
||||
{
|
||||
return openvpn_io::basic_waitable_timer<AsioClock>::expires_at(AsioClock::to_time_point(t));
|
||||
}
|
||||
|
||||
std::size_t expires_after(const Time::Duration& d)
|
||||
{
|
||||
return openvpn_io::basic_waitable_timer<AsioClock>::expires_after(AsioClock::to_duration(d));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,91 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/time/asiotimer.hpp>
|
||||
|
||||
// AsioTimerSafe is like AsioTimer but with strict cancellation
|
||||
// semantics that guarantees that a handler will never be called
|
||||
// with a non-error status after the timer is cancelled.
|
||||
|
||||
namespace openvpn {
|
||||
class AsioTimerSafe
|
||||
{
|
||||
public:
|
||||
AsioTimerSafe(openvpn_io::io_context& io_context)
|
||||
: timer_(io_context),
|
||||
epoch_(new Epoch)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t expires_at(const Time& t)
|
||||
{
|
||||
inc_epoch();
|
||||
return timer_.expires_at(t);
|
||||
}
|
||||
|
||||
std::size_t expires_after(const Time::Duration& d)
|
||||
{
|
||||
inc_epoch();
|
||||
return timer_.expires_after(d);
|
||||
}
|
||||
|
||||
std::size_t cancel()
|
||||
{
|
||||
inc_epoch();
|
||||
return timer_.cancel();
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void async_wait(F&& func)
|
||||
{
|
||||
inc_epoch();
|
||||
timer_.async_wait([func=std::move(func), epoch=epoch(), eptr=epoch_](const openvpn_io::error_code& error)
|
||||
{
|
||||
func(epoch == eptr->epoch ? error : openvpn_io::error::operation_aborted);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::size_t epoch_t;
|
||||
|
||||
struct Epoch : public RC<thread_unsafe_refcount>
|
||||
{
|
||||
typedef RCPtr<Epoch> Ptr;
|
||||
epoch_t epoch = 0;
|
||||
};
|
||||
|
||||
epoch_t epoch() const
|
||||
{
|
||||
return epoch_->epoch;
|
||||
}
|
||||
|
||||
void inc_epoch()
|
||||
{
|
||||
++epoch_->epoch;
|
||||
}
|
||||
|
||||
AsioTimer timer_;
|
||||
Epoch::Ptr epoch_;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef OPENVPN_TIME_COARSETIME_H
|
||||
#define OPENVPN_TIME_COARSETIME_H
|
||||
|
||||
#include <openvpn/time/time.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
// Used to compare two time objects within the accuracy limits
|
||||
// defined by pre and post.
|
||||
|
||||
class CoarseTime
|
||||
{
|
||||
public:
|
||||
CoarseTime() {}
|
||||
|
||||
CoarseTime(const Time::Duration& pre, const Time::Duration& post)
|
||||
: pre_(pre), post_(post) {}
|
||||
|
||||
void init(const Time::Duration& pre, const Time::Duration& post)
|
||||
{
|
||||
pre_ = pre;
|
||||
post_ = post;
|
||||
}
|
||||
|
||||
void reset(const Time& t) { time_ = t; }
|
||||
void reset() { time_.reset(); }
|
||||
|
||||
bool similar(const Time& t) const
|
||||
{
|
||||
if (time_.defined())
|
||||
{
|
||||
if (t >= time_)
|
||||
return (t - time_) <= post_;
|
||||
else
|
||||
return (time_ - t) <= pre_;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Time time_;
|
||||
Time::Duration pre_;
|
||||
Time::Duration post_;
|
||||
};
|
||||
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_TIME_COARSETIME_H
|
||||
@@ -0,0 +1,105 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef OPENVPN_TIME_DURHELPER_H
|
||||
#define OPENVPN_TIME_DURHELPER_H
|
||||
|
||||
#include <openvpn/common/options.hpp>
|
||||
#include <openvpn/time/time.hpp>
|
||||
#include <openvpn/random/randapi.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
inline void set_duration_parm(Time::Duration& dur,
|
||||
const std::string& name,
|
||||
const std::string& valstr,
|
||||
const unsigned int min_value,
|
||||
const bool x2, // multiply result by 2
|
||||
const bool ms) // values are in milliseconds rather than seconds
|
||||
{
|
||||
const unsigned int maxdur = ms ? 1000*60*60*24 : 60*60*24*7; // maximum duration -- milliseconds: 1 day, seconds: 7 days
|
||||
unsigned int value = 0;
|
||||
const bool status = parse_number<unsigned int>(valstr, value);
|
||||
if (!status)
|
||||
OPENVPN_THROW(option_error, name << ": error parsing number of " << (ms ? "milliseconds" : "seconds"));
|
||||
if (x2)
|
||||
value *= 2;
|
||||
if (value == 0 || value > maxdur)
|
||||
value = maxdur;
|
||||
if (value < min_value)
|
||||
value = min_value;
|
||||
dur = ms ? Time::Duration::milliseconds(value) : Time::Duration::seconds(value);
|
||||
}
|
||||
|
||||
inline const Option* load_duration_parm(Time::Duration& dur,
|
||||
const std::string& name,
|
||||
const OptionList& opt,
|
||||
const unsigned int min_value,
|
||||
const bool x2,
|
||||
const bool allow_ms)
|
||||
{
|
||||
// look for milliseconds given as <name>-ms
|
||||
if (allow_ms)
|
||||
{
|
||||
const Option *o = opt.get_ptr(name + "-ms");
|
||||
if (o)
|
||||
{
|
||||
set_duration_parm(dur, name, o->get(1, 16), min_value, x2, true);
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
// look for seconds given as <name>
|
||||
{
|
||||
const Option *o = opt.get_ptr(name);
|
||||
if (o)
|
||||
set_duration_parm(dur, name, o->get(1, 16), allow_ms ? 1 : min_value, x2, false);
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
inline Time::Duration load_duration_default(const std::string& name,
|
||||
const OptionList& opt,
|
||||
const Time::Duration& default_duration,
|
||||
const unsigned int min_value,
|
||||
const bool x2,
|
||||
const bool allow_ms)
|
||||
{
|
||||
Time::Duration ret(default_duration);
|
||||
load_duration_parm(ret, name, opt, min_value, x2, allow_ms);
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline Time::Duration skew_duration(const Time::Duration& dur,
|
||||
const Time::Duration& min,
|
||||
const unsigned int flux_order,
|
||||
RandomAPI& rng)
|
||||
{
|
||||
const unsigned int range = 1 << flux_order;
|
||||
const int delta = int(rng.rand_get<unsigned int>() & (range-1)) - int(range>>1);
|
||||
const Time::Duration ret = dur + delta;
|
||||
if (ret >= min)
|
||||
return ret;
|
||||
else
|
||||
return min;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,52 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef OPENVPN_TIME_EPOCH_H
|
||||
#define OPENVPN_TIME_EPOCH_H
|
||||
|
||||
#include <time.h>
|
||||
#include <cstdint> // for std::uint64_t
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
typedef std::uint64_t nanotime_t;
|
||||
|
||||
inline std::uint64_t milliseconds_since_epoch()
|
||||
{
|
||||
struct timespec ts;
|
||||
if (::clock_gettime(CLOCK_REALTIME, &ts))
|
||||
return 0;
|
||||
return std::uint64_t(ts.tv_sec) * std::uint64_t(1000)
|
||||
+ std::uint64_t(ts.tv_nsec) / std::uint64_t(1000000);
|
||||
}
|
||||
|
||||
inline nanotime_t nanoseconds_since_epoch()
|
||||
{
|
||||
struct timespec ts;
|
||||
if (::clock_gettime(CLOCK_REALTIME, &ts))
|
||||
return 0;
|
||||
return std::uint64_t(ts.tv_sec) * std::uint64_t(1000000000)
|
||||
+ std::uint64_t(ts.tv_nsec);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2019 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <openvpn/time/time.hpp>
|
||||
#include <openvpn/random/randapi.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
struct TimeSkew
|
||||
{
|
||||
// Skew factors (+/- %).
|
||||
// Pass these to skew() via factor parameter.
|
||||
enum {
|
||||
PCT_50 = 0,
|
||||
PCT_25 = 1,
|
||||
PCT_12_5 = 2,
|
||||
PCT_6_25 = 3,
|
||||
PCT_3_125 = 4,
|
||||
PCT_1_5625 = 5,
|
||||
};
|
||||
|
||||
// Skew a duration by some random flux.
|
||||
static Time::Duration skew(const Time::Duration& dur, const unsigned int factor, RandomAPI& prng)
|
||||
{
|
||||
const std::uint32_t bms = std::min(dur.to_binary_ms() >> factor, oulong(0x40000000)); // avoid 32-bit overflow in next step
|
||||
const int flux = int(prng.randrange32(bms)) - int(bms/2);
|
||||
return dur + flux;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// These are our fundamental Time and Time Duration classes.
|
||||
// We normally deal with time in units of 1/1024 of a second.
|
||||
// This allows us to use 32-bit values to represent most time
|
||||
// and time duration values, but still gives us reasonable
|
||||
// accuracy. Using units of 1/1024 of a second vs. straight
|
||||
// milliseconds gives us an advantage of not needing to do
|
||||
// very much integer multiplication and division which can
|
||||
// help us on platforms such as ARM that lack integer division
|
||||
// instructions. Note that the data type used to store the time
|
||||
// is an oulong, so it will automatically expand to 64 bits on
|
||||
// 64-bit machines (see olong.hpp). Using a 32-bit
|
||||
// data type for time durations is normally fine for clients,
|
||||
// but imposes a wraparound limit of ~ 48 days. Servers
|
||||
// should always use a 64-bit data type to avoid this
|
||||
// limitation.
|
||||
|
||||
#ifndef OPENVPN_TIME_TIME_H
|
||||
#define OPENVPN_TIME_TIME_H
|
||||
|
||||
#include <limits>
|
||||
#include <cstdint> // for std::uint32_t, uint64_t
|
||||
|
||||
#include <openvpn/common/platform.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/olong.hpp>
|
||||
#include <openvpn/common/to_string.hpp>
|
||||
|
||||
#ifdef OPENVPN_PLATFORM_WIN
|
||||
#include <time.h> // for ::time() on Windows
|
||||
#include <windows.h> // for GetTickCount
|
||||
#else
|
||||
#include <sys/time.h> // for ::time() and ::gettimeofday()
|
||||
#endif
|
||||
|
||||
namespace openvpn {
|
||||
OPENVPN_SIMPLE_EXCEPTION(get_time_error);
|
||||
|
||||
template <typename T>
|
||||
class TimeType
|
||||
{
|
||||
public:
|
||||
enum { prec=1024 };
|
||||
typedef ::time_t base_type;
|
||||
typedef T type;
|
||||
|
||||
class Duration
|
||||
{
|
||||
friend class TimeType;
|
||||
|
||||
public:
|
||||
static Duration seconds(const T v) { return Duration(v * prec); }
|
||||
static Duration binary_ms(const T v) { return Duration(v); }
|
||||
static Duration infinite() { return Duration(std::numeric_limits<T>::max()); }
|
||||
|
||||
static Duration milliseconds(const T v)
|
||||
{
|
||||
// NOTE: assumes that prec == 1024
|
||||
// Also note that this might wrap if v is larger than 1/3 of max size of T
|
||||
return Duration(v + (v * T(3) / T(128)));
|
||||
}
|
||||
|
||||
Duration() noexcept : duration_(T(0)) {}
|
||||
|
||||
bool defined() const { return duration_ != T(0); }
|
||||
bool operator!() const { return duration_ == T(0); }
|
||||
bool is_infinite() const { return duration_ == std::numeric_limits<T>::max(); }
|
||||
bool enabled() const { return defined() && !is_infinite(); }
|
||||
void set_infinite() { duration_ = std::numeric_limits<T>::max(); }
|
||||
void set_zero() { duration_ = T(0); }
|
||||
|
||||
Duration operator+(const Duration& d) const
|
||||
{
|
||||
if (is_infinite() || d.is_infinite())
|
||||
return infinite();
|
||||
else
|
||||
return Duration(duration_ + d.duration_);
|
||||
}
|
||||
|
||||
Duration operator+(const int delta) const
|
||||
{
|
||||
T duration = duration_;
|
||||
if (delta >= 0)
|
||||
duration += delta;
|
||||
else
|
||||
{
|
||||
const unsigned int ndelta = -delta;
|
||||
if (duration_ >= ndelta)
|
||||
duration -= ndelta;
|
||||
else
|
||||
duration = 0;
|
||||
}
|
||||
return Duration(duration);
|
||||
}
|
||||
|
||||
Duration operator*(const unsigned int mult) const
|
||||
{
|
||||
return Duration(duration_ * mult);
|
||||
}
|
||||
|
||||
Duration& operator+=(const Duration& d)
|
||||
{
|
||||
if (is_infinite() || d.is_infinite())
|
||||
set_infinite();
|
||||
else
|
||||
duration_ += d.duration_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void min(const Duration& d)
|
||||
{
|
||||
if (d.duration_ < duration_)
|
||||
duration_ = d.duration_;
|
||||
}
|
||||
|
||||
void max(const Duration& d)
|
||||
{
|
||||
if (d.duration_ > duration_)
|
||||
duration_ = d.duration_;
|
||||
}
|
||||
|
||||
Duration operator-(const Duration& d) const
|
||||
{
|
||||
if (d.duration_ >= duration_)
|
||||
return Duration(0);
|
||||
else if (is_infinite())
|
||||
return Duration::infinite();
|
||||
else
|
||||
return Duration(duration_ - d.duration_);
|
||||
}
|
||||
|
||||
Duration& operator-=(const Duration& d)
|
||||
{
|
||||
if (d.duration_ >= duration_)
|
||||
set_zero();
|
||||
else if (!is_infinite())
|
||||
duration_ -= d.duration_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T to_seconds() const { return duration_ / prec; }
|
||||
T to_binary_ms() const { return duration_; }
|
||||
|
||||
T to_milliseconds() const
|
||||
{
|
||||
// NOTE: assumes that prec == 1024
|
||||
// Also note that this might wrap if duration_ is larger than 1/3 of max size of T
|
||||
return duration_ - (duration_ * T(3) / T(128));
|
||||
}
|
||||
|
||||
double to_double() const
|
||||
{
|
||||
return double(duration_) / double(prec);
|
||||
}
|
||||
|
||||
T raw() const { return duration_; }
|
||||
|
||||
# define OPENVPN_DURATION_REL(OP) bool operator OP(const Duration& d) const { return duration_ OP d.duration_; }
|
||||
OPENVPN_DURATION_REL(==)
|
||||
OPENVPN_DURATION_REL(!=)
|
||||
OPENVPN_DURATION_REL(>)
|
||||
OPENVPN_DURATION_REL(<)
|
||||
OPENVPN_DURATION_REL(>=)
|
||||
OPENVPN_DURATION_REL(<=)
|
||||
# undef OPENVPN_DURATION_REL
|
||||
|
||||
private:
|
||||
explicit Duration(const T duration) : duration_(duration) {}
|
||||
|
||||
T duration_;
|
||||
};
|
||||
|
||||
TimeType() noexcept : time_(T(0)) {}
|
||||
|
||||
static TimeType zero() { return TimeType(T(0)); }
|
||||
static TimeType infinite() { return TimeType(std::numeric_limits<T>::max()); }
|
||||
|
||||
bool is_infinite() const { return time_ == std::numeric_limits<T>::max(); }
|
||||
|
||||
void reset() { time_ = 0; }
|
||||
void set_infinite() { time_ = std::numeric_limits<T>::max(); }
|
||||
|
||||
bool defined() const { return time_ != 0; }
|
||||
bool operator!() const { return time_ == 0; }
|
||||
|
||||
base_type seconds_since_epoch() const { return base_ + time_ / prec; }
|
||||
T fractional_binary_ms() const { return time_ % prec; }
|
||||
|
||||
static TimeType now() { return TimeType(now_()); }
|
||||
|
||||
void update() { time_ = now_(); }
|
||||
|
||||
TimeType operator+(const Duration& d) const
|
||||
{
|
||||
if (is_infinite() || d.is_infinite())
|
||||
return infinite();
|
||||
else
|
||||
return TimeType(time_ + d.duration_);
|
||||
}
|
||||
|
||||
TimeType& operator+=(const Duration& d)
|
||||
{
|
||||
if (is_infinite() || d.is_infinite())
|
||||
set_infinite();
|
||||
else
|
||||
time_ += d.duration_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Duration operator-(const TimeType& t) const
|
||||
{
|
||||
if (t.time_ >= time_)
|
||||
return Duration(0);
|
||||
else if (is_infinite())
|
||||
return Duration::infinite();
|
||||
else
|
||||
return Duration(time_ - t.time_);
|
||||
}
|
||||
|
||||
void min(const TimeType& t)
|
||||
{
|
||||
if (t.time_ < time_)
|
||||
time_ = t.time_;
|
||||
}
|
||||
|
||||
void max(const TimeType& t)
|
||||
{
|
||||
if (t.time_ > time_)
|
||||
time_ = t.time_;
|
||||
}
|
||||
|
||||
long delta_prec(const TimeType& t) const
|
||||
{
|
||||
return long(time_) - long(t.time_);
|
||||
}
|
||||
|
||||
long delta(const TimeType& t) const
|
||||
{
|
||||
return delta_prec(t) / long(prec);
|
||||
}
|
||||
|
||||
double delta_float(const TimeType& t) const
|
||||
{
|
||||
return (double(time_) - double(t.time_)) / double(prec);
|
||||
}
|
||||
|
||||
std::string delta_str(const TimeType& t) const
|
||||
{
|
||||
if (!defined())
|
||||
return "UNDEF-TIME";
|
||||
if (is_infinite())
|
||||
return "INF";
|
||||
const double df = delta_float(t);
|
||||
std::string ret;
|
||||
if (df >= 0.0)
|
||||
ret += '+';
|
||||
ret += openvpn::to_string(df);
|
||||
return ret;
|
||||
}
|
||||
|
||||
# define OPENVPN_TIME_REL(OP) bool operator OP(const TimeType& t) const { return time_ OP t.time_; }
|
||||
OPENVPN_TIME_REL(==)
|
||||
OPENVPN_TIME_REL(!=)
|
||||
OPENVPN_TIME_REL(>)
|
||||
OPENVPN_TIME_REL(<)
|
||||
OPENVPN_TIME_REL(>=)
|
||||
OPENVPN_TIME_REL(<=)
|
||||
# undef OPENVPN_TIME_REL
|
||||
|
||||
T raw() const { return time_; }
|
||||
|
||||
static void reset_base_conditional()
|
||||
{
|
||||
// on 32-bit systems, reset time base after 30 days
|
||||
if (sizeof(T) == 4)
|
||||
{
|
||||
const base_type newbase = ::time(0);
|
||||
if (newbase - base_ >= (60*60*24*30))
|
||||
reset_base();
|
||||
}
|
||||
}
|
||||
|
||||
static void reset_base()
|
||||
{
|
||||
base_ = ::time(0);
|
||||
#ifdef OPENVPN_PLATFORM_WIN
|
||||
#if (_WIN32_WINNT >= 0x0600)
|
||||
win_recalibrate((DWORD)::GetTickCount64());
|
||||
#else
|
||||
win_recalibrate(::GetTickCount());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// number of tenths of a microsecond since January 1, 1601.
|
||||
static uint64_t win_time()
|
||||
{
|
||||
// NOTE: assumes that prec == 1024
|
||||
return ((11644473600ULL * uint64_t(prec)) + (uint64_t(base_) * uint64_t(prec)) + uint64_t(now_())) * 78125ULL / 8ULL;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit TimeType(const T time) : time_(time) {}
|
||||
|
||||
#ifdef OPENVPN_PLATFORM_WIN
|
||||
|
||||
static void win_recalibrate(const DWORD gtc)
|
||||
{
|
||||
gtc_last = gtc;
|
||||
gtc_base = ::time(0) - gtc_last/1000;
|
||||
}
|
||||
|
||||
static T now_()
|
||||
{
|
||||
#if (_WIN32_WINNT >= 0x0600)
|
||||
const DWORD gtc = (DWORD)::GetTickCount64();
|
||||
#else
|
||||
const DWORD gtc = ::GetTickCount();
|
||||
#endif
|
||||
if (gtc < gtc_last)
|
||||
win_recalibrate(gtc);
|
||||
const time_t sec = gtc_base + gtc / 1000;
|
||||
const unsigned int msec = gtc % 1000;
|
||||
return T((sec - base_) * prec + msec * prec / 1000);
|
||||
}
|
||||
|
||||
static DWORD gtc_last;
|
||||
static time_t gtc_base;
|
||||
|
||||
#else
|
||||
|
||||
static T now_()
|
||||
{
|
||||
::timeval tv;
|
||||
if (::gettimeofday(&tv, nullptr) != 0)
|
||||
throw get_time_error();
|
||||
return T((tv.tv_sec - base_) * prec + tv.tv_usec * prec / 1000000);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static base_type base_;
|
||||
T time_;
|
||||
};
|
||||
|
||||
#ifdef OPENVPN_PLATFORM_WIN
|
||||
template <typename T> DWORD TimeType<T>::gtc_last;
|
||||
template <typename T> time_t TimeType<T>::gtc_base;
|
||||
#endif
|
||||
|
||||
template <typename T> typename TimeType<T>::base_type TimeType<T>::base_;
|
||||
|
||||
typedef TimeType<oulong> Time;
|
||||
|
||||
typedef Time* TimePtr;
|
||||
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_TIME_TIME_H
|
||||
@@ -0,0 +1,204 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Function to return the current date/time as a string.
|
||||
|
||||
#ifndef OPENVPN_TIME_TIMESTR_H
|
||||
#define OPENVPN_TIME_TIMESTR_H
|
||||
|
||||
#include <string>
|
||||
#include <cstring> // for std::strlen and std::memset
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <cstdint> // for std::uint64_t
|
||||
|
||||
#include <openvpn/common/platform.hpp>
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/string.hpp>
|
||||
|
||||
#if defined(OPENVPN_PLATFORM_WIN)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
#if defined(OPENVPN_PLATFORM_WIN)
|
||||
|
||||
inline std::string date_time(const time_t now)
|
||||
{
|
||||
struct tm *lt = localtime(&now);
|
||||
char *ret = asctime(lt);
|
||||
const size_t len = std::strlen(ret);
|
||||
if (len > 0 && ret[len-1] == '\n')
|
||||
ret[len-1] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline std::string date_time()
|
||||
{
|
||||
const time_t now = time(NULL);
|
||||
return date_time(now);
|
||||
}
|
||||
|
||||
inline std::string date_time_store_time_t(time_t& save)
|
||||
{
|
||||
save = time(NULL);
|
||||
return date_time(save);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline std::string date_time(const time_t t)
|
||||
{
|
||||
struct tm lt;
|
||||
char buf[64];
|
||||
|
||||
std::memset(<, 0, sizeof(lt));
|
||||
if (!localtime_r(&t, <))
|
||||
return "LOCALTIME_ERROR";
|
||||
if (!asctime_r(<, buf))
|
||||
return "ASCTIME_ERROR";
|
||||
const size_t len = std::strlen(buf);
|
||||
if (len > 0 && buf[len-1] == '\n')
|
||||
buf[len-1] = '\0';
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
inline std::string date_time_utc(const time_t t)
|
||||
{
|
||||
struct tm lt;
|
||||
char buf[64];
|
||||
|
||||
std::memset(<, 0, sizeof(lt));
|
||||
if (!gmtime_r(&t, <))
|
||||
return "GMTIME_ERROR";
|
||||
if (!asctime_r(<, buf))
|
||||
return "ASCTIME_ERROR";
|
||||
const size_t len = std::strlen(buf);
|
||||
if (len > 0 && buf[len-1] == '\n')
|
||||
buf[len-1] = '\0';
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
// msecs == false : Tue Feb 17 01:24:30 2015
|
||||
// msecs == true : Tue Feb 17 01:24:30.123 2015
|
||||
inline std::string date_time(const struct timeval *tv, const bool msecs)
|
||||
{
|
||||
const std::string dt = date_time(tv->tv_sec);
|
||||
if (msecs)
|
||||
{
|
||||
// find correct position in string to insert milliseconds
|
||||
const size_t pos = dt.find_last_of(':');
|
||||
if (pos != std::string::npos
|
||||
&& pos + 3 < dt.length()
|
||||
&& string::is_digit(dt[pos+1])
|
||||
&& string::is_digit(dt[pos+2])
|
||||
&& string::is_space(dt[pos+3]))
|
||||
{
|
||||
char ms[5];
|
||||
::snprintf(ms, sizeof(ms), ".%03u", static_cast<unsigned int>(tv->tv_usec / 1000));
|
||||
return dt.substr(0, pos+3) + ms + dt.substr(pos+3);
|
||||
}
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
inline std::string nanosec_time_to_string(const std::uint64_t ns_time)
|
||||
{
|
||||
const std::uint64_t sec = ns_time / std::uint64_t(1000000000);
|
||||
const std::uint64_t ns = ns_time % std::uint64_t(1000000000);
|
||||
|
||||
const std::string dt = date_time_utc(sec);
|
||||
|
||||
// find correct position in string to insert nanoseconds
|
||||
const size_t pos = dt.find_last_of(':');
|
||||
if (pos != std::string::npos
|
||||
&& pos + 3 < dt.length()
|
||||
&& string::is_digit(dt[pos+1])
|
||||
&& string::is_digit(dt[pos+2])
|
||||
&& string::is_space(dt[pos+3]))
|
||||
{
|
||||
char ms[11];
|
||||
::snprintf(ms, sizeof(ms), ".%09u", (unsigned int)ns);
|
||||
return dt.substr(0, pos+3) + ms + dt.substr(pos+3);
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
inline std::string date_time()
|
||||
{
|
||||
struct timeval tv;
|
||||
if (::gettimeofday(&tv, nullptr) < 0)
|
||||
{
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
}
|
||||
return date_time(&tv, true);
|
||||
}
|
||||
|
||||
inline std::string date_time_store_time_t(time_t& save)
|
||||
{
|
||||
struct timeval tv;
|
||||
if (::gettimeofday(&tv, nullptr) < 0)
|
||||
{
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
}
|
||||
save = tv.tv_sec;
|
||||
return date_time(&tv, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline std::string date_time_rfc822(const time_t t)
|
||||
{
|
||||
struct tm lt;
|
||||
char buf[64];
|
||||
|
||||
#if defined(OPENVPN_PLATFORM_WIN)
|
||||
if (gmtime_s(<, &t))
|
||||
return "";
|
||||
if (!strftime(buf, sizeof(buf),
|
||||
"%a, %d %b %Y %T GMT",
|
||||
<))
|
||||
return "";
|
||||
#else
|
||||
if (!gmtime_r(&t, <))
|
||||
return "";
|
||||
if (!strftime(buf, sizeof(buf),
|
||||
"%a, %d %b %Y %T %Z",
|
||||
<))
|
||||
return "";
|
||||
#endif
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
inline std::string date_time_rfc822()
|
||||
{
|
||||
return date_time_rfc822(::time(nullptr));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user