aboutsummaryrefslogtreecommitdiff
path: root/src/ssl/error.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssl/error.rs')
-rw-r--r--src/ssl/error.rs78
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");
}