Fix EOF detection
See https://github.com/openssl/openssl/issues/1903 for details
This commit is contained in:
parent
ee5ad0b257
commit
898e7f02df
|
|
@ -1323,10 +1323,14 @@ impl<S: Read + Write> SslStream<S> {
|
||||||
/// value will identify if OpenSSL is waiting on read or write readiness.
|
/// value will identify if OpenSSL is waiting on read or write readiness.
|
||||||
pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
let ret = self.ssl.read(buf);
|
let ret = self.ssl.read(buf);
|
||||||
if ret >= 0 {
|
if ret > 0 {
|
||||||
Ok(ret as usize)
|
Ok(ret as usize)
|
||||||
} else {
|
} else {
|
||||||
Err(self.make_error(ret))
|
match self.make_error(ret) {
|
||||||
|
// Don't treat unexpected EOFs as errors when reading
|
||||||
|
Error::Stream(ref e) if e.kind() == io::ErrorKind::ConnectionAborted => Ok(0),
|
||||||
|
e => Err(e),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1336,7 +1340,7 @@ impl<S: Read + Write> SslStream<S> {
|
||||||
/// value will identify if OpenSSL is waiting on read or write readiness.
|
/// value will identify if OpenSSL is waiting on read or write readiness.
|
||||||
pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
|
pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
|
||||||
let ret = self.ssl.write(buf);
|
let ret = self.ssl.write(buf);
|
||||||
if ret >= 0 {
|
if ret > 0 {
|
||||||
Ok(ret as usize)
|
Ok(ret as usize)
|
||||||
} else {
|
} else {
|
||||||
Err(self.make_error(ret))
|
Err(self.make_error(ret))
|
||||||
|
|
@ -1373,19 +1377,38 @@ impl<S> SslStream<S> {
|
||||||
ffi::SSL_ERROR_SYSCALL => {
|
ffi::SSL_ERROR_SYSCALL => {
|
||||||
let errs = ErrorStack::get();
|
let errs = ErrorStack::get();
|
||||||
if errs.errors().is_empty() {
|
if errs.errors().is_empty() {
|
||||||
if ret == 0 {
|
match self.get_bio_error() {
|
||||||
Error::Stream(io::Error::new(io::ErrorKind::ConnectionAborted,
|
Some(err) => Error::Stream(err),
|
||||||
"unexpected EOF observed"))
|
None => {
|
||||||
} else {
|
Error::Stream(io::Error::new(io::ErrorKind::ConnectionAborted,
|
||||||
Error::Stream(self.get_bio_error())
|
"unexpected EOF observed"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Error::Ssl(errs)
|
Error::Ssl(errs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ffi::SSL_ERROR_ZERO_RETURN => Error::ZeroReturn,
|
ffi::SSL_ERROR_ZERO_RETURN => Error::ZeroReturn,
|
||||||
ffi::SSL_ERROR_WANT_WRITE => Error::WantWrite(self.get_bio_error()),
|
ffi::SSL_ERROR_WANT_WRITE => {
|
||||||
ffi::SSL_ERROR_WANT_READ => Error::WantRead(self.get_bio_error()),
|
let err = match self.get_bio_error() {
|
||||||
|
Some(err) => err,
|
||||||
|
None => {
|
||||||
|
io::Error::new(io::ErrorKind::Other,
|
||||||
|
"BUG: got an SSL_ERROR_WANT_WRITE with no error in the BIO")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Error::WantWrite(err)
|
||||||
|
},
|
||||||
|
ffi::SSL_ERROR_WANT_READ => {
|
||||||
|
let err = match self.get_bio_error() {
|
||||||
|
Some(err) => err,
|
||||||
|
None => {
|
||||||
|
io::Error::new(io::ErrorKind::Other,
|
||||||
|
"BUG: got an SSL_ERROR_WANT_WRITE with no error in the BIO")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Error::WantRead(err)
|
||||||
|
},
|
||||||
err => {
|
err => {
|
||||||
Error::Stream(io::Error::new(io::ErrorKind::InvalidData,
|
Error::Stream(io::Error::new(io::ErrorKind::InvalidData,
|
||||||
format!("unexpected error {}", err)))
|
format!("unexpected error {}", err)))
|
||||||
|
|
@ -1399,15 +1422,8 @@ impl<S> SslStream<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_bio_error(&mut self) -> io::Error {
|
fn get_bio_error(&mut self) -> Option<io::Error> {
|
||||||
let error = unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) };
|
unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
|
||||||
match error {
|
|
||||||
Some(error) => error,
|
|
||||||
None => {
|
|
||||||
io::Error::new(io::ErrorKind::Other,
|
|
||||||
"BUG: got an ErrorSyscall without an error in the BIO?")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to the underlying stream.
|
/// Returns a reference to the underlying stream.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue