aboutsummaryrefslogtreecommitdiff
path: root/interval.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--interval.h239
1 files changed, 239 insertions, 0 deletions
diff --git a/interval.h b/interval.h
new file mode 100644
index 0000000..9845066
--- /dev/null
+++ b/interval.h
@@ -0,0 +1,239 @@
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single TCP/UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * The interval_ routines are designed to optimize the calling of a routine
+ * (normally tls_multi_process()) which can be called less frequently
+ * between triggers.
+ */
+
+#ifndef INTERVAL_H
+#define INTERVAL_H
+
+#include "otime.h"
+
+#define INTERVAL_DEBUG 0
+
+/*
+ * Designed to limit calls to expensive functions that need to be called
+ * regularly.
+ */
+
+struct interval
+{
+ interval_t refresh;
+ interval_t horizon;
+ time_t future_trigger;
+ time_t last_action;
+ time_t last_test_true;
+};
+
+void interval_init (struct interval *top, int horizon, int refresh);
+
+/*
+ * IF
+ * last_action less than horizon seconds ago
+ * OR last_test_true more than refresh seconds ago
+ * OR hit future_trigger
+ * THEN
+ * return true
+ * ELSE
+ * set wakeup to the number of seconds until a true return
+ * return false
+ */
+
+static inline bool
+interval_test (struct interval* top)
+{
+ bool trigger = false;
+ const time_t local_now = now;
+
+ if (top->future_trigger && local_now >= top->future_trigger)
+ {
+ trigger = true;
+ top->future_trigger = 0;
+ }
+
+ if (top->last_action + top->horizon > local_now ||
+ top->last_test_true + top->refresh <= local_now ||
+ trigger)
+ {
+ top->last_test_true = local_now;
+#if INTERVAL_DEBUG
+ dmsg (D_INTERVAL, "INTERVAL interval_test true");
+#endif
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+static inline void
+interval_schedule_wakeup (struct interval* top, interval_t *wakeup)
+{
+ const time_t local_now = now;
+ interval_earliest_wakeup (wakeup, top->last_test_true + top->refresh, local_now);
+ interval_earliest_wakeup (wakeup, top->future_trigger, local_now);
+#if INTERVAL_DEBUG
+ dmsg (D_INTERVAL, "INTERVAL interval_schedule wakeup=%d", (int)*wakeup);
+#endif
+}
+
+/*
+ * In wakeup seconds, interval_test will return true once.
+ */
+static inline void
+interval_future_trigger (struct interval* top, interval_t wakeup) {
+ if (wakeup)
+ {
+#if INTERVAL_DEBUG
+ dmsg (D_INTERVAL, "INTERVAL interval_future_trigger %d", (int)wakeup);
+#endif
+ top->future_trigger = now + wakeup;
+ }
+}
+
+/*
+ * Once an action is triggered, interval_test will remain true for
+ * horizon seconds.
+ */
+static inline void
+interval_action (struct interval* top)
+{
+#if INTERVAL_DEBUG
+ dmsg (D_INTERVAL, "INTERVAL action");
+#endif
+ top->last_action = now;
+}
+
+/*
+ * Measure when n seconds beyond an event have elapsed
+ */
+
+struct event_timeout
+{
+ bool defined;
+ interval_t n;
+ time_t last; /* time of last event */
+};
+
+static inline bool
+event_timeout_defined (const struct event_timeout* et)
+{
+ return et->defined;
+}
+
+static inline void
+event_timeout_clear (struct event_timeout* et)
+{
+ et->defined = false;
+ et->n = 0;
+ et->last = 0;
+}
+
+static inline struct event_timeout
+event_timeout_clear_ret ()
+{
+ struct event_timeout ret;
+ event_timeout_clear (&ret);
+ return ret;
+}
+
+static inline void
+event_timeout_init (struct event_timeout* et, interval_t n, const time_t local_now)
+{
+ et->defined = true;
+ et->n = (n >= 0) ? n : 0;
+ et->last = local_now;
+}
+
+static inline void
+event_timeout_reset (struct event_timeout* et)
+{
+ if (et->defined)
+ et->last = now;
+}
+
+/*
+ * This is the principal function for testing and triggering recurring
+ * timers and will return true on a timer signal event.
+ * If et_const_retry == ETT_DEFAULT and a signal occurs,
+ * the function will return true and *et will be armed for the
+ * next event. If et_const_retry >= 0 and a signal occurs,
+ * *et will not be touched, but *tv will be set to
+ * minimum (*tv, et_const_retry) for a future re-test,
+ * and the function will return true.
+ */
+
+#define ETT_DEFAULT (-1)
+
+bool event_timeout_trigger (struct event_timeout *et,
+ struct timeval *tv,
+ const int et_const_retry);
+
+/*
+ * Measure time intervals in microseconds
+ */
+
+#define USEC_TIMER_MAX 60 /* maximum interval size in seconds */
+
+#define USEC_TIMER_MAX_USEC (USEC_TIMER_MAX * 1000000)
+
+struct usec_timer {
+ struct timeval start;
+ struct timeval end;
+};
+
+#ifdef HAVE_GETTIMEOFDAY
+
+static inline void
+usec_timer_start (struct usec_timer *obj)
+{
+ CLEAR (*obj);
+ gettimeofday (&obj->start, NULL);
+}
+
+static inline void
+usec_timer_end (struct usec_timer *obj)
+{
+ gettimeofday (&obj->end, NULL);
+}
+
+#endif /* HAVE_GETTIMEOFDAY */
+
+static inline bool
+usec_timer_interval_defined (struct usec_timer *obj)
+{
+ return obj->start.tv_sec && obj->end.tv_sec;
+}
+
+static inline int
+usec_timer_interval (struct usec_timer *obj)
+{
+ return tv_subtract (&obj->end, &obj->start, USEC_TIMER_MAX);
+}
+
+#endif /* INTERVAL_H */