diff options
| author | Chris Cole <[email protected]> | 2014-11-29 19:47:09 -0500 |
|---|---|---|
| committer | Chris Cole <[email protected]> | 2014-11-29 19:47:09 -0500 |
| commit | 5f76f1cb62c70af4bbf064ea5c27c69544f04cea (patch) | |
| tree | 6c90d43f6bfdf1b2b83094c1bfc559bfbdecf554 /src/ssl/error.rs | |
| parent | Added mod_mul. (diff) | |
| parent | Make SslStream Cloneable (diff) | |
| download | rust-openssl-5f76f1cb62c70af4bbf064ea5c27c69544f04cea.tar.xz rust-openssl-5f76f1cb62c70af4bbf064ea5c27c69544f04cea.zip | |
Merge remote-tracking branch 'upstream/master'
Conflicts:
src/bn/mod.rs
Diffstat (limited to 'src/ssl/error.rs')
| -rw-r--r-- | src/ssl/error.rs | 78 |
1 files changed, 62 insertions, 16 deletions
diff --git a/src/ssl/error.rs b/src/ssl/error.rs index 9af14dd9..7e8daef1 100644 --- a/src/ssl/error.rs +++ b/src/ssl/error.rs @@ -1,12 +1,17 @@ +pub use self::SslError::*; +pub use self::OpensslError::*; + use libc::c_ulong; +use std::error; use std::io::IoError; +use std::c_str::CString; -use ssl::ffi; +use ffi; /// An SSL error #[deriving(Show, Clone, PartialEq, Eq)] pub enum SslError { - /// The underlying stream has reported an error + /// The underlying stream reported an error StreamError(IoError), /// The SSL session has been closed by the other end SslSessionClosed, @@ -14,30 +19,47 @@ pub enum SslError { OpenSslErrors(Vec<OpensslError>) } +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 #[deriving(Show, Clone, PartialEq, Eq)] pub enum OpensslError { /// An unknown error UnknownError { /// The library reporting the error - library: u8, + library: String, /// The function reporting the error - function: u16, + function: String, /// The reason for the error - reason: u16 + reason: String } } -fn get_lib(err: c_ulong) -> u8 { - ((err >> 24) & 0xff) as u8 +fn get_lib(err: c_ulong) -> String { + unsafe { CString::new(ffi::ERR_lib_error_string(err), false) }.to_string() } -fn get_func(err: c_ulong) -> u16 { - ((err >> 12) & 0xfff) as u16 +fn get_func(err: c_ulong) -> String { + unsafe { CString::new(ffi::ERR_func_error_string(err), false).to_string() } } -fn get_reason(err: c_ulong) -> u16 { - (err & 0xfff) as u16 +fn get_reason(err: c_ulong) -> String { + unsafe { CString::new(ffi::ERR_reason_error_string(err), false).to_string() } } impl SslError { @@ -48,13 +70,37 @@ impl SslError { loop { match unsafe { ffi::ERR_get_error() } { 0 => break, - err => errs.push(UnknownError { - library: get_lib(err), - function: get_func(err), - reason: get_reason(err) - }) + 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"); } |