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) {
190 if (flags & REX_FLAGS::REX_TLS) {
192 ERR_error_string_n(n, buf, sizeof(buf)); // Get error string from OpenSSL in a thread-safe way
195 if (__msg.find(" ") == std::string::npos) __msg.append(__msg.empty() ? "" : ": ") // Empty or single-word, so more detail is needed
196 .append(gai_strerror(n) != "Unknown error" ? gai_strerror(n) : strerror(n)) // Use EAI error string instead if it's available
198 .append(std::to_string(n)) // Include error number in parenthesis (via all three append() methods here)
200 } // -x- if flags -x-
202 }; // -x- constructor rex -x-
204 /*======================================================================*//**
206 Construct exception with an std::string object.
208 When throwing an exception, it's not necessary to know the error number,
209 which means that new types of errors can be introduced (although we really
210 want to avoid deviating from the standard Linux API as much as possible).
211 @see mk_exception(std::string, long, int)
212 *///=========================================================================
213 explicit rex(/// Error code as an std::string
214 const std::string& m,
215 /// Result of the errno() function goes here (if known)
218 const int flags = REX_FLAGS::REX_DEFAULT) : __msg(m), __errno(n), __flags(flags) {
220 // --------------------------------------------------------------------------
222 // --------------------------------------------------------------------------
223 if (flags && REX_FLAGS::REX_FIND_ERRNO) {
224 n = flags && REX_FLAGS::REX_TLS ? ERR_peek_error() : errno;
225 } // -x- if FIND::ERRNO -x-
227 // --------------------------------------------------------------------------
228 // Build error string.
229 // --------------------------------------------------------------------------
230 if (flags && REX_FLAGS::REX_TLS) {
232 ERR_error_string_n(n, buf, sizeof(buf)); // Get error string from OpenSSL in a thread-safe way
233 __msg.append(__msg.empty() ? "" : ": ").append(buf);
235 if (__msg.find(" ") == std::string::npos) __msg.append(__msg.empty() ? "" : ": ") // Empty or single-word, so more detail is needed
236 .append(gai_strerror(n) != "Unknown error" ? gai_strerror(n) : strerror(n)) // Use EAI error string instead if it's available
238 .append(std::to_string(n)) // Include error number in parenthesis (via all three append() methods here)
240 } // -x- if flags -x-
242 }; // -x- constructor rex -x-
244 /*======================================================================*//**
246 Find out what the @c errno (or OpenSSL's @c ERR_get_error() number) was that
247 caused this exception to be thrown.
248 @return Original errno() value
249 *///=========================================================================
250 const long err_no() const noexcept {
252 }; // -x- int err_no -x-
254 /*======================================================================*//**
256 Arbitrarily throw an exception based on the error number.
258 This is useful for developers who may need (or want) to throw a specific
259 exception to ease error handling for circumstances that warrant throwing a
260 particular exception that otherwise normally wouldn't be thrown (0 will also
261 cause @ref xUNKNOWN to be thrown).
263 If the error message text isn't known, then passing in an empty std::string
264 will trigger the relevant error message to be generated automatically).
267 The exception xTLS_ZERO_RETURN represents OpenSSL's error code 6, which is an
268 actual error, unlike 0, which indicates that an error didn't occur.
269 @throws rex has many subclasses, all of which may be caught individually, or
270 under one of the rex exceptions groups, such as @ref xALL
272 *///=========================================================================
273 static void mk_exception(/// Custom error message (replaces default message if defined)
274 const std::string msg = "",
275 /// 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
277 /// Flags that influence how exceptions are thrown
278 const int flags = rex::REX_FLAGS::REX_DEFAULT);
279 // Forward-declaration.
281 /*======================================================================*//**
283 Find out what the reason (usually the error code, e.g., EAGAIN) was for this
284 exception to be thrown.
285 @return Error code text as a pointer to an ASCIIZ string
286 *///=========================================================================
287 const char* what() const noexcept {
288 return __msg.c_str();
289 }; // -x- char* what -x-
291 }; // -x- class rex -x-
295 /// Exception group that can be used to catch exceptions thrown for errors returned from POSIX fuctions (e.g., socket functions).
296 class xALL : public virtual rex { using rex::rex; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); }; // Exception group
297 /// Exception for error: @c E2BIG
298 class xE2BIG : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
299 /// Exception for error: @c EACCES
300 class xEACCES : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
301 /// Exception for error: @c EADDRINUSE
302 class xEADDRINUSE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
303 /// Exception for error: @c EADDRNOTAVAIL
304 class xEADDRNOTAVAIL : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
305 /// Exception for error: @c EAFNOSUPPORT
306 class xEAFNOSUPPORT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
307 /// Exception for error: @c EAGAIN / @c EWOULDBLOCK
308 class xEAGAIN : public virtual xALL { using xALL::xALL; };
309 /// Exception group that can be used to catch exceptions thrown for @c EAI_ errors returned from POSIX fuctions (e.g., socket functions).
310 class xALL_EAI : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); }; // Exception group
311 /// Exception for error: @c EAI_ADDRFAMILY
312 class xEAI_ADDRFAMILY : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
313 /// Exception for error: @c EAI_AGAIN
314 class xEAI_AGAIN : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
315 /// Exception for error: @c EAI_BADFLAGS
316 class xEAI_BADFLAGS : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
317 /// Exception for error: @c EAI_FAIL
318 class xEAI_FAIL : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
319 /// Exception for error: @c EAI_FAMILY
320 class xEAI_FAMILY : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
321 /// Exception for error: @c EAI_INPROGRESS
322 class xEAI_INPROGRESS : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
323 /// Exception for error: @c EAI_SERVICE
324 class xEAI_SERVICE : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
325 /// Exception for error: @c EAI_SOCKTYPE
326 class xEAI_SOCKTYPE : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
327 /// Exception for error: @c EAI_SYSTEM
328 class xEAI_SYSTEM : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
329 /// Exception for error: @c EAI_MEMORY
330 class xEAI_MEMORY : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
331 /// Exception for error: @c EAI_NODATA
332 class xEAI_NODATA : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
333 /// Exception for error: @c EAI_NONAME
334 class xEAI_NONAME : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
335 /// Exception for error: @c EAI_OVERFLOW
336 class xEAI_OVERFLOW : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
337 /// Exception for error: @c EAI_CANCELED
338 class xEAI_CANCELED : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
339 /// Exception for error: @c EAI_NOTCANCELED
340 class xEAI_NOTCANCELED : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
341 /// Exception for error: @c EAI_ALLDONE
342 class xEAI_ALLDONE : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
343 /// Exception for error: @c EAI_INTR
344 class xEAI_INTR : public virtual xALL_EAI { using xALL_EAI::xALL_EAI; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
345 /// Exception for error: @c EAI_IDN_ENCODE
346 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); };
347 /// Exception for error: @c EALREADY
348 class xEALREADY : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
349 /// Exception for error: @c EBADE
350 class xEBADE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
351 /// Exception for error: @c EBADF
352 class xEBADF : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
353 /// Exception for error: @c EBADFD
354 class xEBADFD : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
355 /// Exception for error: @c EBADMSG
356 class xEBADMSG : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
357 /// Exception for error: @c EBADR
358 class xEBADR : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
359 /// Exception for error: @c EBADRQC
360 class xEBADRQC : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
361 /// Exception for error: @c EBADSLT
362 class xEBADSLT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
363 /// Exception for error: @c EBUSY
364 class xEBUSY : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
365 /// Exception for error: @c ECOMM
366 class xECOMM : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
367 /// Exception for error: @c ECONNABORTED
368 class xECONNABORTED : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
369 /// Exception for error: @c ECONNREFUSED
370 class xECONNREFUSED : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
371 /// Exception for error: @c ECONNRESET
372 class xECONNRESET : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
373 /// Exception for error: @c EDEADLK
374 class xEDEADLK : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
375 /// Exception for error: @c EDESTADDRREQ
376 class xEDESTADDRREQ : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
377 /// Exception for error: @c EFAULT
378 class xEFAULT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
379 /// Exception for error: @c EHOSTDOWN
380 class xEHOSTDOWN : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
381 /// Exception for error: @c EHOSTUNREACH
382 class xEHOSTUNREACH : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
383 /// Exception for error: @c EILSEQ
384 class xEILSEQ : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
385 /// Exception for error: @c EINPROGRESS
386 class xEINPROGRESS : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
387 /// Exception for error: @c EINTR
388 class xEINTR : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
389 /// Exception for error: @c EINVAL
390 class xEINVAL : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
391 /// Exception for error: @c EIO
392 class xEIO : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
393 /// Exception for error: @c EISCONN
394 class xEISCONN : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
395 /// Exception for error: @c ELOOP
396 class xELOOP : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
397 /// Exception for error: @c EMFILE
398 class xEMFILE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
399 /// Exception for error: @c EMSGSIZE
400 class xEMSGSIZE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
401 /// Exception for error: @c EMULTIHOP
402 class xEMULTIHOP : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
403 /// Exception for error: @c ENAMETOOLONG
404 class xENAMETOOLONG : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
405 /// Exception for error: @c ENETDOWN
406 class xENETDOWN : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
407 /// Exception for error: @c ENETRESET
408 class xENETRESET : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
409 /// Exception for error: @c ENETUNREACH
410 class xENETUNREACH : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
411 /// Exception for error: @c ENFILE
412 class xENFILE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
413 /// Exception for error: @c ENOBUFS
414 class xENOBUFS : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
415 /// Exception for error: @c ENODATA
416 class xENODATA : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
417 /// Exception for error: @c ENODEV
418 class xENODEV : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
419 /// Exception for error: @c ENOENT
420 class xENOENT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
421 /// Exception for error: @c ENOLINK
422 class xENOLINK : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
423 /// Exception for error: @c ENOMEM
424 class xENOMEM : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
425 /// Exception for error: @c ENONET
426 class xENONET : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
427 /// Exception for error: @c ENOPROTOOPT
428 class xENOPROTOOPT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
429 /// Exception for error: @c ENOSR
430 class xENOSR : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
431 /// Exception for error: @c ENOSPC
432 class xENOSPC : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
433 /// Exception for error: @c ENOSTR
434 class xENOSTR : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
435 /// Exception for error: @c ENOTCONN
436 class xENOTCONN : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
437 /// Exception for error: @c ENOTDIR
438 class xENOTDIR : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
439 /// Exception for error: @c ENOTSOCK
440 class xENOTSOCK : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
441 /// Exception for error: @c ENOTSUP / @c EOPTNOTSUP
442 class xENOTSUP : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); }; // a.k.a., EOPTNOTSUP
443 /// Exception for error: @c ENOTTY
444 class xENOTTY : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
445 /// Exception for error: @c ENOTUNIQ
446 class xENOTUNIQ : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
447 /// Exception for error: @c ENXIO
448 class xENXIO : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
449 /// Exception for error: @c EOPNOTSUPP
450 class xEOPNOTSUPP : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
451 /// Exception for error: @c EOVERFLOW
452 class xEOVERFLOW : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
453 /// Exception for error: @c EPERM
454 class xEPERM : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
455 /// Exception for error: @c EPFNOSUPPORT
456 class xEPFNOSUPPORT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
457 /// Exception for error: @c EPIPE
458 class xEPIPE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
459 /// Exception for error: @c EPROTONOSUPPORT
460 class xEPROTO : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
461 /// Exception for error: @c EPROTO
462 class xEPROTONOSUPPORT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
463 /// Exception for error: @c EPROTOTYPE
464 class xEPROTOTYPE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
465 /// Exception for error: @c ERANGE
466 class xERANGE : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
467 /// Exception for error: @c EREMOTEIO
468 class xEREMOTEIO : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
469// /// Exception for error: @c ERESTARTSYS
470// class xERESTARTSYS : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
471 /// Exception for error: @c EROFS
472 class xEROFS : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
473 /// Exception for error: @c ESOCKNOSUPPORT
474 class xESOCKTNOSUPPORT : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
475 /// Exception for error: @c ESRCH
476 class xESRCH : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
477 /// 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).
478 class xALL_ETIME : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); }; // Exception group
479 /// Exception for error: @c ETIME
480 class xETIME : public virtual xALL_ETIME { using xALL_ETIME::xALL_ETIME; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
481 /// Exception for error: @c ETIMEDOUT
482 class xETIMEDOUT : public virtual xALL_ETIME { using xALL_ETIME::xALL_ETIME; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
483 /// Exception group that can be used to catch exceptions thrown for @c TLS errors returned from OpenSSL socket functions.
484 class xALL_TLS : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); }; // Exception group
485 /// Exception for error @c SSL_ERROR_SYSCALL
486 class xTLS_SYSCALL : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
487 /// Exception for error @c SSL_ERROR_SSL
488 class xTLS_TLS : public virtual xALL_TLS { using xALL_TLS::xALL_TLS; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
489 /// Exception for error @c SSL_ERROR_WANT_ACCEPT
490 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); };
491 /// Exception for error @c SSL_ERROR_WANT_ASYNC
492 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); };
493 /// Exception for error @c SSL_ERROR_WANT_ASYNC_JOB
494 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); };
495 /// Exception for error @c SSL_ERROR_WANT_CLIENT_HELLO_CB
496 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); };
497 /// Exception for error @c SSL_ERROR_WANT_CONNECT
498 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); };
499 /// Exception for error @c SSL_ERROR_WANT_READ
500 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); };
501 /// Exception for error @c SSL_ERROR_WANT_WRITE
502 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); };
503 /// Exception for error @c SSL_ERROR_WANT_X509_LOOKUP
504 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); };
505 /// Exception for error @c SSL_ERROR_ZERO_RETURN
506 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); };
507 /// Exception for error: @c EWOULDBLOCK / @c EAGAIN
508 class xEWOULDBLOCK : public virtual xALL { using xALL::xALL; };
509 /// Exception for all other errors that are not known
510 class xUNKNOWN : public virtual xALL { using xALL::xALL; private: enum REX_FLAGS: int{}; void mk_exception(std::string, long, int); };
511 // Total: 102 socket exceptions (including xALL, xALL_EAI, xALL_ETIME, and xALL_TLS groups)
513 /*======================================================================*//**
514 @copydoc mk_exception(std::string, long, int)
515 *///=========================================================================
516 static void mk_exception(/// Custom error message (replaces default message if defined)
517 const std::string msg = "",
518 /// 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
520 /// Flags that influence how exceptions are thrown
521 const int flags = rex::REX_FLAGS::REX_DEFAULT) {
523 // --------------------------------------------------------------------------
525 // --------------------------------------------------------------------------
526 if (flags && rex::REX_FLAGS::REX_FIND_ERRNO) {
527 rex_errno = flags && rex::REX_FLAGS::REX_TLS ? ERR_peek_error() : errno;
528 } // -x- if FIND::ERRNO -x-
530 // --------------------------------------------------------------------------
531 // If there is no error, then just return without throwing an exception. The
532 // reason we handle this here now is to save CPU cycles (handling it in a
533 // default case later requires first running many other comparisons that
534 // are less of a conern when an exception is to be thrown because greater
535 // efficiency is normally needed when errors aren't occurring).
536 // --------------------------------------------------------------------------
537 if (rex_errno == 0) return; // Do nothing for error code 0
539 // --------------------------------------------------------------------------
540 // Effectively insert text in front of msg if it's not empty so it remains
541 // properly separated from the error type text. (We're working with a copy
542 // of the string because we want to not change the std::string that was
543 // specified by the caller.)
544 // --------------------------------------------------------------------------
545 std::string m = msg.empty() ? msg : ": " + msg;
547 // TODO: If SSL_get_error() returns SSL_ERROR_SSL, use ERR_get_error() and related functions instead.
548 // --------------------------------------------------------------------------
550 // --------------------------------------------------------------------------
551 if (flags && rex::REX_FLAGS::REX_TLS) {
553 case SSL_ERROR_SYSCALL: throw randolf::rex::xTLS_SYSCALL("SSL_ERROR_SYSCALL" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
554 case SSL_ERROR_SSL: throw randolf::rex::xTLS_TLS("SSL_ERROR_SSL" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
555 case SSL_ERROR_WANT_ACCEPT: throw randolf::rex::xTLS_WANT_ACCEPT("SSL_ERROR_WANT_ACCEPT" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
556 case SSL_ERROR_WANT_ASYNC: throw randolf::rex::xTLS_WANT_ASYNC("SSL_ERROR_WANT_ASYNC" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
557 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);
558 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);
559 case SSL_ERROR_WANT_CONNECT: throw randolf::rex::xTLS_WANT_CONNECT("SSL_ERROR_WANT_CONNECT" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
560 case SSL_ERROR_WANT_READ: throw randolf::rex::xTLS_WANT_READ("SSL_ERROR_WANT_READ" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
561 case SSL_ERROR_WANT_WRITE: throw randolf::rex::xTLS_WANT_WRITE("SSL_ERROR_WANT_WRITE" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
562 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);
563 case SSL_ERROR_ZERO_RETURN: throw randolf::rex::xTLS_ZERO_RETURN("SSL_ERROR_ZERO_RETURN" + m, rex_errno, rex::REX_FLAGS::REX_TLS);
564 default: if (errno == 0) throw randolf::rex::xUNKNOWN("SSL_ERROR_UNKNOWN" + m, rex_errno, rex::REX_FLAGS::REX_TLS); // Everything else
565 rex_errno = errno; // Fall through to general exceptions
566 }; // -x- switch rex_errno -x-
567 } // -x- if rex::REX_FLAGS::REX_TLS -x-
569 // --------------------------------------------------------------------------
570 // General exeptions: Miscellanous fixups
571 // --------------------------------------------------------------------------
572 if (rex_errno == EAGAIN && EAGAIN != EWOULDBLOCK) rex_errno = EWOULDBLOCK; // These are the same, even though some systems define them differently
573 else if (rex_errno == ENOTSUP && ENOTSUP != EOPNOTSUPP) rex_errno = EOPNOTSUPP; // These are the same, even though some systems define them differently
575 // --------------------------------------------------------------------------
576 // General exeptions.
577 // --------------------------------------------------------------------------
579 case E2BIG: throw randolf::rex::xE2BIG("E2BIG" + m, rex_errno);
580 case EACCES: throw randolf::rex::xEACCES("EACCES" + m, rex_errno);
581 case EADDRINUSE: throw randolf::rex::xEADDRINUSE("EADDRINUSE" + m, rex_errno);
582 case EADDRNOTAVAIL: throw randolf::rex::xEADDRNOTAVAIL("EADDRNOTAVAIL" + m, rex_errno);
583 case EAFNOSUPPORT: throw randolf::rex::xEAFNOSUPPORT("EAFNOSUPPORT" + m, rex_errno);
584 case EAI_ADDRFAMILY: throw randolf::rex::xEAI_ADDRFAMILY("EAI_ADDRFAMILY" + m, rex_errno);
585 case EAI_AGAIN: throw randolf::rex::xEAI_AGAIN("EAI_AGAIN" + m, rex_errno);
586 case EAI_ALLDONE: throw randolf::rex::xEAI_ALLDONE("EAI_ALLDONE" + m, rex_errno);
587 case EAI_BADFLAGS: throw randolf::rex::xEAI_BADFLAGS("EAI_BADFLAGS" + m, rex_errno);
588 case EAI_CANCELED: throw randolf::rex::xEAI_CANCELED("EAI_CANCELED" + m, rex_errno);
589 case EAI_FAIL: throw randolf::rex::xEAI_FAIL("EAI_FAIL" + m, rex_errno);
590 case EAI_FAMILY: throw randolf::rex::xEAI_FAMILY("EAI_FAMILY" + m, rex_errno);
591 case EAI_IDN_ENCODE: throw randolf::rex::xEAI_IDN_ENCODE("EAI_IDN_ENCODE" + m, rex_errno);
592 case EAI_INPROGRESS: throw randolf::rex::xEAI_INPROGRESS("EAI_INPROGRESS" + m, rex_errno);
593 case EAI_INTR: throw randolf::rex::xEAI_INTR("EAI_INTR" + m, rex_errno);
594 case EAI_MEMORY: throw randolf::rex::xEAI_MEMORY("EAI_MEMORY" + m, rex_errno);
595 case EAI_NODATA: throw randolf::rex::xEAI_NODATA("EAI_NODATA" + m, rex_errno);
596 case EAI_NONAME: throw randolf::rex::xEAI_NONAME("EAI_NONAME" + m, rex_errno);
597 case EAI_NOTCANCELED: throw randolf::rex::xEAI_NOTCANCELED("EAI_NOTCANCELED" + m, rex_errno);
598 case EAI_OVERFLOW: throw randolf::rex::xEAI_OVERFLOW("EAI_OVERFLOW" + m, rex_errno);
599 case EAI_SERVICE: throw randolf::rex::xEAI_SERVICE("EAI_SERVICE" + m, rex_errno);
600 case EAI_SOCKTYPE: throw randolf::rex::xEAI_SOCKTYPE("EAI_SOCKTYPE" + m, rex_errno);
601 case EAI_SYSTEM: throw randolf::rex::xEAI_SYSTEM("EAI_SYSTEM" + m, rex_errno);
602 case EALREADY: throw randolf::rex::xEALREADY("EALREADY" + m, rex_errno);
603 case EBADE: throw randolf::rex::xEBADE("EBADE" + m, rex_errno);
604 case EBADF: throw randolf::rex::xEBADF("EBADF" + m, rex_errno);
605 case EBADFD: throw randolf::rex::xEBADFD("EBADFD" + m, rex_errno);
606 case EBADMSG: throw randolf::rex::xEBADMSG("EBADMSG" + m, rex_errno);
607 case EBADR: throw randolf::rex::xEBADR("EBADR" + m, rex_errno);
608 case EBADRQC: throw randolf::rex::xEBADRQC("EBADRQC" + m, rex_errno);
609 case EBADSLT: throw randolf::rex::xEBADSLT("EBADSLT" + m, rex_errno);
610 case EBUSY: throw randolf::rex::xEBUSY("EBUSY" + m, rex_errno);
611 case ECOMM: throw randolf::rex::xECOMM("ECOMM" + m, rex_errno);
612 case ECONNABORTED: throw randolf::rex::xECONNABORTED("ECONNABORTED" + m, rex_errno);
613 case ECONNREFUSED: throw randolf::rex::xECONNREFUSED("ECONNREFUSED" + m, rex_errno);
614 case ECONNRESET: throw randolf::rex::xECONNRESET("ECONNRESET" + m, rex_errno);
615 case EDEADLK: throw randolf::rex::xEDEADLK("EDEADLK" + m, rex_errno);
616 case EDESTADDRREQ: throw randolf::rex::xEDESTADDRREQ("EDESTADDRREQ" + m, rex_errno);
617 case EFAULT: throw randolf::rex::xEFAULT("EFAULT" + m, rex_errno);
618 case EHOSTDOWN: throw randolf::rex::xEHOSTDOWN("EHOSTDOWN" + m, rex_errno);
619 case EHOSTUNREACH: throw randolf::rex::xEHOSTUNREACH("EHOSTUNREACH" + m, rex_errno);
620 case EILSEQ: throw randolf::rex::xEILSEQ("EILSEQ" + m, rex_errno);
621 case EINPROGRESS: throw randolf::rex::xEINPROGRESS("EINPROGRESS" + m, rex_errno);
622 case EINTR: throw randolf::rex::xEINTR("EINTR" + m, rex_errno);
623 case EINVAL: throw randolf::rex::xEINVAL("EINVAL" + m, rex_errno);
624 case EIO: throw randolf::rex::xEIO("EIO" + m, rex_errno);
625 case EISCONN: throw randolf::rex::xEISCONN("EISCONN" + m, rex_errno);
626 case ELOOP: throw randolf::rex::xELOOP("ELOOP" + m, rex_errno);
627 case EMFILE: throw randolf::rex::xEMFILE("EMFILE" + m, rex_errno);
628 case EMSGSIZE: throw randolf::rex::xEMSGSIZE("EMSGSIZE" + m, rex_errno);
629 case EMULTIHOP: throw randolf::rex::xEMULTIHOP("EMULTIHOP" + m, rex_errno);
630 case ENAMETOOLONG: throw randolf::rex::xENAMETOOLONG("ENAMETOOLONG" + m, rex_errno);
631 case ENETDOWN: throw randolf::rex::xENETDOWN("ENETDOWN" + m, rex_errno);
632 case ENETRESET: throw randolf::rex::xENETRESET("ENETRESET" + m, rex_errno);
633 case ENETUNREACH: throw randolf::rex::xENETUNREACH("ENETUNREACH" + m, rex_errno);
634 case ENFILE: throw randolf::rex::xENFILE("ENFILE" + m, rex_errno);
635 case ENOBUFS: throw randolf::rex::xENOBUFS("ENOBUFS" + m, rex_errno);
636 case ENODATA: throw randolf::rex::xENODATA("ENODATA" + m, rex_errno);
637 case ENODEV: throw randolf::rex::xENODEV("ENODEV" + m, rex_errno);
638 case ENOENT: throw randolf::rex::xENOENT("ENOENT" + m, rex_errno);
639 case ENOLINK: throw randolf::rex::xENOLINK("ENOLINK" + m, rex_errno);
640 case ENOMEM: throw randolf::rex::xENOMEM("ENOMEM" + m, rex_errno);
641 case ENONET: throw randolf::rex::xENONET("ENONET" + m, rex_errno);
642 case ENOPROTOOPT: throw randolf::rex::xENOPROTOOPT("ENOPROTOOPT" + m, rex_errno);
643 case ENOSR: throw randolf::rex::xENOSR("ENOSR" + m, rex_errno);
644 case ENOSPC: throw randolf::rex::xENOSPC("ENOSPC" + m, rex_errno);
645 case ENOSTR: throw randolf::rex::xENOSTR("ENOSTR" + m, rex_errno);
646 case ENOTCONN: throw randolf::rex::xENOTCONN("ENOTCONN" + m, rex_errno);
647 case ENOTDIR: throw randolf::rex::xENOTDIR("ENOTDIR" + m, rex_errno);
648 case ENOTSOCK: throw randolf::rex::xENOTSOCK("ENOTSOCK" + m, rex_errno);
649 case ENOTTY: throw randolf::rex::xENOTTY("ENOTTY" + m, rex_errno);
650 case ENOTUNIQ: throw randolf::rex::xENOTUNIQ("ENOTUNIQ" + m, rex_errno);
651 case ENXIO: throw randolf::rex::xENXIO("ENXIO" + m, rex_errno);
652 case EOPNOTSUPP: if (flags && rex::REX_FLAGS::REX_ALT_ENOTSUP)
653 throw randolf::rex::xENOTSUP("ENOTSUP" + m, rex_errno);
654 else throw randolf::rex::xEOPNOTSUPP("EOPNOTSUPP" + m, rex_errno);
655 case EOVERFLOW: throw randolf::rex::xEOVERFLOW("EOVERFLOW" + m, rex_errno);
656 case EPERM: throw randolf::rex::xEPERM("EPERM" + m, rex_errno);
657 case EPFNOSUPPORT: throw randolf::rex::xEPFNOSUPPORT("EPFNOSUPPORT" + m, rex_errno);
658 case EPIPE: throw randolf::rex::xEPIPE("EPIPE" + m, rex_errno);
659 case EPROTO: throw randolf::rex::xEPROTO("EPROTO" + m, rex_errno);
660 case EPROTONOSUPPORT: throw randolf::rex::xEPROTONOSUPPORT("EPROTONOSUPPORT" + m, rex_errno);
661 case EPROTOTYPE: throw randolf::rex::xEPROTOTYPE("EPROTOTYPE" + m, rex_errno);
662 case ERANGE: throw randolf::rex::xERANGE("ERANGE" + m, rex_errno);
663 case EREMOTEIO: throw randolf::rex::xEREMOTEIO("EREMOTEIO" + m, rex_errno);
664// case ERESTARTSYS: throw randolf::rex::xERESTARTSYS("ERESTARTSYS" + m, rex_errno);
665 case EROFS: throw randolf::rex::xEROFS("EROFS" + m, rex_errno);
666 case ESOCKTNOSUPPORT: throw randolf::rex::xESOCKTNOSUPPORT("ESOCKTNOSUPPORT" + m, rex_errno);
667 case ESRCH: throw randolf::rex::xESRCH("ESRCH" + m, rex_errno);
668 case ETIME: throw randolf::rex::xETIME("ETIME" + m, rex_errno);
669 case ETIMEDOUT: throw randolf::rex::xETIMEDOUT("ETIMEDOUT" + m, rex_errno);
670 case EWOULDBLOCK: if (flags && rex::REX_FLAGS::REX_ALT_EAGAIN)
671 throw randolf::rex::xEAGAIN("EAGAIN" + m, rex_errno);
672 else throw randolf::rex::xEWOULDBLOCK("EWOULDBLOCK" + m, rex_errno); // a.k.a., EAGAIN
673 default: throw randolf::rex::xUNKNOWN("UNKNOWN" + m, rex_errno); // Everything else
674 }; // -x- switch rex_errno -x-
676 // Total: 102 socket exceptions (including randolf::rex::xALL_-prefixed exceptions groups)
677// Helpful alternative reference: https://www.ibm.com/docs/en/zos/2.3.0?topic=codes-sockets-return-errnos
679 }; // -x- void rex::mk_exception -x-
681 } // -x- namespace rex -x-
682} // -x- namespace randolf -x-