OpenVPN 3 Core Library
Loading...
Searching...
No Matches
stop.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#ifndef OPENVPN_COMMON_STOP_H
13#define OPENVPN_COMMON_STOP_H
14
15#include <vector>
16#include <functional>
17#include <utility>
18#include <mutex>
19
21
22OPENVPN_EXCEPTION_INHERIT(std::range_error, openvpn_stop_limit);
23
24namespace openvpn {
25
26class Stop
27{
28 public:
29 class Scope
30 {
31 friend Stop;
32
33 public:
34 Scope(Stop *stop_arg, std::function<void()> &&method_arg)
35 : stop(stop_arg),
36 method(std::move(method_arg)),
37 index(-1)
38 {
39 constexpr int stop_index_limit = 1000;
40 if (stop)
41 {
42 const std::lock_guard<std::recursive_mutex> lock(stop->mutex);
43 if (stop->stop_called)
44 {
45 // stop already called, call method immediately
46 method();
47 }
48 else
49 {
50 if (index > stop_index_limit)
51 throw openvpn_stop_limit("Stop count limit exceeded");
52
53 index = static_cast<decltype(index)>(stop->scopes.size());
54 stop->scopes.push_back(this);
55 }
56 }
57 }
58
60 {
61 if (stop)
62 {
63 const std::lock_guard<std::recursive_mutex> lock(stop->mutex);
64 if (index >= 0 && index < static_cast<int>(stop->scopes.size()) && stop->scopes[index] == this)
65 {
66 stop->scopes[index] = nullptr;
67 stop->prune();
68 }
69 }
70 }
71
72 private:
73 Scope(const Scope &) = delete;
74 Scope &operator=(const Scope &) = delete;
75
76 Stop *const stop;
77 const std::function<void()> method;
78 int index;
79 };
80
81 Stop() = default;
82
83 void stop()
84 {
85 const std::lock_guard<std::recursive_mutex> lock(mutex);
86 stop_called = true;
87 while (!scopes.empty())
88 {
89 Scope *scope = scopes.back();
90 scopes.pop_back();
91 if (scope)
92 {
93 scope->index = -1;
94 scope->method();
95 }
96 }
97 }
98
99 static bool is_triggered(const Stop *stop)
100 {
101 return stop && stop->stop_called;
102 }
103
104 Stop(const Stop &) = delete;
105 Stop &operator=(const Stop &) = delete;
106
107 private:
108 void prune()
109 {
110 while (!scopes.empty() && !scopes.back())
111 scopes.pop_back();
112 }
113
114 std::recursive_mutex mutex;
115 std::vector<Scope *> scopes;
116 volatile bool stop_called = false;
117};
118
119} // namespace openvpn
120
121#endif
Scope & operator=(const Scope &)=delete
Scope(Stop *stop_arg, std::function< void()> &&method_arg)
Definition stop.hpp:34
Stop *const stop
Definition stop.hpp:76
const std::function< void()> method
Definition stop.hpp:77
Scope(const Scope &)=delete
volatile bool stop_called
Definition stop.hpp:116
Stop & operator=(const Stop &)=delete
std::recursive_mutex mutex
Definition stop.hpp:114
static bool is_triggered(const Stop *stop)
Definition stop.hpp:99
std::vector< Scope * > scopes
Definition stop.hpp:115
void stop()
Definition stop.hpp:83
Stop()=default
void prune()
Definition stop.hpp:108
Stop(const Stop &)=delete
#define OPENVPN_EXCEPTION_INHERIT(B, C)