aboutsummaryrefslogtreecommitdiff
path: root/openssl/src/ssl/error.rs
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2015-12-15 19:42:12 -0800
committerSteven Fackler <[email protected]>2015-12-15 19:42:12 -0800
commitcf075d8e6b7f5849a40659f380a660dc226a9118 (patch)
tree630ed9e2a3fcd047fd95a778977585803cd5a94a /openssl/src/ssl/error.rs
parentMerge branch 'release-v0.7.1' into release (diff)
parentRelease v0.7.2 (diff)
downloadrust-openssl-0.7.2.tar.xz
rust-openssl-0.7.2.zip
Merge branch 'release-v0.7.2' into releasev0.7.2
Diffstat (limited to 'openssl/src/ssl/error.rs')
-rw-r--r--openssl/src/ssl/error.rs174
1 files changed, 154 insertions, 20 deletions
diff --git a/openssl/src/ssl/error.rs b/openssl/src/ssl/error.rs
index 0126b277..126747d8 100644
--- a/openssl/src/ssl/error.rs
+++ b/openssl/src/ssl/error.rs
@@ -3,12 +3,141 @@ pub use self::OpensslError::*;
use libc::c_ulong;
use std::error;
+use std::error::Error as StdError;
use std::fmt;
use std::ffi::CStr;
use std::io;
+use std::str;
use ffi;
+/// An SSL error.
+#[derive(Debug)]
+pub enum Error {
+ /// The SSL session has been closed by the other end
+ ZeroReturn,
+ /// An attempt to read data from the underlying socket returned
+ /// `WouldBlock`. Wait for read readiness and reattempt the operation.
+ WantRead(io::Error),
+ /// An attempt to write data from the underlying socket returned
+ /// `WouldBlock`. Wait for write readiness and reattempt the operation.
+ WantWrite(io::Error),
+ /// The client certificate callback requested to be called again.
+ WantX509Lookup,
+ /// An error reported by the underlying stream.
+ Stream(io::Error),
+ /// An error in the OpenSSL library.
+ Ssl(Vec<OpenSslError>),
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ try!(fmt.write_str(self.description()));
+ match *self {
+ Error::Stream(ref err) => write!(fmt, ": {}", err),
+ Error::WantRead(ref err) => write!(fmt, ": {}", err),
+ Error::WantWrite(ref err) => write!(fmt, ": {}", err),
+ Error::Ssl(ref errs) => {
+ let mut first = true;
+ for err in errs {
+ if first {
+ try!(fmt.write_str(": "));
+ first = false;
+ } else {
+ try!(fmt.write_str(", "));
+ }
+ try!(fmt.write_str(&err.reason()))
+ }
+ Ok(())
+ }
+ _ => Ok(())
+ }
+ }
+}
+
+impl error::Error for Error {
+ fn description(&self) -> &str {
+ match *self {
+ Error::ZeroReturn => "The SSL session was closed by the other end",
+ Error::WantRead(_) => "A read attempt returned a `WouldBlock` error",
+ Error::WantWrite(_) => "A write attempt returned a `WouldBlock` error",
+ Error::WantX509Lookup => "The client certificate callback requested to be called again",
+ Error::Stream(_) => "The underlying stream reported an error",
+ Error::Ssl(_) => "The OpenSSL library reported an error",
+ }
+ }
+
+ fn cause(&self) -> Option<&error::Error> {
+ match *self {
+ Error::WantRead(ref err) => Some(err),
+ Error::WantWrite(ref err) => Some(err),
+ Error::Stream(ref err) => Some(err),
+ _ => None
+ }
+ }
+}
+
+/// An error reported from OpenSSL.
+pub struct OpenSslError(c_ulong);
+
+impl OpenSslError {
+ /// Returns the contents of the OpenSSL error stack.
+ pub fn get_stack() -> Vec<OpenSslError> {
+ ffi::init();
+
+ let mut errs = vec!();
+ loop {
+ match unsafe { ffi::ERR_get_error() } {
+ 0 => break,
+ err => errs.push(OpenSslError(err))
+ }
+ }
+ errs
+ }
+
+ /// Returns the raw OpenSSL error code for this error.
+ pub fn error_code(&self) -> c_ulong {
+ self.0
+ }
+
+ /// Returns the name of the library reporting the error.
+ pub fn library(&self) -> &'static str {
+ get_lib(self.0)
+ }
+
+ /// Returns the name of the function reporting the error.
+ pub fn function(&self) -> &'static str {
+ get_func(self.0)
+ }
+
+ /// Returns the reason for the error.
+ pub fn reason(&self) -> &'static str {
+ get_reason(self.0)
+ }
+}
+
+impl fmt::Debug for OpenSslError {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("OpenSslError")
+ .field("library", &self.library())
+ .field("function", &self.function())
+ .field("reason", &self.reason())
+ .finish()
+ }
+}
+
+impl fmt::Display for OpenSslError {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.write_str(&self.reason())
+ }
+}
+
+impl error::Error for OpenSslError {
+ fn description(&self) -> &str {
+ "An OpenSSL error"
+ }
+}
+
/// An SSL error
#[derive(Debug)]
pub enum SslError {
@@ -115,24 +244,38 @@ pub enum OpensslError {
}
}
-fn get_lib(err: c_ulong) -> String {
+impl OpensslError {
+ pub fn from_error_code(err: c_ulong) -> OpensslError {
+ ffi::init();
+ UnknownError {
+ library: get_lib(err).to_owned(),
+ function: get_func(err).to_owned(),
+ reason: get_reason(err).to_owned()
+ }
+ }
+}
+
+fn get_lib(err: c_ulong) -> &'static str {
unsafe {
- let bytes = CStr::from_ptr(ffi::ERR_lib_error_string(err)).to_bytes().to_vec();
- String::from_utf8(bytes).unwrap()
+ let cstr = ffi::ERR_lib_error_string(err);
+ let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
+ str::from_utf8(bytes).unwrap()
}
}
-fn get_func(err: c_ulong) -> String {
+fn get_func(err: c_ulong) -> &'static str {
unsafe {
- let bytes = CStr::from_ptr(ffi::ERR_func_error_string(err)).to_bytes().to_vec();
- String::from_utf8(bytes).unwrap()
+ let cstr = ffi::ERR_func_error_string(err);
+ let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
+ str::from_utf8(bytes).unwrap()
}
}
-fn get_reason(err: c_ulong) -> String {
+fn get_reason(err: c_ulong) -> &'static str {
unsafe {
- let bytes = CStr::from_ptr(ffi::ERR_reason_error_string(err)).to_bytes().to_vec();
- String::from_utf8(bytes).unwrap()
+ let cstr = ffi::ERR_reason_error_string(err);
+ let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
+ str::from_utf8(bytes).unwrap()
}
}
@@ -144,7 +287,7 @@ impl SslError {
loop {
match unsafe { ffi::ERR_get_error() } {
0 => break,
- err => errs.push(SslError::from_error_code(err))
+ err => errs.push(OpensslError::from_error_code(err))
}
}
OpenSslErrors(errs)
@@ -152,16 +295,7 @@ impl SslError {
/// 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)
- }
+ OpenSslErrors(vec![OpensslError::from_error_code(err)])
}
}