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 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 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
82 {
83 }
84
85 void stop()
86 {
87 std::lock_guard<std::recursive_mutex> lock(mutex);
88 stop_called = true;
89 while (scopes.size())
90 {
91 Scope *scope = scopes.back();
92 scopes.pop_back();
93 if (scope)
94 {
95 scope->index = -1;
96 scope->method();
97 }
98 }
99 }
100
101 static bool is_triggered(const Stop *stop)
102 {
103 return stop && stop->stop_called;
104 }
105
106 Stop(const Stop &) = delete;
107 Stop &operator=(const Stop &) = delete;
108
109 private:
110 void prune()
111 {
112 while (scopes.size() && !scopes.back())
113 scopes.pop_back();
114 }
115
116 std::recursive_mutex mutex;
117 std::vector<Scope *> scopes;
118 volatile bool stop_called = false;
119};
120
121} // namespace openvpn
122
123#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:118
Stop & operator=(const Stop &)=delete
std::recursive_mutex mutex
Definition stop.hpp:116
static bool is_triggered(const Stop *stop)
Definition stop.hpp:101
std::vector< Scope * > scopes
Definition stop.hpp:117
void stop()
Definition stop.hpp:85
void prune()
Definition stop.hpp:110
Stop(const Stop &)=delete
#define OPENVPN_EXCEPTION_INHERIT(B, C)