Loading openssl-sys/src/lib.rs +1 −0 Original line number Diff line number Diff line Loading @@ -1556,6 +1556,7 @@ extern { #[cfg(not(ossl101))] pub fn SSL_get0_param(ssl: *mut SSL) -> *mut X509_VERIFY_PARAM; pub fn SSL_get_verify_result(ssl: *const SSL) -> c_long; pub fn SSL_shutdown(ssl: *mut SSL) -> c_int; #[cfg(not(osslconf = "OPENSSL_NO_COMP"))] pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char; Loading openssl/src/ssl/mod.rs +30 −0 Original line number Diff line number Diff line Loading @@ -1278,6 +1278,26 @@ impl<S: Read + Write> SslStream<S> { Err(self.make_error(ret)) } } /// Shuts down the session. /// /// The shutdown process consists of two steps. The first step sends a /// close notify message to the peer, after which `ShutdownResult::Sent` /// is returned. The second step awaits the receipt of a close notify /// message from the peer, after which `ShutdownResult::Received` is /// returned. /// /// While the connection may be closed after the first step, it is /// recommended to fully shut the session down. In particular, it must /// be fully shut down if the connection is to be used for further /// communication in the future. pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> { match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } { 0 => Ok(ShutdownResult::Sent), 1 => Ok(ShutdownResult::Received), n => Err(self.make_error(n)), } } } impl<S> SslStream<S> { Loading Loading @@ -1383,6 +1403,16 @@ impl<S: Read + Write> Write for SslStream<S> { } } /// The result of a shutdown request. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ShutdownResult { /// A close notify message has been sent to the peer. Sent, /// A close notify response message has been received from the peer. Received, } #[cfg(ossl110)] mod compat { use std::ptr; Loading openssl/src/ssl/tests/mod.rs +33 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ use ssl; use ssl::SSL_VERIFY_PEER; use ssl::{SslMethod, HandshakeError}; use ssl::error::Error; use ssl::{SslContext, SslStream, Ssl}; use ssl::{SslContext, SslStream, Ssl, ShutdownResult}; use x509::X509StoreContextRef; use x509::X509FileType; use x509::X509; Loading Loading @@ -1084,6 +1084,38 @@ fn invalid_hostname() { assert!(ssl.connect(s).is_err()); } #[test] fn shutdown() { let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let port = listener.local_addr().unwrap().port(); thread::spawn(move || { let stream = listener.accept().unwrap().0; let mut ctx = SslContext::new(SslMethod::tls()).unwrap(); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM).unwrap(); ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM).unwrap(); let ssl = Ssl::new(&ctx).unwrap(); let mut stream = ssl.accept(stream).unwrap(); stream.write_all(b"hello").unwrap(); let mut buf = [0; 1]; assert_eq!(stream.read(&mut buf).unwrap(), 0); assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Received); }); let stream = TcpStream::connect(("127.0.0.1", port)).unwrap(); let ctx = SslContext::new(SslMethod::tls()).unwrap(); let ssl = Ssl::new(&ctx).unwrap(); let mut stream = ssl.connect(stream).unwrap(); let mut buf = [0; 5]; stream.read_exact(&mut buf).unwrap(); assert_eq!(b"hello", &buf); assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Sent); assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Received); } fn _check_kinds() { fn is_send<T: Send>() {} fn is_sync<T: Sync>() {} Loading Loading
openssl-sys/src/lib.rs +1 −0 Original line number Diff line number Diff line Loading @@ -1556,6 +1556,7 @@ extern { #[cfg(not(ossl101))] pub fn SSL_get0_param(ssl: *mut SSL) -> *mut X509_VERIFY_PARAM; pub fn SSL_get_verify_result(ssl: *const SSL) -> c_long; pub fn SSL_shutdown(ssl: *mut SSL) -> c_int; #[cfg(not(osslconf = "OPENSSL_NO_COMP"))] pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char; Loading
openssl/src/ssl/mod.rs +30 −0 Original line number Diff line number Diff line Loading @@ -1278,6 +1278,26 @@ impl<S: Read + Write> SslStream<S> { Err(self.make_error(ret)) } } /// Shuts down the session. /// /// The shutdown process consists of two steps. The first step sends a /// close notify message to the peer, after which `ShutdownResult::Sent` /// is returned. The second step awaits the receipt of a close notify /// message from the peer, after which `ShutdownResult::Received` is /// returned. /// /// While the connection may be closed after the first step, it is /// recommended to fully shut the session down. In particular, it must /// be fully shut down if the connection is to be used for further /// communication in the future. pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> { match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } { 0 => Ok(ShutdownResult::Sent), 1 => Ok(ShutdownResult::Received), n => Err(self.make_error(n)), } } } impl<S> SslStream<S> { Loading Loading @@ -1383,6 +1403,16 @@ impl<S: Read + Write> Write for SslStream<S> { } } /// The result of a shutdown request. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ShutdownResult { /// A close notify message has been sent to the peer. Sent, /// A close notify response message has been received from the peer. Received, } #[cfg(ossl110)] mod compat { use std::ptr; Loading
openssl/src/ssl/tests/mod.rs +33 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ use ssl; use ssl::SSL_VERIFY_PEER; use ssl::{SslMethod, HandshakeError}; use ssl::error::Error; use ssl::{SslContext, SslStream, Ssl}; use ssl::{SslContext, SslStream, Ssl, ShutdownResult}; use x509::X509StoreContextRef; use x509::X509FileType; use x509::X509; Loading Loading @@ -1084,6 +1084,38 @@ fn invalid_hostname() { assert!(ssl.connect(s).is_err()); } #[test] fn shutdown() { let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let port = listener.local_addr().unwrap().port(); thread::spawn(move || { let stream = listener.accept().unwrap().0; let mut ctx = SslContext::new(SslMethod::tls()).unwrap(); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM).unwrap(); ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM).unwrap(); let ssl = Ssl::new(&ctx).unwrap(); let mut stream = ssl.accept(stream).unwrap(); stream.write_all(b"hello").unwrap(); let mut buf = [0; 1]; assert_eq!(stream.read(&mut buf).unwrap(), 0); assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Received); }); let stream = TcpStream::connect(("127.0.0.1", port)).unwrap(); let ctx = SslContext::new(SslMethod::tls()).unwrap(); let ssl = Ssl::new(&ctx).unwrap(); let mut stream = ssl.connect(stream).unwrap(); let mut buf = [0; 5]; stream.read_exact(&mut buf).unwrap(); assert_eq!(b"hello", &buf); assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Sent); assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Received); } fn _check_kinds() { fn is_send<T: Send>() {} fn is_sync<T: Sync>() {} Loading