3#include <netdb.h> // gai_strerror()
4#include <iostream> // std::string
7#include <string.h> // strerror()
9#include <openssl/err.h> // OpenSSL's ERR_peek_err() function
10#include <openssl/ssl.h> // OpenSSL error codes
15 /*======================================================================*//**
17 Randolf's exceptions class, that takes errors from POSIX and OpenSSL
18 functions and throws logically-named C++ exceptions.
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.
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
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).
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.
41 @par Compilation dependencies
42 In your source code, the following include line is needed:
44 #include <randolf/rex>
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
53 g++ -std=c++20 -x c++ rex -lcrypto
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).
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.
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 {
79 // --------------------------------------------------------------------------
80 // Internal variables.
81 // --------------------------------------------------------------------------
84 int __flags = REX_FLAGS::REX_DEFAULT;
87 /*======================================================================*//**
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 *///=========================================================================
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 *///-------------------------------------------------------------------------
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 *///-------------------------------------------------------------------------
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 *///-------------------------------------------------------------------------
115 /*----------------------------------------------------------------------*//**
116 Throw xEAGAIN instead of xEWOULDBLOCK, if either the @c EAGAIN error code or
117 the @c EWOULDBLOCK error code is encountered.
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.
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,
130 /*----------------------------------------------------------------------*//**
131 Throw xENOTSUP instead of xEOPNOTSUPP, if either the @c ENOTSUP error code or
132 the @c EOPNOTSUPP error code is encountered.
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.
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,
145 }; // -x- enum REX_FLAGS -x-
147 /*======================================================================*//**
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-
156 /*======================================================================*//**
158 Construct exception with an ASCIIZ string.
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
167 /// Result of the errno() function goes here (if known)
170 const int flags = REX_FLAGS::REX_DEFAULT) : __msg(m), __errno(n) {
172 // --------------------------------------------------------------------------
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-
179 // --------------------------------------------------------------------------
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-
186 // --------------------------------------------------------------------------
187 // Build error string.
188 // --------------------------------------------------------------------------
189 if (flags && REX_FLAGS::REX_TLS) {
191 ERR_error_string_n(n, buf, sizeof(buf)); // Get error string from OpenSSL in a thread-safe way
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
197 .append(std::to_string(n)) // Include error number in parenthesis (via all three append() methods here)
199 } // -x- if flags -x-
201 }; // -x- constructor rex -x-
203 /*======================================================================*//**
205 Construct exception with an std::string object.
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)
217 const int flags = REX_FLAGS::REX_DEFAULT) : __msg(m), __errno(n), __flags(flags) {
219 // --------------------------------------------------------------------------
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-
226 // --------------------------------------------------------------------------
227 // Build error string.
228 // --------------------------------------------------------------------------
229 if (flags && REX_FLAGS::REX_TLS) {
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);
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
237 .append(std::to_string(n)) // Include error number in parenthesis (via all three append() methods here)
239 } // -x- if flags -x-
241 }; // -x- constructor rex -x-
243 /*======================================================================*//**
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 {
251 }; // -x- int err_no -x-
253 /*======================================================================*//**
255 Arbitrarily throw an exception based on the error number.
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).
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).
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
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
276 /// Flags that influence how exceptions are thrown
277 const int flags = rex::REX_FLAGS::REX_DEFAULT);
278 // Forward-declaration.
280 /*======================================================================*//**
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-
290 }; // -x- class rex -x-
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)
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
519 /// Flags that influence how exceptions are thrown
520 const int flags = rex::REX_FLAGS::REX_DEFAULT) {
522 // --------------------------------------------------------------------------
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-
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
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;
546 // TODO: If SSL_get_error() returns SSL_ERROR_SSL, use ERR_get_error() and related functions instead.
547 // --------------------------------------------------------------------------
549 // --------------------------------------------------------------------------
550 if (flags && rex::REX_FLAGS::REX_TLS) {
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-
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
574 // --------------------------------------------------------------------------
575 // General exeptions.
576 // --------------------------------------------------------------------------
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-
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
678 }; // -x- void rex::mk_exception -x-
680 } // -x- namespace rex -x-
681} // -x- namespace randolf -x-