aboutsummaryrefslogtreecommitdiff
path: root/openssl/src/ssl
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2016-10-25 20:40:18 -0700
committerSteven Fackler <[email protected]>2016-10-25 20:40:18 -0700
commit39279455c8b0132d58742b8a08e884c3fde404fd (patch)
tree0eeb8dd24c6625d49da03a89f79044a2a4fa393f /openssl/src/ssl
parentFix ordering (diff)
downloadrust-openssl-39279455c8b0132d58742b8a08e884c3fde404fd.tar.xz
rust-openssl-39279455c8b0132d58742b8a08e884c3fde404fd.zip
Add a shutdown method
Diffstat (limited to 'openssl/src/ssl')
-rw-r--r--openssl/src/ssl/mod.rs30
-rw-r--r--openssl/src/ssl/tests/mod.rs34
2 files changed, 63 insertions, 1 deletions
diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs
index bf4c03f7..2577600f 100644
--- a/openssl/src/ssl/mod.rs
+++ b/openssl/src/ssl/mod.rs
@@ -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> {
@@ -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;
diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs
index d11073f2..4bc6f216 100644
--- a/openssl/src/ssl/tests/mod.rs
+++ b/openssl/src/ssl/tests/mod.rs
@@ -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;
@@ -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>() {}