OpenVPN 3 Core Library
Loading...
Searching...
No Matches
exception.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// Basic exception handling. Allow exception classes for specific errors
13// to be easily defined, and allow exceptions to be thrown with a consise
14// syntax that allows stringstream concatenation using <<
15
16#ifndef OPENVPN_COMMON_EXCEPTION_H
17#define OPENVPN_COMMON_EXCEPTION_H
18
19#include <string>
20#include <sstream>
21#include <exception>
22#include <utility>
23
24#include <openvpn/common/stringize.hpp> // for OPENVPN_STRINGIZE
26
27#ifdef OPENVPN_DEBUG_EXCEPTION
28// well-known preprocessor hack to get __FILE__:__LINE__ rendered as a string
29#define OPENVPN_FILE_LINE "/" __FILE__ ":" OPENVPN_STRINGIZE(__LINE__)
30#else
31#define OPENVPN_FILE_LINE
32#endif
33
34namespace openvpn {
35
36// string exception class, where the exception is described by a std::string
37class Exception : public std::exception
38{
39 public:
40 explicit Exception(const std::string &err) noexcept
41 : err_(err)
42 {
43 }
44 explicit Exception(std::string &&err) noexcept
45 : err_(std::move(err))
46 {
47 }
48 const char *what() const noexcept override
49 {
50 return err_.c_str();
51 }
52 const std::string &err() const noexcept
53 {
54 return err_;
55 }
56 virtual ~Exception() noexcept = default;
57
58 void add_label(const std::string &label)
59 {
60 err_ = label + ": " + err_;
61 }
62
63 void remove_label(const std::string &label)
64 {
65 const std::string head = label + ": ";
66 if (string::starts_with(err_, head))
67 err_ = err_.substr(head.length());
68 }
69
70 private:
71 std::string err_;
72};
73
74// define a simple custom exception class with no extra info
75#define OPENVPN_SIMPLE_EXCEPTION(C) \
76 class C : public std::exception \
77 { \
78 public: \
79 const char *what() const noexcept override \
80 { \
81 return #C OPENVPN_FILE_LINE; \
82 } \
83 }
84
85// define a simple custom exception class with no extra info that inherits from a custom base
86#define OPENVPN_SIMPLE_EXCEPTION_INHERIT(B, C) \
87 class C : public B \
88 { \
89 public: \
90 C() : B(#C OPENVPN_FILE_LINE) \
91 { \
92 } \
93 const char *what() const noexcept override \
94 { \
95 return #C OPENVPN_FILE_LINE; \
96 } \
97 }
98
99// define a custom exception class that allows extra info
100#define OPENVPN_EXCEPTION(C) \
101 class C : public openvpn::Exception \
102 { \
103 public: \
104 C() : openvpn::Exception(#C OPENVPN_FILE_LINE) \
105 { \
106 } \
107 C(const std::string err) : openvpn::Exception(#C OPENVPN_FILE_LINE ": " + err) \
108 { \
109 } \
110 }
111
112// define a custom exception class that allows extra info with error code
113#define OPENVPN_EXCEPTION_WITH_CODE(C, DEFAULT_CODE, ...) \
114 enum C##_##code : unsigned int{__VA_ARGS__}; \
115 class C : public openvpn::Exception \
116 { \
117 public: \
118 C() : openvpn::Exception(#C OPENVPN_FILE_LINE) \
119 { \
120 add_label(#DEFAULT_CODE); \
121 } \
122 C(const std::string &err) : openvpn::Exception(#C OPENVPN_FILE_LINE ": " + err) \
123 { \
124 add_label(#DEFAULT_CODE); \
125 } \
126 option_error(C##_##code code, const std::string &err) \
127 : openvpn::Exception(#C OPENVPN_FILE_LINE ": " + err) \
128 { \
129 add_label(code2string(code)); \
130 } \
131 static std::string code2string(C##_##code code); \
132 }
133// define a custom exception class that allows extra info, but does not emit a tag
134#define OPENVPN_UNTAGGED_EXCEPTION(C) \
135 class C : public openvpn::Exception \
136 { \
137 public: \
138 C(const std::string err) : openvpn::Exception(err) \
139 { \
140 } \
141 }
142
143// define a custom exception class that allows extra info, and inherits from a custom base
144#define OPENVPN_EXCEPTION_INHERIT(B, C) \
145 class C : public B \
146 { \
147 public: \
148 C() : B(#C OPENVPN_FILE_LINE) \
149 { \
150 } \
151 C(const std::string err) : B(#C OPENVPN_FILE_LINE ": " + err) \
152 { \
153 } \
154 }
155
156// define a custom exception class that allows extra info, and inherits from a custom base,
157// but does not emit a tag
158#define OPENVPN_UNTAGGED_EXCEPTION_INHERIT(B, C) \
159 class C : public B \
160 { \
161 public: \
162 using B::B; \
163 }
164
165// throw an Exception with stringstream concatenation allowed
166#define OPENVPN_THROW_EXCEPTION(stuff) \
167 do \
168 { \
169 std::ostringstream _ovpn_exc; \
170 _ovpn_exc << stuff; \
171 throw openvpn::Exception(_ovpn_exc.str()); \
172 } while (0)
173
174// throw an OPENVPN_EXCEPTION class with stringstream concatenation allowed
175#define OPENVPN_THROW(exc, stuff) \
176 do \
177 { \
178 std::ostringstream _ovpn_exc; \
179 _ovpn_exc << stuff; \
180 throw exc(_ovpn_exc.str()); \
181 } while (0)
182
183#define OPENVPN_THROW_ARG1(exc, arg, stuff) \
184 do \
185 { \
186 std::ostringstream _ovpn_exc; \
187 _ovpn_exc << stuff; \
188 throw exc(arg, _ovpn_exc.str()); \
189 } while (0)
190
191// properly rethrow an exception that might be derived from Exception
192inline void throw_ref(const std::exception &e)
193{
194 const Exception *ex = dynamic_cast<const Exception *>(&e);
195 if (ex)
196 throw *ex;
197 else
198 throw e;
199}
200
201} // namespace openvpn
202
203#endif // OPENVPN_COMMON_EXCEPTION_H
Exception(const std::string &err) noexcept
Definition exception.hpp:40
const std::string & err() const noexcept
Definition exception.hpp:52
const char * what() const noexcept override
Definition exception.hpp:48
std::string err_
Definition exception.hpp:71
virtual ~Exception() noexcept=default
Exception(std::string &&err) noexcept
Definition exception.hpp:44
void remove_label(const std::string &label)
Definition exception.hpp:63
void add_label(const std::string &label)
Definition exception.hpp:58
bool starts_with(const STRING &str, const std::string &prefix)
Definition string.hpp:79
Support deferred server-side state creation when client connects.
Definition ovpncli.cpp:95
void throw_ref(const std::exception &e)