aboutsummaryrefslogtreecommitdiff
path: root/openssl/src/ssl/error.rs
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2015-02-07 21:28:54 -0800
committerSteven Fackler <[email protected]>2015-02-07 21:30:05 -0800
commitec65b0c67b452539fded5e06cbb6ce1d165074e0 (patch)
treec50c22c2ce4ca095149c96a0f3a3b935b4012a5c /openssl/src/ssl/error.rs
parentFix deprecation warnings in openssl-sys (diff)
downloadrust-openssl-ec65b0c67b452539fded5e06cbb6ce1d165074e0.tar.xz
rust-openssl-ec65b0c67b452539fded5e06cbb6ce1d165074e0.zip
Move docs to this repo and auto build
Diffstat (limited to 'openssl/src/ssl/error.rs')
-rw-r--r--openssl/src/ssl/error.rs122
1 files changed, 122 insertions, 0 deletions
diff --git a/openssl/src/ssl/error.rs b/openssl/src/ssl/error.rs
new file mode 100644
index 00000000..027554c5
--- /dev/null
+++ b/openssl/src/ssl/error.rs
@@ -0,0 +1,122 @@
+pub use self::SslError::*;
+pub use self::OpensslError::*;
+
+use libc::c_ulong;
+use std::error;
+use std::fmt;
+use std::ffi::c_str_to_bytes;
+use std::old_io::IoError;
+
+use ffi;
+
+/// An SSL error
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum SslError {
+ /// The underlying stream reported an error
+ StreamError(IoError),
+ /// The SSL session has been closed by the other end
+ SslSessionClosed,
+ /// An error in the OpenSSL library
+ OpenSslErrors(Vec<OpensslError>)
+}
+
+impl fmt::Display for SslError {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.write_str(error::Error::description(self))
+ }
+}
+
+impl error::Error for SslError {
+ fn description(&self) -> &str {
+ match *self {
+ StreamError(_) => "The underlying stream reported an error",
+ SslSessionClosed => "The SSL session has been closed by the other end",
+ OpenSslErrors(_) => "An error in the OpenSSL library",
+ }
+ }
+
+ fn cause(&self) -> Option<&error::Error> {
+ match *self {
+ StreamError(ref err) => Some(err as &error::Error),
+ _ => None
+ }
+ }
+}
+
+/// An error from the OpenSSL library
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum OpensslError {
+ /// An unknown error
+ UnknownError {
+ /// The library reporting the error
+ library: String,
+ /// The function reporting the error
+ function: String,
+ /// The reason for the error
+ reason: String
+ }
+}
+
+fn get_lib(err: c_ulong) -> String {
+ unsafe {
+ let bytes = c_str_to_bytes(&ffi::ERR_lib_error_string(err)).to_vec();
+ String::from_utf8(bytes).unwrap()
+ }
+}
+
+fn get_func(err: c_ulong) -> String {
+ unsafe {
+ let bytes = c_str_to_bytes(&ffi::ERR_func_error_string(err)).to_vec();
+ String::from_utf8(bytes).unwrap()
+ }
+}
+
+fn get_reason(err: c_ulong) -> String {
+ unsafe {
+ let bytes = c_str_to_bytes(&ffi::ERR_reason_error_string(err)).to_vec();
+ String::from_utf8(bytes).unwrap()
+ }
+}
+
+impl SslError {
+ /// Creates a new `OpenSslErrors` with the current contents of the error
+ /// stack.
+ pub fn get() -> SslError {
+ let mut errs = vec!();
+ loop {
+ match unsafe { ffi::ERR_get_error() } {
+ 0 => break,
+ err => errs.push(SslError::from_error_code(err))
+ }
+ }
+ OpenSslErrors(errs)
+ }
+
+ /// Creates an `SslError` from the raw numeric error code.
+ pub fn from_error(err: c_ulong) -> SslError {
+ OpenSslErrors(vec![SslError::from_error_code(err)])
+ }
+
+ fn from_error_code(err: c_ulong) -> OpensslError {
+ ffi::init();
+ UnknownError {
+ library: get_lib(err),
+ function: get_func(err),
+ reason: get_reason(err)
+ }
+ }
+}
+
+#[test]
+fn test_uknown_error_should_have_correct_messages() {
+ let errs = match SslError::from_error(336032784) {
+ OpenSslErrors(errs) => errs,
+ _ => panic!("This should always be an `OpenSslErrors` variant.")
+ };
+
+ let UnknownError { ref library, ref function, ref reason } = errs[0];
+
+ assert_eq!(library.as_slice(), "SSL routines");
+ assert_eq!(function.as_slice(), "SSL23_GET_SERVER_HELLO");
+ assert_eq!(reason.as_slice(), "sslv3 alert handshake failure");
+}