Merge pull request #506 from hyperium/error-ssl
feat(error): add Ssl variant to hyper::Error
This commit is contained in:
@@ -79,7 +79,7 @@ struct MockConnector;
|
|||||||
|
|
||||||
impl net::NetworkConnector for MockConnector {
|
impl net::NetworkConnector for MockConnector {
|
||||||
type Stream = MockStream;
|
type Stream = MockStream;
|
||||||
fn connect(&mut self, _: &str, _: u16, _: &str) -> io::Result<MockStream> {
|
fn connect(&mut self, _: &str, _: u16, _: &str) -> hyper::Result<MockStream> {
|
||||||
Ok(MockStream::new())
|
Ok(MockStream::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ impl<C: NetworkConnector<Stream=S> + Send, S: NetworkStream + Send> NetworkConne
|
|||||||
type Stream = Box<NetworkStream + Send>;
|
type Stream = Box<NetworkStream + Send>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn connect(&mut self, host: &str, port: u16, scheme: &str)
|
fn connect(&mut self, host: &str, port: u16, scheme: &str)
|
||||||
-> io::Result<Box<NetworkStream + Send>> {
|
-> ::Result<Box<NetworkStream + Send>> {
|
||||||
Ok(try!(self.0.connect(host, port, scheme)).into())
|
Ok(try!(self.0.connect(host, port, scheme)).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,7 +155,7 @@ impl NetworkConnector for Connector {
|
|||||||
type Stream = Box<NetworkStream + Send>;
|
type Stream = Box<NetworkStream + Send>;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn connect(&mut self, host: &str, port: u16, scheme: &str)
|
fn connect(&mut self, host: &str, port: u16, scheme: &str)
|
||||||
-> io::Result<Box<NetworkStream + Send>> {
|
-> ::Result<Box<NetworkStream + Send>> {
|
||||||
Ok(try!(self.0.connect(host, port, scheme)).into())
|
Ok(try!(self.0.connect(host, port, scheme)).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ impl<S> PoolImpl<S> {
|
|||||||
|
|
||||||
impl<C: NetworkConnector<Stream=S>, S: NetworkStream + Send> NetworkConnector for Pool<C> {
|
impl<C: NetworkConnector<Stream=S>, S: NetworkStream + Send> NetworkConnector for Pool<C> {
|
||||||
type Stream = PooledStream<S>;
|
type Stream = PooledStream<S>;
|
||||||
fn connect(&mut self, host: &str, port: u16, scheme: &str) -> io::Result<PooledStream<S>> {
|
fn connect(&mut self, host: &str, port: u16, scheme: &str) -> ::Result<PooledStream<S>> {
|
||||||
let key = key(host, port, scheme);
|
let key = key(host, port, scheme);
|
||||||
let mut locked = self.inner.lock().unwrap();
|
let mut locked = self.inner.lock().unwrap();
|
||||||
let mut should_remove = false;
|
let mut should_remove = false;
|
||||||
|
|||||||
31
src/error.rs
31
src/error.rs
@@ -4,11 +4,19 @@ use std::fmt;
|
|||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
|
|
||||||
use httparse;
|
use httparse;
|
||||||
|
use openssl::ssl::error::SslError;
|
||||||
use url;
|
use url;
|
||||||
|
|
||||||
use self::Error::{Method, Uri, Version,
|
use self::Error::{
|
||||||
Header, Status, Io,
|
Method,
|
||||||
TooLarge};
|
Uri,
|
||||||
|
Version,
|
||||||
|
Header,
|
||||||
|
Status,
|
||||||
|
Io,
|
||||||
|
Ssl,
|
||||||
|
TooLarge
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Result type often returned from methods that can have hyper `Error`s.
|
/// Result type often returned from methods that can have hyper `Error`s.
|
||||||
@@ -29,8 +37,10 @@ pub enum Error {
|
|||||||
TooLarge,
|
TooLarge,
|
||||||
/// An invalid `Status`, such as `1337 ELITE`.
|
/// An invalid `Status`, such as `1337 ELITE`.
|
||||||
Status,
|
Status,
|
||||||
/// An `IoError` that occurred while trying to read or write to a network stream.
|
/// An `io::Error` that occurred while trying to read or write to a network stream.
|
||||||
Io(IoError),
|
Io(IoError),
|
||||||
|
/// An error from the `openssl` library.
|
||||||
|
Ssl(SslError)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
@@ -48,13 +58,15 @@ impl StdError for Error {
|
|||||||
Header => "Invalid Header provided",
|
Header => "Invalid Header provided",
|
||||||
TooLarge => "Message head is too large",
|
TooLarge => "Message head is too large",
|
||||||
Status => "Invalid Status provided",
|
Status => "Invalid Status provided",
|
||||||
Io(_) => "An IoError occurred while connecting to the specified network",
|
Io(ref e) => e.description(),
|
||||||
|
Ssl(ref e) => e.description(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cause(&self) -> Option<&StdError> {
|
fn cause(&self) -> Option<&StdError> {
|
||||||
match *self {
|
match *self {
|
||||||
Io(ref error) => Some(error),
|
Io(ref error) => Some(error),
|
||||||
|
Ssl(ref error) => Some(error),
|
||||||
Uri(ref error) => Some(error),
|
Uri(ref error) => Some(error),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@@ -73,6 +85,15 @@ impl From<url::ParseError> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<SslError> for Error {
|
||||||
|
fn from(err: SslError) -> Error {
|
||||||
|
match err {
|
||||||
|
SslError::StreamError(err) => Io(err),
|
||||||
|
err => Ssl(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<httparse::Error> for Error {
|
impl From<httparse::Error> for Error {
|
||||||
fn from(err: httparse::Error) -> Error {
|
fn from(err: httparse::Error) -> Error {
|
||||||
match err {
|
match err {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ pub struct MockConnector;
|
|||||||
impl NetworkConnector for MockConnector {
|
impl NetworkConnector for MockConnector {
|
||||||
type Stream = MockStream;
|
type Stream = MockStream;
|
||||||
|
|
||||||
fn connect(&mut self, _host: &str, _port: u16, _scheme: &str) -> io::Result<MockStream> {
|
fn connect(&mut self, _host: &str, _port: u16, _scheme: &str) -> ::Result<MockStream> {
|
||||||
Ok(MockStream::new())
|
Ok(MockStream::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ macro_rules! mock_connector (
|
|||||||
|
|
||||||
impl ::net::NetworkConnector for $name {
|
impl ::net::NetworkConnector for $name {
|
||||||
type Stream = ::mock::MockStream;
|
type Stream = ::mock::MockStream;
|
||||||
fn connect(&mut self, host: &str, port: u16, scheme: &str) -> ::std::io::Result<::mock::MockStream> {
|
fn connect(&mut self, host: &str, port: u16, scheme: &str) -> $crate::Result<::mock::MockStream> {
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
debug!("MockStream::connect({:?}, {:?}, {:?})", host, port, scheme);
|
debug!("MockStream::connect({:?}, {:?}, {:?})", host, port, scheme);
|
||||||
@@ -99,7 +99,7 @@ macro_rules! mock_connector (
|
|||||||
let key = format!("{}://{}", scheme, host);
|
let key = format!("{}://{}", scheme, host);
|
||||||
// ignore port for now
|
// ignore port for now
|
||||||
match map.get(&*key) {
|
match map.get(&*key) {
|
||||||
Some(res) => Ok(::mock::MockStream {
|
Some(res) => Ok($crate::mock::MockStream {
|
||||||
write: vec![],
|
write: vec![],
|
||||||
read: Cursor::new(res.to_string().into_bytes()),
|
read: Cursor::new(res.to_string().into_bytes()),
|
||||||
}),
|
}),
|
||||||
|
|||||||
66
src/net.rs
66
src/net.rs
@@ -9,7 +9,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use openssl::ssl::{Ssl, SslStream, SslContext, SSL_VERIFY_NONE};
|
use openssl::ssl::{Ssl, SslStream, SslContext, SSL_VERIFY_NONE};
|
||||||
use openssl::ssl::SslMethod::Sslv23;
|
use openssl::ssl::SslMethod::Sslv23;
|
||||||
use openssl::ssl::error::{SslError, StreamError, OpenSslErrors, SslSessionClosed};
|
use openssl::ssl::error::StreamError as SslIoError;
|
||||||
use openssl::x509::X509FileType;
|
use openssl::x509::X509FileType;
|
||||||
|
|
||||||
use typeable::Typeable;
|
use typeable::Typeable;
|
||||||
@@ -29,7 +29,7 @@ pub trait NetworkListener: Clone {
|
|||||||
//fn listen<To: ToSocketAddrs>(&mut self, addr: To) -> io::Result<Self::Acceptor>;
|
//fn listen<To: ToSocketAddrs>(&mut self, addr: To) -> io::Result<Self::Acceptor>;
|
||||||
|
|
||||||
/// Returns an iterator of streams.
|
/// Returns an iterator of streams.
|
||||||
fn accept(&mut self) -> io::Result<Self::Stream>;
|
fn accept(&mut self) -> ::Result<Self::Stream>;
|
||||||
|
|
||||||
/// Get the address this Listener ended up listening on.
|
/// Get the address this Listener ended up listening on.
|
||||||
fn local_addr(&mut self) -> io::Result<SocketAddr>;
|
fn local_addr(&mut self) -> io::Result<SocketAddr>;
|
||||||
@@ -47,8 +47,8 @@ pub trait NetworkListener: Clone {
|
|||||||
pub struct NetworkConnections<'a, N: NetworkListener + 'a>(&'a mut N);
|
pub struct NetworkConnections<'a, N: NetworkListener + 'a>(&'a mut N);
|
||||||
|
|
||||||
impl<'a, N: NetworkListener + 'a> Iterator for NetworkConnections<'a, N> {
|
impl<'a, N: NetworkListener + 'a> Iterator for NetworkConnections<'a, N> {
|
||||||
type Item = io::Result<N::Stream>;
|
type Item = ::Result<N::Stream>;
|
||||||
fn next(&mut self) -> Option<io::Result<N::Stream>> {
|
fn next(&mut self) -> Option<::Result<N::Stream>> {
|
||||||
Some(self.0.accept())
|
Some(self.0.accept())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,6 +58,7 @@ pub trait NetworkStream: Read + Write + Any + Send + Typeable {
|
|||||||
/// Get the remote address of the underlying connection.
|
/// Get the remote address of the underlying connection.
|
||||||
fn peer_addr(&mut self) -> io::Result<SocketAddr>;
|
fn peer_addr(&mut self) -> io::Result<SocketAddr>;
|
||||||
/// This will be called when Stream should no longer be kept alive.
|
/// This will be called when Stream should no longer be kept alive.
|
||||||
|
#[inline]
|
||||||
fn close(&mut self, _how: Shutdown) -> io::Result<()> {
|
fn close(&mut self, _how: Shutdown) -> io::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -68,7 +69,7 @@ pub trait NetworkConnector {
|
|||||||
/// Type of Stream to create
|
/// Type of Stream to create
|
||||||
type Stream: Into<Box<NetworkStream + Send>>;
|
type Stream: Into<Box<NetworkStream + Send>>;
|
||||||
/// Connect to a remote address.
|
/// Connect to a remote address.
|
||||||
fn connect(&mut self, host: &str, port: u16, scheme: &str) -> io::Result<Self::Stream>;
|
fn connect(&mut self, host: &str, port: u16, scheme: &str) -> ::Result<Self::Stream>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: NetworkStream + Send> From<T> for Box<NetworkStream + Send> {
|
impl<T: NetworkStream + Send> From<T> for Box<NetworkStream + Send> {
|
||||||
@@ -158,22 +159,22 @@ impl Clone for HttpListener {
|
|||||||
impl HttpListener {
|
impl HttpListener {
|
||||||
|
|
||||||
/// Start listening to an address over HTTP.
|
/// Start listening to an address over HTTP.
|
||||||
pub fn http<To: ToSocketAddrs>(addr: To) -> io::Result<HttpListener> {
|
pub fn http<To: ToSocketAddrs>(addr: To) -> ::Result<HttpListener> {
|
||||||
Ok(HttpListener::Http(try!(TcpListener::bind(addr))))
|
Ok(HttpListener::Http(try!(TcpListener::bind(addr))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start listening to an address over HTTPS.
|
/// Start listening to an address over HTTPS.
|
||||||
pub fn https<To: ToSocketAddrs>(addr: To, cert: &Path, key: &Path) -> io::Result<HttpListener> {
|
pub fn https<To: ToSocketAddrs>(addr: To, cert: &Path, key: &Path) -> ::Result<HttpListener> {
|
||||||
let mut ssl_context = try!(SslContext::new(Sslv23).map_err(lift_ssl_error));
|
let mut ssl_context = try!(SslContext::new(Sslv23));
|
||||||
try!(ssl_context.set_cipher_list("DEFAULT").map_err(lift_ssl_error));
|
try!(ssl_context.set_cipher_list("DEFAULT"));
|
||||||
try!(ssl_context.set_certificate_file(cert, X509FileType::PEM).map_err(lift_ssl_error));
|
try!(ssl_context.set_certificate_file(cert, X509FileType::PEM));
|
||||||
try!(ssl_context.set_private_key_file(key, X509FileType::PEM).map_err(lift_ssl_error));
|
try!(ssl_context.set_private_key_file(key, X509FileType::PEM));
|
||||||
ssl_context.set_verify(SSL_VERIFY_NONE, None);
|
ssl_context.set_verify(SSL_VERIFY_NONE, None);
|
||||||
HttpListener::https_with_context(addr, ssl_context)
|
HttpListener::https_with_context(addr, ssl_context)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start listening to an address of HTTPS using the given SslContext
|
/// Start listening to an address of HTTPS using the given SslContext
|
||||||
pub fn https_with_context<To: ToSocketAddrs>(addr: To, ssl_context: SslContext) -> io::Result<HttpListener> {
|
pub fn https_with_context<To: ToSocketAddrs>(addr: To, ssl_context: SslContext) -> ::Result<HttpListener> {
|
||||||
Ok(HttpListener::Https(try!(TcpListener::bind(addr)), Arc::new(ssl_context)))
|
Ok(HttpListener::Https(try!(TcpListener::bind(addr)), Arc::new(ssl_context)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,21 +183,20 @@ impl NetworkListener for HttpListener {
|
|||||||
type Stream = HttpStream;
|
type Stream = HttpStream;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn accept(&mut self) -> io::Result<HttpStream> {
|
fn accept(&mut self) -> ::Result<HttpStream> {
|
||||||
Ok(match *self {
|
match *self {
|
||||||
HttpListener::Http(ref mut tcp) => HttpStream::Http(CloneTcpStream(try!(tcp.accept()).0)),
|
HttpListener::Http(ref mut tcp) => Ok(HttpStream::Http(CloneTcpStream(try!(tcp.accept()).0))),
|
||||||
HttpListener::Https(ref mut tcp, ref ssl_context) => {
|
HttpListener::Https(ref mut tcp, ref ssl_context) => {
|
||||||
let stream = CloneTcpStream(try!(tcp.accept()).0);
|
let stream = CloneTcpStream(try!(tcp.accept()).0);
|
||||||
match SslStream::new_server(&**ssl_context, stream) {
|
match SslStream::new_server(&**ssl_context, stream) {
|
||||||
Ok(ssl_stream) => HttpStream::Https(ssl_stream),
|
Ok(ssl_stream) => Ok(HttpStream::Https(ssl_stream)),
|
||||||
Err(StreamError(e)) => {
|
Err(SslIoError(e)) => {
|
||||||
return Err(io::Error::new(io::ErrorKind::ConnectionAborted,
|
Err(io::Error::new(io::ErrorKind::ConnectionAborted, e).into())
|
||||||
e));
|
|
||||||
},
|
},
|
||||||
Err(e) => return Err(lift_ssl_error(e))
|
Err(e) => Err(e.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -308,9 +308,9 @@ pub type ContextVerifier = Box<FnMut(&mut SslContext) -> () + Send>;
|
|||||||
impl NetworkConnector for HttpConnector {
|
impl NetworkConnector for HttpConnector {
|
||||||
type Stream = HttpStream;
|
type Stream = HttpStream;
|
||||||
|
|
||||||
fn connect(&mut self, host: &str, port: u16, scheme: &str) -> io::Result<HttpStream> {
|
fn connect(&mut self, host: &str, port: u16, scheme: &str) -> ::Result<HttpStream> {
|
||||||
let addr = &(host, port);
|
let addr = &(host, port);
|
||||||
match scheme {
|
Ok(try!(match scheme {
|
||||||
"http" => {
|
"http" => {
|
||||||
debug!("http scheme");
|
debug!("http scheme");
|
||||||
Ok(HttpStream::Http(CloneTcpStream(try!(TcpStream::connect(addr)))))
|
Ok(HttpStream::Http(CloneTcpStream(try!(TcpStream::connect(addr)))))
|
||||||
@@ -318,30 +318,20 @@ impl NetworkConnector for HttpConnector {
|
|||||||
"https" => {
|
"https" => {
|
||||||
debug!("https scheme");
|
debug!("https scheme");
|
||||||
let stream = CloneTcpStream(try!(TcpStream::connect(addr)));
|
let stream = CloneTcpStream(try!(TcpStream::connect(addr)));
|
||||||
let mut context = try!(SslContext::new(Sslv23).map_err(lift_ssl_error));
|
let mut context = try!(SslContext::new(Sslv23));
|
||||||
if let Some(ref mut verifier) = self.0 {
|
if let Some(ref mut verifier) = self.0 {
|
||||||
verifier(&mut context);
|
verifier(&mut context);
|
||||||
}
|
}
|
||||||
let ssl = try!(Ssl::new(&context).map_err(lift_ssl_error));
|
let ssl = try!(Ssl::new(&context));
|
||||||
try!(ssl.set_hostname(host).map_err(lift_ssl_error));
|
try!(ssl.set_hostname(host));
|
||||||
let stream = try!(SslStream::new(&context, stream).map_err(lift_ssl_error));
|
let stream = try!(SslStream::new(&context, stream));
|
||||||
Ok(HttpStream::Https(stream))
|
Ok(HttpStream::Https(stream))
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
Err(io::Error::new(io::ErrorKind::InvalidInput,
|
Err(io::Error::new(io::ErrorKind::InvalidInput,
|
||||||
"Invalid scheme for Http"))
|
"Invalid scheme for Http"))
|
||||||
}
|
}
|
||||||
}
|
}))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lift_ssl_error(ssl: SslError) -> io::Error {
|
|
||||||
debug!("lift_ssl_error: {:?}", ssl);
|
|
||||||
match ssl {
|
|
||||||
StreamError(err) => err,
|
|
||||||
SslSessionClosed => io::Error::new(io::ErrorKind::ConnectionAborted,
|
|
||||||
"SSL Connection Closed"),
|
|
||||||
e@OpenSslErrors(..) => io::Error::new(io::ErrorKind::Other, e)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user