randolf.ca  1.00
Randolf Richardson's C++ classes
Loading...
Searching...
No Matches
rex
1#pragma once
2
3#include <netdb.h> // gai_strerror()
4#include <iostream> // std::string
5#include <exception>
6
7#include <string.h> // strerror()
8
9#include <openssl/err.h> // OpenSSL's ERR_peek_err() function
10#include <openssl/ssl.h> // OpenSSL error codes
11
12namespace randolf {
13 namespace rex {
14
15 /*======================================================================*//**
16 @brief
17 Randolf's exceptions class, that takes errors from POSIX and OpenSSL
18 functions and throws logically-named C++ exceptions.
19
20 Every error that can be returned by a POSIX function (e.g., socket functions)
21 is available as a subclass of the @ref xALL exception, which is a subclass of
22 @ref rex, and which in turn is ultimately a subclass of @c std::exception.
23
24 @note
25 Exception names that begin with \c xALL_ are subclassed by other exceptions
26 so that developers can capture specific groups of exceptions for easier error
27 handling.
28
29 A minimal amount of hierarchy is included in this design so that developers
30 can more conveniently capture groups of exceptions with a single @c catch
31 statement. For example, since all errors beginning with @c xEAI_ are also a
32 subclass of @ref rex::xALL_EAI a single @c catch statement will capture all
33 of them (the what() method can still be presented to the user so they may
34 more easily differentiate the specific error).
35
36 Any errors that are added in the future (or were overlooked) belong in a
37 special exception called @ref rex::xUNKNOWN (note that there's no letter "E"
38 prefixing this name so as to avoid any possible future conflict with a
39 hypothetical @n EUNKNOWN error ever being added to the POSIX standard.
40
41 @par Compilation dependencies
42 In your source code, the following include line is needed:
43 @code {.cpp}
44 #include <randolf/rex>
45 @endcode
46
47 When compiling, the crypto library is needed (for TLS/OpenSSL error handling,
48 whether or not you actually use it; perhaps in the distant future I can look
49 into the possibility of improving this source code header so the TLS/OpenSSL
50 handling portions are conditionally included when compiling with the crypto
51 library).
52 @code {.sh}
53 g++ -std=c++20 -x c++ rex -lcrypto
54 @endcode
55
56 @par Background
57 This was originally built for the @ref rsocket class, but I've moved it out
58 into a separate C++ header file because it's useful for generating exceptions
59 from other classes and projects too. So, now it's a general-purpose class
60 that can be used independently (without any reliance on my other projects).
61
62 @par Conventions
63 All @c xTLS_ exceptions represent OpenSSL library errors prefixed with @c
64 SSL_ERROR_, and all references to SSL are replaced by TLS so as to be in
65 accordance with the fact that SSL was deprecated many years ago (TLS replaces
66 SSL due to security weaknesses that were discovered with SSL) prior to the
67 creation of this @ref rex class.
68
69 Every TLS-related/SSL-related exception is documented to indicate which @c
70 SSL_ERROR_ it represents, in an effort to make it easier (and clearer) which
71 @c SSL_ERROR_ is being represented. (For the text representation of
72 OpenSSL's error codes, we still present them just as the library does, using
73 the @c SSL_ERROR_ prefix, so that users can more easily make sense of them
74 and find helpful information if research them on the internet or ask others
75 for help who are expecting these well-known/more-recognizable error names.)
76 *///=========================================================================
77 class rex : public std::exception {
78
79 // --------------------------------------------------------------------------
80 // Internal variables.
81 // --------------------------------------------------------------------------
82 std::string __msg;
83 long __errno = 0;
84 int __flags = REX_FLAGS::REX_DEFAULT;
85
86 public:
87 /*======================================================================*//**
88 @brief
89 Optional flags used with the static @ref mk_exception() method to specify.
90 @see randolf::rex::rex::mk_exception(const std::string, long, const int)
91 *///=========================================================================
92 enum REX_FLAGS: int {
93
94 /*----------------------------------------------------------------------*//**
95 The REX_DEFAULT flag isn't necessary, but it's included here for completeness
96 as it accomodates programming styles that prefer to emphasize when defaults
97 are being relied upon.
98 *///-------------------------------------------------------------------------
99 REX_DEFAULT = 0,
100
101 /*----------------------------------------------------------------------*//**
102 This will override whatever error number was provided to the constructor by
103 querying @c errno or [for TLS errors] querying OpenSSL's @c ERR_peek_err
104 function for the error code.
105 *///-------------------------------------------------------------------------
106 REX_FIND_ERRNO = 1,
107
108 /*----------------------------------------------------------------------*//**
109 Indicate that the error code is from the OpenSSL library (some of which are
110 in conflict with general/POSIX error codes, which is why this flag is
111 necessary), and is not a general/POSIX error code.
112 *///-------------------------------------------------------------------------
113 REX_TLS = 2,
114
115 /*----------------------------------------------------------------------*//**
116 Throw xEAGAIN instead of xEWOULDBLOCK, if either the @c EAGAIN error code or
117 the @c EWOULDBLOCK error code is encountered.
118
119 @note
120 Sometimes this is needed by @ref mk_exception so that it constructs from the
121 correct exception class because some Operating Systems use the same error
122 code number for both of the respective errors as noted.
123
124 This is a workaround used primarily by the static @ref mk_exception method so
125 that the intended exception is thrown regardless of whether the error code
126 numbers are properly differentiated.
127 *///-------------------------------------------------------------------------
128 REX_ALT_EAGAIN = 4096,
129
130 /*----------------------------------------------------------------------*//**
131 Throw xENOTSUP instead of xEOPNOTSUPP, if either the @c ENOTSUP error code or
132 the @c EOPNOTSUPP error code is encountered.
133
134 @note
135 Sometimes this is needed by @ref mk_exception so that it constructs from the
136 correct exception class because some Operating Systems use the same error
137 code number for both of the respective errors as noted.
138
139 This is a workaround used primarily by the static @ref mk_exception method so
140 that the intended exception is thrown regardless of whether the error code
141 numbers are properly differentiated.
142 *///-------------------------------------------------------------------------
143 REX_ALT_ENOTSUP = 8192,
144
145 }; // -x- enum REX_FLAGS -x-
146
147 /*======================================================================*//**
148 @brief
149 Default constructor.
150 @note
151 This is to keep clang++ from generating hundreds of useless errors.
152 @see mk_exception(std::string, long, int)
153 *///=========================================================================
154 rex (); // -x- constructor rex -x-
155
156 /*======================================================================*//**
157 @brief
158 Construct exception with an ASCIIZ string.
159 @note
160 When throwing an exception, it's not necessary to know the error number,
161 which means that new types of errors can be introduced (although we really
162 want to avoid deviating from the standard Linux API as much as possible).
163 @see mk_exception(std::string, long, int)
164 *///=========================================================================
165 explicit rex(/// Error code as a pointer to an ASCIIZ string
166 const char* m,
167 /// Result of the errno() function goes here (if known)
168 long n = 0,
169 /// Flags
170 const int flags = REX_FLAGS::REX_DEFAULT) : __msg(m), __errno(n) {
171
172 // --------------------------------------------------------------------------
173 // Process flags.
174 // --------------------------------------------------------------------------
175 if (flags && REX_FLAGS::REX_FIND_ERRNO) {
176 n = flags && REX_FLAGS::REX_TLS ? ERR_peek_error() : errno;
177 } // -x- if FIND::ERRNO -x-
178
179 // --------------------------------------------------------------------------
180 // Process flags.
181 // --------------------------------------------------------------------------
182 if (flags && REX_FLAGS::REX_FIND_ERRNO) {
183 n = flags && REX_FLAGS::REX_TLS ? ERR_peek_error() : errno;
184 } // -x- if FIND::ERRNO -x-
185
186 // --------------------------------------------------------------------------
187 // Build error string.
188 // --------------------------------------------------------------------------
189 if (flags && REX_FLAGS::REX_TLS) {
190 char buf[512];
191 ERR_error_string_n(n, buf, sizeof(buf)); // Get error string from OpenSSL in a thread-safe way
192 __msg.append(buf);
193 } else {
194 if (__msg.find(" ") == std::string::npos) __msg.append(__msg.empty() ? "" : ": ") // Empty or single-word, so more detail is needed
195 .append(gai_strerror(n) != "Unknown error" ? gai_strerror(n) : strerror(n)) // Use EAI error string instead if it's available
196 .append(" (")
197 .append(std::to_string(n)) // Include error number in parenthesis (via all three append() methods here)
198 .append(")");
199 } // -x- if flags -x-
200
201 }; // -x- constructor rex -x-
202
203 /*======================================================================*//**
204 @brief
205 Construct exception with an std::string object.
206 @note
207 When throwing an exception, it's not necessary to know the error number,
208 which means that new types of errors can be introduced (although we really
209 want to avoid deviating from the standard Linux API as much as possible).
210 @see mk_exception(std::string, long, int)
211 *///=========================================================================
212 explicit rex(/// Error code as an std::string
213 const std::string& m,
214 /// Result of the errno() function goes here (if known)
215 long n = 0,
216 /// Flags
217 const int flags = REX_FLAGS::REX_DEFAULT) : __msg(m), __errno(n), __flags(flags) {
218
219 // --------------------------------------------------------------------------
220 // Process flags.
221 // --------------------------------------------------------------------------
222 if (flags && REX_FLAGS::REX_FIND_ERRNO) {
223 n = flags && REX_FLAGS::REX_TLS ? ERR_peek_error() : errno;
224 } // -x- if FIND::ERRNO -x-
225
226 // --------------------------------------------------------------------------
227 // Build error string.
228 // --------------------------------------------------------------------------
229 if (flags && REX_FLAGS::REX_TLS) {
230 char buf[512];
231 ERR_error_string_n(n, buf, sizeof(buf)); // Get error string from OpenSSL in a thread-safe way
232 __msg.append(__msg.empty() ? "" : ": ").append(buf);
233 } else {
234 if (__msg.find(" ") == std::string::npos) __msg.append(__msg.empty() ? "" : ": ") // Empty or single-word, so more detail is needed
235 .append(gai_strerror(n) != "Unknown error" ? gai_strerror(n) : strerror(n)) // Use EAI error string instead if it's available
236 .append(" (")
237 .append(std::to_string(n)) // Include error number in parenthesis (via all three append() methods here)
238 .append(")");
239 } // -x- if flags -x-
240
241 }; // -x- constructor rex -x-
242
243 /*======================================================================*//**
244 @brief
245 Find out what the @c errno (or OpenSSL's @c ERR_get_error() number) was that
246 caused this exception to be thrown.
247 @return Original errno() value
248 *///=========================================================================
249 const long err_no() const noexcept {
250 return __errno;
251 }; // -x- int err_no -x-
252
253 /*======================================================================*//**
254 @brief
255 Arbitrarily throw an exception based on the error number.
256
257 This is useful for developers who may need (or want) to throw a specific
258 exception to ease error handling for circumstances that warrant throwing a
259 particular exception that otherwise normally wouldn't be thrown (0 will also
260 cause @ref xUNKNOWN to be thrown).
261
262 If the error message text isn't known, then passing in an empty std::string
263 will trigger the relevant error message to be generated automatically).
264
265 @note
266 The exception xTLS_ZERO_RETURN represents OpenSSL's error code 6, which is an
267 actual error, unlike 0, which indicates that an error didn't occur.
268 @throws rex has many subclasses, all of which may be caught individually, or
269 under one of the rex exceptions groups, such as @ref xALL
270 @see REX_FLAGS
271 *///=========================================================================
272 static void mk_exception(/// Custom error message (replaces default message if defined)
273 const std::string msg = "",
274 /// Error number (N/A if @ref REX_FIND_ERRNO is specified)@n Ultimately, an error code of 0 has no effect and will result in no exception being thrown
275 long rex_errno = 0,
276 /// Flags that influence how exceptions are thrown
277 const int flags = rex::REX_FLAGS::REX_DEFAULT);
278 // Forward-declaration.
279
280 /*======================================================================*//**
281 @brief
282 Find out what the reason (usually the error code, e.g., EAGAIN) was for this
283 exception to be thrown.
284 @return Error code text as a pointer to an ASCIIZ string
285 *///=========================================================================
286 const char* what() const noexcept {
287 return __msg.c_str();
288 }; // -x- char* what -x-
289
290 }; // -x- class rex -x-
291
292 // namespace x {
293
294 /// Exception group that can be used to catch exceptions thrown for errors returned from POSIX fuctions (e.g., socket functions).
295 class xALL : public virtual rex { using rex::rex; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); }; // Exception group
296 /// Exception for error: @c E2BIG
297 class xE2BIG : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
298 /// Exception for error: @c EACCES
299 class xEACCES : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
300 /// Exception for error: @c EADDRINUSE
301 class xEADDRINUSE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
302 /// Exception for error: @c EADDRNOTAVAIL
303 class xEADDRNOTAVAIL : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
304 /// Exception for error: @c EAFNOSUPPORT
305 class xEAFNOSUPPORT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
306 /// Exception for error: @c EAGAIN / @c EWOULDBLOCK
307 class xEAGAIN : public virtual xALL { using xALL::xALL; };
308 /// Exception group that can be used to catch exceptions thrown for @c EAI_ errors returned from POSIX fuctions (e.g., socket functions).
309 class xALL_EAI : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); }; // Exception group
310 /// Exception for error: @c EAI_ADDRFAMILY
311 class xEAI_ADDRFAMILY : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
312 /// Exception for error: @c EAI_AGAIN
313 class xEAI_AGAIN : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
314 /// Exception for error: @c EAI_BADFLAGS
315 class xEAI_BADFLAGS : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
316 /// Exception for error: @c EAI_FAIL
317 class xEAI_FAIL : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
318 /// Exception for error: @c EAI_FAMILY
319 class xEAI_FAMILY : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
320 /// Exception for error: @c EAI_INPROGRESS
321 class xEAI_INPROGRESS : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
322 /// Exception for error: @c EAI_SERVICE
323 class xEAI_SERVICE : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
324 /// Exception for error: @c EAI_SOCKTYPE
325 class xEAI_SOCKTYPE : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
326 /// Exception for error: @c EAI_SYSTEM
327 class xEAI_SYSTEM : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
328 /// Exception for error: @c EAI_MEMORY
329 class xEAI_MEMORY : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
330 /// Exception for error: @c EAI_NODATA
331 class xEAI_NODATA : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
332 /// Exception for error: @c EAI_NONAME
333 class xEAI_NONAME : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
334 /// Exception for error: @c EAI_OVERFLOW
335 class xEAI_OVERFLOW : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
336 /// Exception for error: @c EAI_CANCELED
337 class xEAI_CANCELED : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
338 /// Exception for error: @c EAI_NOTCANCELED
339 class xEAI_NOTCANCELED : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
340 /// Exception for error: @c EAI_ALLDONE
341 class xEAI_ALLDONE : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
342 /// Exception for error: @c EAI_INTR
343 class xEAI_INTR : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
344 /// Exception for error: @c EAI_IDN_ENCODE
345 class xEAI_IDN_ENCODE : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
346 /// Exception for error: @c EALREADY
347 class xEALREADY : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
348 /// Exception for error: @c EBADE
349 class xEBADE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
350 /// Exception for error: @c EBADF
351 class xEBADF : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
352 /// Exception for error: @c EBADFD
353 class xEBADFD : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
354 /// Exception for error: @c EBADMSG
355 class xEBADMSG : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
356 /// Exception for error: @c EBADR
357 class xEBADR : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
358 /// Exception for error: @c EBADRQC
359 class xEBADRQC : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
360 /// Exception for error: @c EBADSLT
361 class xEBADSLT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
362 /// Exception for error: @c EBUSY
363 class xEBUSY : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
364 /// Exception for error: @c ECOMM
365 class xECOMM : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
366 /// Exception for error: @c ECONNABORTED
367 class xECONNABORTED : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
368 /// Exception for error: @c ECONNREFUSED
369 class xECONNREFUSED : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
370 /// Exception for error: @c ECONNRESET
371 class xECONNRESET : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
372 /// Exception for error: @c EDEADLK
373 class xEDEADLK : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
374 /// Exception for error: @c EDESTADDRREQ
375 class xEDESTADDRREQ : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
376 /// Exception for error: @c EFAULT
377 class xEFAULT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
378 /// Exception for error: @c EHOSTDOWN
379 class xEHOSTDOWN : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
380 /// Exception for error: @c EHOSTUNREACH
381 class xEHOSTUNREACH : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
382 /// Exception for error: @c EILSEQ
383 class xEILSEQ : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
384 /// Exception for error: @c EINPROGRESS
385 class xEINPROGRESS : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
386 /// Exception for error: @c EINTR
387 class xEINTR : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
388 /// Exception for error: @c EINVAL
389 class xEINVAL : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
390 /// Exception for error: @c EIO
391 class xEIO : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
392 /// Exception for error: @c EISCONN
393 class xEISCONN : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
394 /// Exception for error: @c ELOOP
395 class xELOOP : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
396 /// Exception for error: @c EMFILE
397 class xEMFILE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
398 /// Exception for error: @c EMSGSIZE
399 class xEMSGSIZE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
400 /// Exception for error: @c EMULTIHOP
401 class xEMULTIHOP : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
402 /// Exception for error: @c ENAMETOOLONG
403 class xENAMETOOLONG : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
404 /// Exception for error: @c ENETDOWN
405 class xENETDOWN : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
406 /// Exception for error: @c ENETRESET
407 class xENETRESET : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
408 /// Exception for error: @c ENETUNREACH
409 class xENETUNREACH : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
410 /// Exception for error: @c ENFILE
411 class xENFILE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
412 /// Exception for error: @c ENOBUFS
413 class xENOBUFS : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
414 /// Exception for error: @c ENODATA
415 class xENODATA : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
416 /// Exception for error: @c ENODEV
417 class xENODEV : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
418 /// Exception for error: @c ENOENT
419 class xENOENT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
420 /// Exception for error: @c ENOLINK
421 class xENOLINK : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
422 /// Exception for error: @c ENOMEM
423 class xENOMEM : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
424 /// Exception for error: @c ENONET
425 class xENONET : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
426 /// Exception for error: @c ENOPROTOOPT
427 class xENOPROTOOPT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
428 /// Exception for error: @c ENOSR
429 class xENOSR : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
430 /// Exception for error: @c ENOSPC
431 class xENOSPC : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
432 /// Exception for error: @c ENOSTR
433 class xENOSTR : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
434 /// Exception for error: @c ENOTCONN
435 class xENOTCONN : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
436 /// Exception for error: @c ENOTDIR
437 class xENOTDIR : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
438 /// Exception for error: @c ENOTSOCK
439 class xENOTSOCK : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
440 /// Exception for error: @c ENOTSUP / @c EOPTNOTSUP
441 class xENOTSUP : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); }; // a.k.a., EOPTNOTSUP
442 /// Exception for error: @c ENOTTY
443 class xENOTTY : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
444 /// Exception for error: @c ENOTUNIQ
445 class xENOTUNIQ : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
446 /// Exception for error: @c ENXIO
447 class xENXIO : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
448 /// Exception for error: @c EOPNOTSUPP
449 class xEOPNOTSUPP : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
450 /// Exception for error: @c EOVERFLOW
451 class xEOVERFLOW : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
452 /// Exception for error: @c EPERM
453 class xEPERM : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
454 /// Exception for error: @c EPFNOSUPPORT
455 class xEPFNOSUPPORT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
456 /// Exception for error: @c EPIPE
457 class xEPIPE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
458 /// Exception for error: @c EPROTONOSUPPORT
459 class xEPROTO : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
460 /// Exception for error: @c EPROTO
461 class xEPROTONOSUPPORT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
462 /// Exception for error: @c EPROTOTYPE
463 class xEPROTOTYPE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
464 /// Exception for error: @c ERANGE
465 class xERANGE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
466 /// Exception for error: @c EREMOTEIO
467 class xEREMOTEIO : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
468// /// Exception for error: @c ERESTARTSYS
469// class xERESTARTSYS : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
470 /// Exception for error: @c EROFS
471 class xEROFS : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
472 /// Exception for error: @c ESOCKNOSUPPORT
473 class xESOCKTNOSUPPORT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
474 /// Exception for error: @c ESRCH
475 class xESRCH : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
476 /// Exception group that can be used to catch exceptions thrown for @c ETIME and @c ETIMEDOUT errors returned from POSIX fuctions (e.g., socket functions).
477 class xALL_ETIME : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); }; // Exception group
478 /// Exception for error: @c ETIME
479 class xETIME : public virtual xALL_ETIME { using xALL_ETIME::xALL_ETIME; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
480 /// Exception for error: @c ETIMEDOUT
481 class xETIMEDOUT : public virtual xALL_ETIME { using xALL_ETIME::xALL_ETIME; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
482 /// Exception group that can be used to catch exceptions thrown for @c TLS errors returned from OpenSSL socket functions.
483 class xALL_TLS : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); }; // Exception group
484 /// Exception for error @c SSL_ERROR_SYSCALL
485 class xTLS_SYSCALL : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
486 /// Exception for error @c SSL_ERROR_SSL
487 class xTLS_TLS : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
488 /// Exception for error @c SSL_ERROR_WANT_ACCEPT
489 class xTLS_WANT_ACCEPT : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
490 /// Exception for error @c SSL_ERROR_WANT_ASYNC
491 class xTLS_WANT_ASYNC : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
492 /// Exception for error @c SSL_ERROR_WANT_ASYNC_JOB
493 class xTLS_WANT_ASYNC_JOB : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
494 /// Exception for error @c SSL_ERROR_WANT_CLIENT_HELLO_CB
495 class xTLS_WANT_CLIENT_HELLO_CB : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
496 /// Exception for error @c SSL_ERROR_WANT_CONNECT
497 class xTLS_WANT_CONNECT : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
498 /// Exception for error @c SSL_ERROR_WANT_READ
499 class xTLS_WANT_READ : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
500 /// Exception for error @c SSL_ERROR_WANT_WRITE
501 class xTLS_WANT_WRITE : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
502 /// Exception for error @c SSL_ERROR_WANT_X509_LOOKUP
503 class xTLS_WANT_X509_LOOKUP : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
504 /// Exception for error @c SSL_ERROR_ZERO_RETURN
505 class xTLS_ZERO_RETURN : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
506 /// Exception for error: @c EWOULDBLOCK / @c EAGAIN
507 class xEWOULDBLOCK : public virtual xALL { using xALL::xALL; };
508 /// Exception for all other errors that are not known
509 class xUNKNOWN : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
510 // Total: 102 socket exceptions (including xALL, xALL_EAI, xALL_ETIME, and xALL_TLS groups)
511
512 /*======================================================================*//**
513 @copydoc mk_exception(std::string, long, int)
514 *///=========================================================================
515 static void mk_exception(/// Custom error message (replaces default message if defined)
516 const std::string msg = "",
517 /// Error number (N/A if @ref REX_FIND_ERRNO is specified)@n Ultimately, an error code of 0 has no effect and will result in no exception being thrown
518 long rex_errno = 0,
519 /// Flags that influence how exceptions are thrown
520 const int flags = rex::REX_FLAGS::REX_DEFAULT) {
521
522 // --------------------------------------------------------------------------
523 // Process flags.
524 // --------------------------------------------------------------------------
525 if (flags && rex::REX_FLAGS::REX_FIND_ERRNO) {
526 rex_errno = flags && rex::REX_FLAGS::REX_TLS ? ERR_peek_error() : errno;
527 } // -x- if FIND::ERRNO -x-
528
529 // --------------------------------------------------------------------------
530 // If there is no error, then just return without throwing an exception. The
531 // reason we handle this here now is to save CPU cycles (handling it in a
532 // default case later requires first running many other comparisons that
533 // are less of a conern when an exception is to be thrown because greater
534 // efficiency is normally needed when errors aren't occurring).
535 // --------------------------------------------------------------------------
536 if (rex_errno == 0) return; // Do nothing for error code 0
537
538 // --------------------------------------------------------------------------
539 // Effectively insert text in front of msg if it's not empty so it remains
540 // properly separated from the error type text. (We're working with a copy
541 // of the string because we want to not change the std::string that was
542 // specified by the caller.)
543 // --------------------------------------------------------------------------
544 std::string m = msg.empty() ? msg : ": " + msg;
545
546 // TODO: If SSL_get_error() returns SSL_ERROR_SSL, use ERR_get_error() and related functions instead.
547 // --------------------------------------------------------------------------
548 // TLS exeptions.
549 // --------------------------------------------------------------------------
550 if (flags && rex::REX_FLAGS::REX_TLS) {
551 switch(rex_errno) {
552 case SSL_ERROR_SYSCALL: throw randolf::rex::xTLS_SYSCALL("SSL_ERROR_SYSCALL" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
553 case SSL_ERROR_SSL: throw randolf::rex::xTLS_TLS("SSL_ERROR_SSL" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
554 case SSL_ERROR_WANT_ACCEPT: throw randolf::rex::xTLS_WANT_ACCEPT("SSL_ERROR_WANT_ACCEPT" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
555 case SSL_ERROR_WANT_ASYNC: throw randolf::rex::xTLS_WANT_ASYNC("SSL_ERROR_WANT_ASYNC" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
556 case SSL_ERROR_WANT_ASYNC_JOB: throw randolf::rex::xTLS_WANT_ASYNC_JOB("SSL_ERROR_WANT_ASYNC_JOB" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
557 case SSL_ERROR_WANT_CLIENT_HELLO_CB: throw randolf::rex::xTLS_WANT_CLIENT_HELLO_CB("SSL_ERROR_WANT_CLIENT_HELLO_CB" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
558 case SSL_ERROR_WANT_CONNECT: throw randolf::rex::xTLS_WANT_CONNECT("SSL_ERROR_WANT_CONNECT" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
559 case SSL_ERROR_WANT_READ: throw randolf::rex::xTLS_WANT_READ("SSL_ERROR_WANT_READ" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
560 case SSL_ERROR_WANT_WRITE: throw randolf::rex::xTLS_WANT_WRITE("SSL_ERROR_WANT_WRITE" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
561 case SSL_ERROR_WANT_X509_LOOKUP: throw randolf::rex::xTLS_WANT_X509_LOOKUP("SSL_ERROR_WANT_X509_LOOKUP" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
562 case SSL_ERROR_ZERO_RETURN: throw randolf::rex::xTLS_ZERO_RETURN("SSL_ERROR_ZERO_RETURN" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
563 default: if (errno == 0) throw randolf::rex::xUNKNOWN("SSL_ERROR_UNKNOWN" + m, rex_errno, rex::REX_FLAGS::REX_TLS); // Everything else
564 rex_errno = errno; // Fall through to general exceptions
565 }; // -x- switch rex_errno -x-
566 } // -x- if rex::REX_FLAGS::REX_TLS -x-
567
568 // --------------------------------------------------------------------------
569 // General exeptions: Miscellanous fixups
570 // --------------------------------------------------------------------------
571 if (rex_errno == EAGAIN && EAGAIN != EWOULDBLOCK) rex_errno = EWOULDBLOCK; // These are the same, even though some systems define them differently
572 else if (rex_errno == ENOTSUP && ENOTSUP != EOPNOTSUPP) rex_errno = EOPNOTSUPP; // These are the same, even though some systems define them differently
573
574 // --------------------------------------------------------------------------
575 // General exeptions.
576 // --------------------------------------------------------------------------
577 switch(rex_errno) {
578 case E2BIG: throw randolf::rex::xE2BIG("E2BIG" + m, rex_errno);
579 case EACCES: throw randolf::rex::xEACCES("EACCES" + m, rex_errno);
580 case EADDRINUSE: throw randolf::rex::xEADDRINUSE("EADDRINUSE" + m, rex_errno);
581 case EADDRNOTAVAIL: throw randolf::rex::xEADDRNOTAVAIL("EADDRNOTAVAIL" + m, rex_errno);
582 case EAFNOSUPPORT: throw randolf::rex::xEAFNOSUPPORT("EAFNOSUPPORT" + m, rex_errno);
583 case EAI_ADDRFAMILY: throw randolf::rex::xEAI_ADDRFAMILY("EAI_ADDRFAMILY" + m, rex_errno);
584 case EAI_AGAIN: throw randolf::rex::xEAI_AGAIN("EAI_AGAIN" + m, rex_errno);
585 case EAI_ALLDONE: throw randolf::rex::xEAI_ALLDONE("EAI_ALLDONE" + m, rex_errno);
586 case EAI_BADFLAGS: throw randolf::rex::xEAI_BADFLAGS("EAI_BADFLAGS" + m, rex_errno);
587 case EAI_CANCELED: throw randolf::rex::xEAI_CANCELED("EAI_CANCELED" + m, rex_errno);
588 case EAI_FAIL: throw randolf::rex::xEAI_FAIL("EAI_FAIL" + m, rex_errno);
589 case EAI_FAMILY: throw randolf::rex::xEAI_FAMILY("EAI_FAMILY" + m, rex_errno);
590 case EAI_IDN_ENCODE: throw randolf::rex::xEAI_IDN_ENCODE("EAI_IDN_ENCODE" + m, rex_errno);
591 case EAI_INPROGRESS: throw randolf::rex::xEAI_INPROGRESS("EAI_INPROGRESS" + m, rex_errno);
592 case EAI_INTR: throw randolf::rex::xEAI_INTR("EAI_INTR" + m, rex_errno);
593 case EAI_MEMORY: throw randolf::rex::xEAI_MEMORY("EAI_MEMORY" + m, rex_errno);
594 case EAI_NODATA: throw randolf::rex::xEAI_NODATA("EAI_NODATA" + m, rex_errno);
595 case EAI_NONAME: throw randolf::rex::xEAI_NONAME("EAI_NONAME" + m, rex_errno);
596 case EAI_NOTCANCELED: throw randolf::rex::xEAI_NOTCANCELED("EAI_NOTCANCELED" + m, rex_errno);
597 case EAI_OVERFLOW: throw randolf::rex::xEAI_OVERFLOW("EAI_OVERFLOW" + m, rex_errno);
598 case EAI_SERVICE: throw randolf::rex::xEAI_SERVICE("EAI_SERVICE" + m, rex_errno);
599 case EAI_SOCKTYPE: throw randolf::rex::xEAI_SOCKTYPE("EAI_SOCKTYPE" + m, rex_errno);
600 case EAI_SYSTEM: throw randolf::rex::xEAI_SYSTEM("EAI_SYSTEM" + m, rex_errno);
601 case EALREADY: throw randolf::rex::xEALREADY("EALREADY" + m, rex_errno);
602 case EBADE: throw randolf::rex::xEBADE("EBADE" + m, rex_errno);
603 case EBADF: throw randolf::rex::xEBADF("EBADF" + m, rex_errno);
604 case EBADFD: throw randolf::rex::xEBADFD("EBADFD" + m, rex_errno);
605 case EBADMSG: throw randolf::rex::xEBADMSG("EBADMSG" + m, rex_errno);
606 case EBADR: throw randolf::rex::xEBADR("EBADR" + m, rex_errno);
607 case EBADRQC: throw randolf::rex::xEBADRQC("EBADRQC" + m, rex_errno);
608 case EBADSLT: throw randolf::rex::xEBADSLT("EBADSLT" + m, rex_errno);
609 case EBUSY: throw randolf::rex::xEBUSY("EBUSY" + m, rex_errno);
610 case ECOMM: throw randolf::rex::xECOMM("ECOMM" + m, rex_errno);
611 case ECONNABORTED: throw randolf::rex::xECONNABORTED("ECONNABORTED" + m, rex_errno);
612 case ECONNREFUSED: throw randolf::rex::xECONNREFUSED("ECONNREFUSED" + m, rex_errno);
613 case ECONNRESET: throw randolf::rex::xECONNRESET("ECONNRESET" + m, rex_errno);
614 case EDEADLK: throw randolf::rex::xEDEADLK("EDEADLK" + m, rex_errno);
615 case EDESTADDRREQ: throw randolf::rex::xEDESTADDRREQ("EDESTADDRREQ" + m, rex_errno);
616 case EFAULT: throw randolf::rex::xEFAULT("EFAULT" + m, rex_errno);
617 case EHOSTDOWN: throw randolf::rex::xEHOSTDOWN("EHOSTDOWN" + m, rex_errno);
618 case EHOSTUNREACH: throw randolf::rex::xEHOSTUNREACH("EHOSTUNREACH" + m, rex_errno);
619 case EILSEQ: throw randolf::rex::xEILSEQ("EILSEQ" + m, rex_errno);
620 case EINPROGRESS: throw randolf::rex::xEINPROGRESS("EINPROGRESS" + m, rex_errno);
621 case EINTR: throw randolf::rex::xEINTR("EINTR" + m, rex_errno);
622 case EINVAL: throw randolf::rex::xEINVAL("EINVAL" + m, rex_errno);
623 case EIO: throw randolf::rex::xEIO("EIO" + m, rex_errno);
624 case EISCONN: throw randolf::rex::xEISCONN("EISCONN" + m, rex_errno);
625 case ELOOP: throw randolf::rex::xELOOP("ELOOP" + m, rex_errno);
626 case EMFILE: throw randolf::rex::xEMFILE("EMFILE" + m, rex_errno);
627 case EMSGSIZE: throw randolf::rex::xEMSGSIZE("EMSGSIZE" + m, rex_errno);
628 case EMULTIHOP: throw randolf::rex::xEMULTIHOP("EMULTIHOP" + m, rex_errno);
629 case ENAMETOOLONG: throw randolf::rex::xENAMETOOLONG("ENAMETOOLONG" + m, rex_errno);
630 case ENETDOWN: throw randolf::rex::xENETDOWN("ENETDOWN" + m, rex_errno);
631 case ENETRESET: throw randolf::rex::xENETRESET("ENETRESET" + m, rex_errno);
632 case ENETUNREACH: throw randolf::rex::xENETUNREACH("ENETUNREACH" + m, rex_errno);
633 case ENFILE: throw randolf::rex::xENFILE("ENFILE" + m, rex_errno);
634 case ENOBUFS: throw randolf::rex::xENOBUFS("ENOBUFS" + m, rex_errno);
635 case ENODATA: throw randolf::rex::xENODATA("ENODATA" + m, rex_errno);
636 case ENODEV: throw randolf::rex::xENODEV("ENODEV" + m, rex_errno);
637 case ENOENT: throw randolf::rex::xENOENT("ENOENT" + m, rex_errno);
638 case ENOLINK: throw randolf::rex::xENOLINK("ENOLINK" + m, rex_errno);
639 case ENOMEM: throw randolf::rex::xENOMEM("ENOMEM" + m, rex_errno);
640 case ENONET: throw randolf::rex::xENONET("ENONET" + m, rex_errno);
641 case ENOPROTOOPT: throw randolf::rex::xENOPROTOOPT("ENOPROTOOPT" + m, rex_errno);
642 case ENOSR: throw randolf::rex::xENOSR("ENOSR" + m, rex_errno);
643 case ENOSPC: throw randolf::rex::xENOSPC("ENOSPC" + m, rex_errno);
644 case ENOSTR: throw randolf::rex::xENOSTR("ENOSTR" + m, rex_errno);
645 case ENOTCONN: throw randolf::rex::xENOTCONN("ENOTCONN" + m, rex_errno);
646 case ENOTDIR: throw randolf::rex::xENOTDIR("ENOTDIR" + m, rex_errno);
647 case ENOTSOCK: throw randolf::rex::xENOTSOCK("ENOTSOCK" + m, rex_errno);
648 case ENOTTY: throw randolf::rex::xENOTTY("ENOTTY" + m, rex_errno);
649 case ENOTUNIQ: throw randolf::rex::xENOTUNIQ("ENOTUNIQ" + m, rex_errno);
650 case ENXIO: throw randolf::rex::xENXIO("ENXIO" + m, rex_errno);
651 case EOPNOTSUPP: if (flags && rex::REX_FLAGS::REX_ALT_ENOTSUP)
652 throw randolf::rex::xENOTSUP("ENOTSUP" + m, rex_errno);
653 else throw randolf::rex::xEOPNOTSUPP("EOPNOTSUPP" + m, rex_errno);
654 case EOVERFLOW: throw randolf::rex::xEOVERFLOW("EOVERFLOW" + m, rex_errno);
655 case EPERM: throw randolf::rex::xEPERM("EPERM" + m, rex_errno);
656 case EPFNOSUPPORT: throw randolf::rex::xEPFNOSUPPORT("EPFNOSUPPORT" + m, rex_errno);
657 case EPIPE: throw randolf::rex::xEPIPE("EPIPE" + m, rex_errno);
658 case EPROTO: throw randolf::rex::xEPROTO("EPROTO" + m, rex_errno);
659 case EPROTONOSUPPORT: throw randolf::rex::xEPROTONOSUPPORT("EPROTONOSUPPORT" + m, rex_errno);
660 case EPROTOTYPE: throw randolf::rex::xEPROTOTYPE("EPROTOTYPE" + m, rex_errno);
661 case ERANGE: throw randolf::rex::xERANGE("ERANGE" + m, rex_errno);
662 case EREMOTEIO: throw randolf::rex::xEREMOTEIO("EREMOTEIO" + m, rex_errno);
663// case ERESTARTSYS: throw randolf::rex::xERESTARTSYS("ERESTARTSYS" + m, rex_errno);
664 case EROFS: throw randolf::rex::xEROFS("EROFS" + m, rex_errno);
665 case ESOCKTNOSUPPORT: throw randolf::rex::xESOCKTNOSUPPORT("ESOCKTNOSUPPORT" + m, rex_errno);
666 case ESRCH: throw randolf::rex::xESRCH("ESRCH" + m, rex_errno);
667 case ETIME: throw randolf::rex::xETIME("ETIME" + m, rex_errno);
668 case ETIMEDOUT: throw randolf::rex::xETIMEDOUT("ETIMEDOUT" + m, rex_errno);
669 case EWOULDBLOCK: if (flags && rex::REX_FLAGS::REX_ALT_EAGAIN)
670 throw randolf::rex::xEAGAIN("EAGAIN" + m, rex_errno);
671 else throw randolf::rex::xEWOULDBLOCK("EWOULDBLOCK" + m, rex_errno); // a.k.a., EAGAIN
672 default: throw randolf::rex::xUNKNOWN("UNKNOWN" + m, rex_errno); // Everything else
673 }; // -x- switch rex_errno -x-
674
675 // Total: 102 socket exceptions (including randolf::rex::xALL_-prefixed exceptions groups)
676// Helpful alternative reference: https://www.ibm.com/docs/en/zos/2.3.0?topic=codes-sockets-return-errnos
677
678 }; // -x- void rex::mk_exception -x-
679
680 } // -x- namespace rex -x-
681} // -x- namespace randolf -x-