aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/utils
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-11-23 18:38:14 -0500
committerJack Lloyd <[email protected]>2018-11-23 18:38:14 -0500
commit761a7f36f708b44c7af1dc9387f324d509b4acf6 (patch)
tree43ee497eb84b98c1f1e04a7e60d95b531ba0a88a /src/lib/utils
parentae42de8433260a37360d60b0a21665e13c4a63e8 (diff)
parentb909778857b3e0b7eb86ac26c818e5f25baaddbd (diff)
Merge GH #1744 Make exception throws easier to debug
Diffstat (limited to 'src/lib/utils')
-rw-r--r--src/lib/utils/assert.cpp2
-rw-r--r--src/lib/utils/dyn_load/dyn_load.cpp11
-rw-r--r--src/lib/utils/exceptn.cpp4
-rw-r--r--src/lib/utils/exceptn.h306
-rw-r--r--src/lib/utils/http_util/http_util.cpp2
-rw-r--r--src/lib/utils/http_util/http_util.h27
-rw-r--r--src/lib/utils/os_utils.cpp4
-rw-r--r--src/lib/utils/read_cfg.cpp2
-rw-r--r--src/lib/utils/safeint.h2
-rw-r--r--src/lib/utils/socket/socket.cpp31
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);
}