From c8d23f37a40afbb7ccb768241e429a51f94b8e7a Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 25 Jun 2015 22:47:53 -0700 Subject: [PATCH] Fix EOF handling in retry wrapper --- openssl-sys/src/lib.rs | 5 +++++ openssl/src/bio/mod.rs | 6 ++++++ openssl/src/ssl/mod.rs | 10 ++++++---- openssl/src/ssl/tests.rs | 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index a1817803..8437a80f 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -116,6 +116,7 @@ pub type PasswordCallback = extern "C" fn(buf: *mut c_char, size: c_int, -> c_int; pub const BIO_CTRL_EOF: c_int = 2; +pub const BIO_C_SET_BUF_MEM_EOF_RETURN: c_int = 130; pub const CRYPTO_LOCK: c_int = 1; @@ -271,6 +272,10 @@ pub unsafe fn SSL_CTX_set_options(ssl: *mut SSL_CTX, op: c_long) -> c_long { SSL_CTX_ctrl(ssl, SSL_CTRL_OPTIONS, op, ptr::null_mut()) } +pub unsafe fn BIO_set_mem_eof_return(b: *mut BIO, v: c_int) { + BIO_ctrl(b, BIO_C_SET_BUF_MEM_EOF_RETURN, v as c_long, ptr::null_mut()); +} + pub unsafe fn SSL_CTX_get_options(ssl: *mut SSL_CTX) -> c_long { SSL_CTX_ctrl(ssl, SSL_CTRL_OPTIONS, 0, ptr::null_mut()) } diff --git a/openssl/src/bio/mod.rs b/openssl/src/bio/mod.rs index ad2f65c2..e81694a4 100644 --- a/openssl/src/bio/mod.rs +++ b/openssl/src/bio/mod.rs @@ -56,6 +56,12 @@ impl MemBio { pub unsafe fn get_handle(&self) -> *mut ffi::BIO { self.bio } + + /// Sets the BIO's EOF state. + pub fn set_eof(&self, eof: bool) { + let v = if eof { 0 } else { -1 }; + unsafe { ffi::BIO_set_mem_eof_return(self.bio, v); } + } } impl Read for MemBio { diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 98611064..a0f97b17 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -758,7 +758,7 @@ pub struct SslStream { impl SslStream { /// Create a new independently owned handle to the underlying socket. pub fn try_clone(&self) -> io::Result> { - Ok(SslStream { + Ok(SslStream { stream: try!(self.stream.try_clone()), ssl: self.ssl.clone(), buf: self.buf.clone(), @@ -851,14 +851,16 @@ impl SslStream { try_ssl_stream!(self.flush()); let len = try_ssl_stream!(self.stream.read(&mut self.buf[..])); if len == 0 { - return Ok(0); + self.ssl.get_rbio().set_eof(true); + } else { + try_ssl_stream!(self.ssl.get_rbio().write_all(&self.buf[..len])); } - try_ssl_stream!(self.ssl.get_rbio().write_all(&self.buf[..len])); } LibSslError::ErrorWantWrite => { try_ssl_stream!(self.flush()) } LibSslError::ErrorZeroReturn => return Err(SslSessionClosed), LibSslError::ErrorSsl => return Err(SslError::get()), - err => panic!("unexpected error {:?}", err), + LibSslError::ErrorSyscall if ret == 0 => return Ok(0), + err => panic!("unexpected error {:?} with ret {}", err, ret), } } } diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index ec4f2b01..028d9f09 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -369,7 +369,7 @@ fn test_pending() { let pending = stream.pending(); let len = stream.read(&mut buf[1..]).unwrap(); assert_eq!(pending, len); -} +} /// Tests that connecting with the client using NPN, but the server not does not /// break the existing connection behavior.