diff options
author | Jack Lloyd <[email protected]> | 2018-11-23 18:38:14 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2018-11-23 18:38:14 -0500 |
commit | 761a7f36f708b44c7af1dc9387f324d509b4acf6 (patch) | |
tree | 43ee497eb84b98c1f1e04a7e60d95b531ba0a88a /src/lib/utils | |
parent | ae42de8433260a37360d60b0a21665e13c4a63e8 (diff) | |
parent | b909778857b3e0b7eb86ac26c818e5f25baaddbd (diff) |
Merge GH #1744 Make exception throws easier to debug
Diffstat (limited to 'src/lib/utils')
-rw-r--r-- | src/lib/utils/assert.cpp | 2 | ||||
-rw-r--r-- | src/lib/utils/dyn_load/dyn_load.cpp | 11 | ||||
-rw-r--r-- | src/lib/utils/exceptn.cpp | 4 | ||||
-rw-r--r-- | src/lib/utils/exceptn.h | 306 | ||||
-rw-r--r-- | src/lib/utils/http_util/http_util.cpp | 2 | ||||
-rw-r--r-- | src/lib/utils/http_util/http_util.h | 27 | ||||
-rw-r--r-- | src/lib/utils/os_utils.cpp | 4 | ||||
-rw-r--r-- | src/lib/utils/read_cfg.cpp | 2 | ||||
-rw-r--r-- | src/lib/utils/safeint.h | 2 | ||||
-rw-r--r-- | src/lib/utils/socket/socket.cpp | 31 |
10 files changed, 287 insertions, 104 deletions
diff --git a/src/lib/utils/assert.cpp b/src/lib/utils/assert.cpp index 31a35374a..b251a469e 100644 --- a/src/lib/utils/assert.cpp +++ b/src/lib/utils/assert.cpp @@ -48,7 +48,7 @@ void assertion_failure(const char* expr_str, format << "@" << file << ":" << line; - throw Exception(format.str()); + throw Internal_Error(format.str()); } } diff --git a/src/lib/utils/dyn_load/dyn_load.cpp b/src/lib/utils/dyn_load/dyn_load.cpp index 1bbcffbdb..b32fe4b3a 100644 --- a/src/lib/utils/dyn_load/dyn_load.cpp +++ b/src/lib/utils/dyn_load/dyn_load.cpp @@ -23,8 +23,11 @@ namespace { void raise_runtime_loader_exception(const std::string& lib_name, const char* msg) { - throw Exception("Failed to load " + lib_name + ": " + - (msg ? msg : "Unknown error")); + const std::string ex_msg = + "Failed to load " + lib_name + ": " + + (msg ? msg : "Unknown error"); + + throw System_Error(ex_msg, 0); } } @@ -70,8 +73,8 @@ void* Dynamically_Loaded_Library::resolve_symbol(const std::string& symbol) #endif if(!addr) - throw Exception("Failed to resolve symbol " + symbol + - " in " + m_lib_name); + throw Invalid_Argument("Failed to resolve symbol " + symbol + + " in " + m_lib_name); return addr; } diff --git a/src/lib/utils/exceptn.cpp b/src/lib/utils/exceptn.cpp index cc6eb9f85..8fc86d3e7 100644 --- a/src/lib/utils/exceptn.cpp +++ b/src/lib/utils/exceptn.cpp @@ -105,6 +105,10 @@ Stream_IO_Error::Stream_IO_Error(const std::string& err) : Exception("I/O error: " + err) {} +System_Error::System_Error(const std::string& msg, int err_code) : + Exception(msg + " error code " + std::to_string(err_code)) + {} + Self_Test_Failure::Self_Test_Failure(const std::string& err) : Internal_Error("Self test failed: " + err) {} diff --git a/src/lib/utils/exceptn.h b/src/lib/utils/exceptn.h index dfe428d72..bfff85618 100644 --- a/src/lib/utils/exceptn.h +++ b/src/lib/utils/exceptn.h @@ -1,6 +1,6 @@ /* * Exceptions -* (C) 1999-2009 Jack Lloyd +* (C) 1999-2009,2018 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -15,22 +15,104 @@ namespace Botan { /** +* Different types of errors that might occur +*/ +enum class ErrorType { + /** Some unknown error */ + Unknown = 1, + /** An error while calling a system interface */ + SystemError, + /** An operation seems valid, but not supported by the current version */ + NotImplemented, + /** Memory allocation failure */ + OutOfMemory, + /** An internal error occurred */ + InternalError, + /** An I/O error occurred */ + IoError, + + /** Invalid object state */ + InvalidObjectState = 100, + /** A key was not set on an object when this is required */ + KeyNotSet, + /** The application provided an argument which is invalid */ + InvalidArgument, + /** A key with invalid length was provided */ + InvalidKeyLength, + /** A nonce with invalid length was provided */ + InvalidNonceLength, + /** An object type was requested but cannot be found */ + LookupError, + /** Encoding a message or datum failed */ + EncodingFailure, + /** Decoding a message or datum failed */ + DecodingFailure, + /** A TLS error (error_code will be the alert type) */ + TLSError, + /** An error during an HTTP operation */ + HttpError, + + /** An error when calling OpenSSL */ + OpenSSLError = 200, + /** An error when interacting with CommonCrypto API */ + CommonCryptoError, + /** An error when interacting with a PKCS11 device */ + Pkcs11Error, + /** An error when interacting with a TPM device */ + TPMError, + + /** An error when interacting with zlib */ + ZlibError = 300, + /** An error when interacting with bzip2 */ + Bzip2Error, + /** An error when interacting with lzma */ + LzmaError, + +}; + +/** * Base class for all exceptions thrown by the library */ class BOTAN_PUBLIC_API(2,0) Exception : public std::exception { public: - Exception(const char* prefix, const std::string& msg); - explicit Exception(const std::string& msg); + /** + * Return a descriptive string which is hopefully comprehensible to + * a developer. It will likely not be useful for an end user. + * + * The string has no particular format, and the content of exception + * messages may change from release to release. Thus the main use of this + * function is for logging or debugging. + */ const char* what() const noexcept override { return m_msg.c_str(); } + + /** + * Return the "type" of error which occurred. + */ + virtual ErrorType error_type() const noexcept { return Botan::ErrorType::Unknown; } + + /** + * Return an error code associated with this exception, or otherwise 0. + * + * The domain of this error varies depending on the source, for example on + * POSIX systems it might be errno, while on a Windows system it might be + * the result of GetLastError or WSAGetLastError. For error_type() is + * OpenSSLError, it will (if nonzero) be an OpenSSL error code from + * ERR_get_error. + */ + virtual int error_code() const noexcept { return 0; } + protected: + explicit Exception(const std::string& msg); + Exception(const char* prefix, const std::string& msg); Exception(const std::string& msg, const std::exception& e); + private: std::string m_msg; }; /** -* An invalid argument +* An invalid argument was provided to an API call. */ class BOTAN_PUBLIC_API(2,0) Invalid_Argument : public Exception { @@ -40,95 +122,126 @@ class BOTAN_PUBLIC_API(2,0) Invalid_Argument : public Exception explicit Invalid_Argument(const std::string& msg, const std::string& where); Invalid_Argument(const std::string& msg, const std::exception& e); + + ErrorType error_type() const noexcept override { return ErrorType::InvalidArgument; } }; /** -* Unsupported_Argument Exception -* -* An argument that is invalid because it is not supported by Botan. -* It might or might not be valid in another context like a standard. +* An invalid key length was used */ -class BOTAN_PUBLIC_API(2,0) Unsupported_Argument final : public Invalid_Argument +class BOTAN_PUBLIC_API(2,0) Invalid_Key_Length final : public Invalid_Argument { public: - explicit Unsupported_Argument(const std::string& msg) : Invalid_Argument(msg) {} + Invalid_Key_Length(const std::string& name, size_t length); + ErrorType error_type() const noexcept override { return ErrorType::InvalidKeyLength; } }; /** -* Invalid_State Exception +* An invalid nonce length was used */ -class BOTAN_PUBLIC_API(2,0) Invalid_State : public Exception +class BOTAN_PUBLIC_API(2,0) Invalid_IV_Length final : public Invalid_Argument { public: - explicit Invalid_State(const std::string& err) : Exception(err) {} + Invalid_IV_Length(const std::string& mode, size_t bad_len); + ErrorType error_type() const noexcept override { return ErrorType::InvalidNonceLength; } }; -class BOTAN_PUBLIC_API(2,4) Key_Not_Set : public Invalid_State +/** +* Invalid_Algorithm_Name Exception +*/ +class BOTAN_PUBLIC_API(2,0) Invalid_Algorithm_Name final : public Invalid_Argument { public: - explicit Key_Not_Set(const std::string& algo); + explicit Invalid_Algorithm_Name(const std::string& name); }; /** -* Lookup_Error Exception +* Encoding_Error Exception +* +* This exception derives from Invalid_Argument for historical reasons, and it +* does not make any real sense for it to do so. In a future major release this +* exception type will derive directly from Exception instead. */ -class BOTAN_PUBLIC_API(2,0) Lookup_Error : public Exception +class BOTAN_PUBLIC_API(2,0) Encoding_Error final : public Invalid_Argument { public: - explicit Lookup_Error(const std::string& err) : Exception(err) {} + explicit Encoding_Error(const std::string& name); - Lookup_Error(const std::string& type, - const std::string& algo, - const std::string& provider); + ErrorType error_type() const noexcept override { return ErrorType::EncodingFailure; } }; /** -* Internal_Error Exception +* A decoding error occurred. +* +* This exception derives from Invalid_Argument for historical reasons, and it +* does not make any real sense for it to do so. In a future major release this +* exception type will derive directly from Exception instead. */ -class BOTAN_PUBLIC_API(2,0) Internal_Error : public Exception +class BOTAN_PUBLIC_API(2,0) Decoding_Error : public Invalid_Argument { public: - explicit Internal_Error(const std::string& err); + explicit Decoding_Error(const std::string& name); + + Decoding_Error(const std::string& name, const char* exception_message); + + Decoding_Error(const std::string& msg, const std::exception& e); + + ErrorType error_type() const noexcept override { return ErrorType::DecodingFailure; } }; /** -* Invalid_Key_Length Exception +* Invalid state was encountered. A request was made on an object while the +* object was in a state where the operation cannot be performed. */ -class BOTAN_PUBLIC_API(2,0) Invalid_Key_Length final : public Invalid_Argument +class BOTAN_PUBLIC_API(2,0) Invalid_State : public Exception { public: - Invalid_Key_Length(const std::string& name, size_t length); + explicit Invalid_State(const std::string& err) : Exception(err) {} + + ErrorType error_type() const noexcept override { return ErrorType::InvalidObjectState; } }; /** -* Invalid_IV_Length Exception +* A PRNG was called on to produce output while still unseeded */ -class BOTAN_PUBLIC_API(2,0) Invalid_IV_Length final : public Invalid_Argument +class BOTAN_PUBLIC_API(2,0) PRNG_Unseeded final : public Invalid_State { public: - Invalid_IV_Length(const std::string& mode, size_t bad_len); + explicit PRNG_Unseeded(const std::string& algo); }; /** -* PRNG_Unseeded Exception +* The key was not set on an object. This occurs with symmetric objects where +* an operation which requires the key is called prior to set_key being called. */ -class BOTAN_PUBLIC_API(2,0) PRNG_Unseeded final : public Invalid_State +class BOTAN_PUBLIC_API(2,4) Key_Not_Set : public Invalid_State { public: - explicit PRNG_Unseeded(const std::string& algo); + explicit Key_Not_Set(const std::string& algo); + + ErrorType error_type() const noexcept override { return ErrorType::KeyNotSet; } }; /** -* Policy_Violation Exception +* A request was made for some kind of object which could not be located */ -class BOTAN_PUBLIC_API(2,0) Policy_Violation final : public Invalid_State +class BOTAN_PUBLIC_API(2,0) Lookup_Error : public Exception { public: - BOTAN_DEPRECATED("deprecated") explicit Policy_Violation(const std::string& err); + explicit Lookup_Error(const std::string& err) : Exception(err) {} + + Lookup_Error(const std::string& type, + const std::string& algo, + const std::string& provider); + + ErrorType error_type() const noexcept override { return ErrorType::LookupError; } }; /** * Algorithm_Not_Found Exception +* +* @warning This exception type will be removed in the future. Instead +* just catch Lookup_Error. */ class BOTAN_PUBLIC_API(2,0) Algorithm_Not_Found final : public Lookup_Error { @@ -137,66 +250,98 @@ class BOTAN_PUBLIC_API(2,0) Algorithm_Not_Found final : public Lookup_Error }; /** -* No_Provider_Found Exception +* Provider_Not_Found is thrown when a specific provider was requested +* but that provider is not available. +* +* @warning This exception type will be removed in the future. Instead +* just catch Lookup_Error. */ -class BOTAN_PUBLIC_API(2,0) No_Provider_Found final : public Exception +class BOTAN_PUBLIC_API(2,0) Provider_Not_Found final : public Lookup_Error { public: - BOTAN_DEPRECATED("deprecated") explicit No_Provider_Found(const std::string& name); + Provider_Not_Found(const std::string& algo, const std::string& provider); }; /** -* Provider_Not_Found is thrown when a specific provider was requested -* but that provider is not available. +* An AEAD or MAC check detected a message modification */ -class BOTAN_PUBLIC_API(2,0) Provider_Not_Found final : public Lookup_Error +class BOTAN_PUBLIC_API(2,0) Integrity_Failure final : public Exception { public: - Provider_Not_Found(const std::string& algo, const std::string& provider); + explicit Integrity_Failure(const std::string& msg); + + ErrorType error_type() const noexcept override { return ErrorType::DecodingFailure; } }; /** -* Invalid_Algorithm_Name Exception +* An error occurred while operating on an IO stream */ -class BOTAN_PUBLIC_API(2,0) Invalid_Algorithm_Name final : public Invalid_Argument +class BOTAN_PUBLIC_API(2,0) Stream_IO_Error final : public Exception { public: - explicit Invalid_Algorithm_Name(const std::string& name); + explicit Stream_IO_Error(const std::string& err); + + ErrorType error_type() const noexcept override { return ErrorType::IoError; } }; /** -* Encoding_Error Exception +* System_Error +* +* This exception is thrown in the event of an error related to interacting +* with the operating system. +* +* This exception type also (optionally) captures an integer error code eg +* POSIX errno or Windows GetLastError. */ -class BOTAN_PUBLIC_API(2,0) Encoding_Error final : public Invalid_Argument +class BOTAN_PUBLIC_API(2,9) System_Error : public Exception { public: - explicit Encoding_Error(const std::string& name); + System_Error(const std::string& msg) : Exception(msg), m_error_code(0) {} + + System_Error(const std::string& msg, int err_code); + + ErrorType error_type() const noexcept override { return ErrorType::SystemError; } + + int error_code() const noexcept override { return m_error_code; } + + private: + int m_error_code; }; /** -* Decoding_Error Exception +* An internal error occurred. If observed, please file a bug. */ -class BOTAN_PUBLIC_API(2,0) Decoding_Error : public Invalid_Argument +class BOTAN_PUBLIC_API(2,0) Internal_Error : public Exception { public: - explicit Decoding_Error(const std::string& name); - - Decoding_Error(const std::string& name, const char* exception_message); + explicit Internal_Error(const std::string& err); - Decoding_Error(const std::string& msg, const std::exception& e); + ErrorType error_type() const noexcept override { return ErrorType::InternalError; } }; /** -* Integrity_Failure Exception +* Not Implemented Exception +* +* This is thrown in the situation where a requested operation is +* logically valid but is not implemented by this version of the library. */ -class BOTAN_PUBLIC_API(2,0) Integrity_Failure final : public Exception +class BOTAN_PUBLIC_API(2,0) Not_Implemented final : public Exception { public: - explicit Integrity_Failure(const std::string& msg); + explicit Not_Implemented(const std::string& err); + + ErrorType error_type() const noexcept override { return ErrorType::NotImplemented; } }; +/* + The following exception types are still in use for compatability reasons, + but are deprecated and will be removed in a future major release +*/ + /** -* Invalid_OID Exception +* An invalid OID string was used. +* +* This exception will be removed in a future major release. */ class BOTAN_PUBLIC_API(2,0) Invalid_OID final : public Decoding_Error { @@ -204,33 +349,58 @@ class BOTAN_PUBLIC_API(2,0) Invalid_OID final : public Decoding_Error explicit Invalid_OID(const std::string& oid); }; +/* + The following exception types are deprecated, no longer used, + and will be removed in a future major release +*/ + /** -* Stream_IO_Error Exception +* Self Test Failure Exception */ -class BOTAN_PUBLIC_API(2,0) Stream_IO_Error final : public Exception +class BOTAN_PUBLIC_API(2,0) Self_Test_Failure final : public Internal_Error { public: - explicit Stream_IO_Error(const std::string& err); + BOTAN_DEPRECATED("no longer used") explicit Self_Test_Failure(const std::string& err); }; /** -* Self Test Failure Exception +* No_Provider_Found Exception */ -class BOTAN_PUBLIC_API(2,0) Self_Test_Failure final : public Internal_Error +class BOTAN_PUBLIC_API(2,0) No_Provider_Found final : public Exception { public: - BOTAN_DEPRECATED("deprecated") explicit Self_Test_Failure(const std::string& err); + BOTAN_DEPRECATED("no longer used") explicit No_Provider_Found(const std::string& name); }; /** -* Not Implemented Exception +* Policy_Violation Exception */ -class BOTAN_PUBLIC_API(2,0) Not_Implemented final : public Exception +class BOTAN_PUBLIC_API(2,0) Policy_Violation final : public Invalid_State { public: - explicit Not_Implemented(const std::string& err); + BOTAN_DEPRECATED("no longer used") explicit Policy_Violation(const std::string& err); + }; + +/** +* Unsupported_Argument Exception +* +* An argument that is invalid because it is not supported by Botan. +* It might or might not be valid in another context like a standard. +* +* This exception is no longer used, instead Not_Implemented is thrown. +*/ +class BOTAN_PUBLIC_API(2,0) Unsupported_Argument final : public Invalid_Argument + { + public: + BOTAN_DEPRECATED("no longer used") explicit Unsupported_Argument(const std::string& msg) : Invalid_Argument(msg) {} }; +template<typename E, typename... Args> +inline void do_throw_error(const char* file, int line, const char* func, Args... args) + { + throw E(file, line, func, args...); + } + } #endif diff --git a/src/lib/utils/http_util/http_util.cpp b/src/lib/utils/http_util/http_util.cpp index f5f9c0213..3fd08b5b8 100644 --- a/src/lib/utils/http_util/http_util.cpp +++ b/src/lib/utils/http_util/http_util.cpp @@ -36,7 +36,7 @@ std::string http_transact(const std::string& hostname, { socket = OS::open_socket(hostname, "http", timeout); if(!socket) - throw Exception("No socket support enabled in build"); + throw Not_Implemented("No socket support enabled in build"); } catch(std::exception& e) { diff --git a/src/lib/utils/http_util/http_util.h b/src/lib/utils/http_util/http_util.h index 9edd3d983..92a67e42b 100644 --- a/src/lib/utils/http_util/http_util.h +++ b/src/lib/utils/http_util/http_util.h @@ -20,6 +20,20 @@ namespace Botan { namespace HTTP { +/** +* HTTP_Error Exception +*/ +class BOTAN_PUBLIC_API(2,0) HTTP_Error final : public Exception + { + public: + explicit HTTP_Error(const std::string& msg) : + Exception("HTTP error " + msg) + {} + + ErrorType error_type() const noexcept override { return ErrorType::HttpError; } + + }; + class Response final { public: @@ -44,7 +58,7 @@ class Response final void throw_unless_ok() { if(status_code() != 200) - throw Exception("HTTP error: " + status_message()); + throw HTTP_Error(status_message()); } private: @@ -54,17 +68,6 @@ class Response final std::map<std::string, std::string> m_headers; }; -/** -* HTTP_Error Exception -*/ -class BOTAN_PUBLIC_API(2,0) HTTP_Error final : public Exception - { - public: - explicit HTTP_Error(const std::string& msg) : - Exception("HTTP error " + msg) - {} - }; - BOTAN_PUBLIC_API(2,0) std::ostream& operator<<(std::ostream& o, const Response& resp); typedef std::function<std::string (const std::string&, const std::string&)> http_exch_fn; diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp index 0d98df867..ab9c73b0c 100644 --- a/src/lib/utils/os_utils.cpp +++ b/src/lib/utils/os_utils.cpp @@ -430,7 +430,7 @@ int OS::run_cpu_instruction_probe(std::function<int ()> probe_fn) int rc = ::sigaction(SIGILL, &sigaction, &old_sigaction); if(rc != 0) - throw Exception("run_cpu_instruction_probe sigaction failed"); + throw System_Error("run_cpu_instruction_probe sigaction failed", errno); rc = sigsetjmp(g_sigill_jmp_buf, /*save sigs*/1); @@ -448,7 +448,7 @@ int OS::run_cpu_instruction_probe(std::function<int ()> probe_fn) // Restore old SIGILL handler, if any rc = ::sigaction(SIGILL, &old_sigaction, nullptr); if(rc != 0) - throw Exception("run_cpu_instruction_probe sigaction restore failed"); + throw System_Error("run_cpu_instruction_probe sigaction restore failed", errno); #elif defined(BOTAN_TARGET_OS_IS_WINDOWS) && defined(BOTAN_TARGET_COMPILER_IS_MSVC) diff --git a/src/lib/utils/read_cfg.cpp b/src/lib/utils/read_cfg.cpp index bf68c0479..02f2e0ac8 100644 --- a/src/lib/utils/read_cfg.cpp +++ b/src/lib/utils/read_cfg.cpp @@ -49,7 +49,7 @@ std::map<std::string, std::string> read_cfg(std::istream& is) auto eq = s.find("="); if(eq == std::string::npos || eq == 0 || eq == s.size() - 1) - throw Exception("Bad read_cfg input '" + s + "' on line " + std::to_string(line)); + throw Decoding_Error("Bad read_cfg input '" + s + "' on line " + std::to_string(line)); const std::string key = clean_ws(s.substr(0, eq)); const std::string val = clean_ws(s.substr(eq + 1, std::string::npos)); diff --git a/src/lib/utils/safeint.h b/src/lib/utils/safeint.h index 377f13418..5c9ea4955 100644 --- a/src/lib/utils/safeint.h +++ b/src/lib/utils/safeint.h @@ -19,6 +19,8 @@ class BOTAN_PUBLIC_API(2,0) Integer_Overflow_Detected final : public Exception Integer_Overflow_Detected(const std::string& file, int line) : Exception("Integer overflow detected at " + file + ":" + std::to_string(line)) {} + + ErrorType error_type() const noexcept override { return ErrorType::InternalError; } }; inline size_t checked_add(size_t x, size_t y, const char* file, int line) diff --git a/src/lib/utils/socket/socket.cpp b/src/lib/utils/socket/socket.cpp index 39ffc7951..c9c37f2bb 100644 --- a/src/lib/utils/socket/socket.cpp +++ b/src/lib/utils/socket/socket.cpp @@ -73,7 +73,7 @@ class Asio_Socket final : public OS::Socket if(ec) throw boost::system::system_error(ec); if(ec || m_tcp.is_open() == false) - throw Exception("Connection to host " + hostname + " failed"); + throw System_Error("Connection to host " + hostname + " failed"); } void write(const uint8_t buf[], size_t len) override @@ -166,13 +166,13 @@ class BSD_Socket final : public OS::Socket if (::WSAStartup(wsa_version, &wsa_data) != 0) { - throw Exception("WSAStartup() failed: " + std::to_string(WSAGetLastError())); + throw System_Error("WSAStartup() failed", WSAGetLastError()); } if (LOBYTE(wsa_data.wVersion) != 2 || HIBYTE(wsa_data.wVersion) != 2) { ::WSACleanup(); - throw Exception("Could not find a usable version of Winsock.dll"); + throw System_Error("Could not find a usable version of Winsock.dll"); } } @@ -190,7 +190,7 @@ class BSD_Socket final : public OS::Socket static void set_nonblocking(socket_type s) { if(::fcntl(s, F_SETFL, O_NONBLOCK) < 0) - throw Exception("Setting socket to non-blocking state failed"); + throw System_Error("Setting socket to non-blocking state failed", errno); } static void socket_init() {} @@ -212,9 +212,11 @@ class BSD_Socket final : public OS::Socket hints.ai_socktype = SOCK_STREAM; addrinfo* res; - if(::getaddrinfo(hostname.c_str(), service.c_str(), &hints, &res) != 0) + int rc = ::getaddrinfo(hostname.c_str(), service.c_str(), &hints, &res); + + if(rc != 0) { - throw Exception("Name resolution failed for " + hostname); + throw System_Error("Name resolution failed for " + hostname, rc); } for(addrinfo* rp = res; (m_socket == invalid_socket()) && (rp != nullptr); rp = rp->ai_next) @@ -252,7 +254,7 @@ class BSD_Socket final : public OS::Socket socklen_t len = sizeof(socket_error); if(::getsockopt(m_socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&socket_error), &len) < 0) - throw Exception("Error calling getsockopt"); + throw System_Error("Error calling getsockopt", errno); if(socket_error != 0) { @@ -274,8 +276,8 @@ class BSD_Socket final : public OS::Socket if(m_socket == invalid_socket()) { - throw Exception("Connecting to " + hostname + - " for service " + service + " failed"); + throw System_Error("Connecting to " + hostname + + " for service " + service + " failed", errno); } } @@ -299,13 +301,12 @@ class BSD_Socket final : public OS::Socket int active = ::select(m_socket + 1, nullptr, &write_set, nullptr, &timeout); if(active == 0) - throw Exception("Timeout during socket write"); + throw System_Error("Timeout during socket write"); const size_t left = len - sent_so_far; socket_op_ret_type sent = ::send(m_socket, cast_uint8_ptr_to_char(&buf[sent_so_far]), left, 0); if(sent < 0) - throw Exception("Socket write failed with error '" + - std::string(::strerror(errno)) + "'"); + throw System_Error("Socket write failed", errno); else sent_so_far += static_cast<size_t>(sent); } @@ -321,13 +322,13 @@ class BSD_Socket final : public OS::Socket int active = ::select(m_socket + 1, &read_set, nullptr, nullptr, &timeout); if(active == 0) - throw Exception("Timeout during socket read"); + throw System_Error("Timeout during socket read"); socket_op_ret_type got = ::recv(m_socket, cast_uint8_ptr_to_char(buf), len, 0); if(got < 0) - throw Exception("Socket read failed with error '" + - std::string(::strerror(errno)) + "'"); + throw System_Error("Socket read failed", errno); + return static_cast<size_t>(got); } |