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