diff options
| author | Steven Fackler <[email protected]> | 2015-12-09 21:43:02 -0800 |
|---|---|---|
| committer | Steven Fackler <[email protected]> | 2015-12-09 21:43:02 -0800 |
| commit | 9ee6f1c5785bb170c04a825ef173d4e336c957b2 (patch) | |
| tree | dc5af83adc869786753164c40fa54ba55ff48b89 /openssl/src/ssl/mod.rs | |
| parent | Custom BIO infrastructure (diff) | |
| download | rust-openssl-9ee6f1c5785bb170c04a825ef173d4e336c957b2.tar.xz rust-openssl-9ee6f1c5785bb170c04a825ef173d4e336c957b2.zip | |
IT LIVES
Diffstat (limited to 'openssl/src/ssl/mod.rs')
| -rw-r--r-- | openssl/src/ssl/mod.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 2f09e4fa..5d24fc32 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -18,6 +18,7 @@ use std::any::Any; use libc::{c_uchar, c_uint}; #[cfg(any(feature = "npn", feature = "alpn"))] use std::slice; +use std::marker::PhantomData; use bio::{MemBio}; use ffi; @@ -724,6 +725,10 @@ impl Ssl { Ok(ssl) } + fn get_raw_rbio(&self) -> *mut ffi::BIO { + unsafe { ffi::SSL_get_rbio(self.ssl) } + } + fn get_rbio<'a>(&'a self) -> MemBioRef<'a> { unsafe { self.wrap_bio(ffi::SSL_get_rbio(self.ssl)) } } @@ -1345,6 +1350,102 @@ impl<S: Read+Write> Write for SslStream<S> { } } +pub struct SslStreamNg<S> { + ssl: Ssl, + _method: Box<ffi::BIO_METHOD>, // :( + _p: PhantomData<S>, +} + +impl<S> Drop for SslStreamNg<S> { + fn drop(&mut self) { + unsafe { + let _ = bio::take_stream::<S>(self.ssl.get_raw_rbio()); + } + } +} + +impl<S: Read + Write> SslStreamNg<S> { + fn new_base(ssl: Ssl, stream: S) -> Result<Self, SslError> { + unsafe { + let (bio, method) = try!(bio::new(stream)); + ffi::SSL_set_bio(ssl.ssl, bio, bio); + + Ok(SslStreamNg { + ssl: ssl, + _method: method, + _p: PhantomData, + }) + } + } + + /// Creates an SSL/TLS client operating over the provided stream. + pub fn connect<T: IntoSsl>(ssl: T, stream: S) -> Result<Self, SslError> { + let ssl = try!(ssl.into_ssl()); + let mut stream = try!(Self::new_base(ssl, stream)); + let ret = stream.ssl.connect(); + if ret > 0 { + Ok(stream) + } else { + Err(stream.make_error(ret)) + } + } + + /// Creates an SSL/TLS server operating over the provided stream. + pub fn accept<T: IntoSsl>(ssl: T, stream: S) -> Result<Self, SslError> { + let ssl = try!(ssl.into_ssl()); + let mut stream = try!(Self::new_base(ssl, stream)); + let ret = stream.ssl.accept(); + if ret > 0 { + Ok(stream) + } else { + Err(stream.make_error(ret)) + } + } + + pub fn get_ref(&self) -> &S { + unsafe { + let bio = self.ssl.get_raw_rbio(); + bio::get_ref(bio) + } + } + + pub fn mut_ref(&mut self) -> &mut S { + unsafe { + let bio = self.ssl.get_raw_rbio(); + bio::get_mut(bio) + } + } + + fn make_error(&mut self, ret: c_int) -> SslError { + match self.ssl.get_error(ret) { + LibSslError::ErrorSsl => SslError::get(), + LibSslError::ErrorSyscall => { + let err = SslError::get(); + let count = match err { + SslError::OpenSslErrors(ref v) => v.len(), + _ => unreachable!(), + }; + if count == 0 { + if ret == 0 { + SslError::StreamError(io::Error::new(io::ErrorKind::ConnectionAborted, + "unexpected EOF observed")) + } else { + let error = unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }; + SslError::StreamError(error.unwrap()) + } + } else { + err + } + } + LibSslError::ErrorWantWrite | LibSslError::ErrorWantRead => { + let error = unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }; + SslError::StreamError(error.unwrap()) + } + err => panic!("unexpected error {:?} with ret {}", err, ret), + } + } +} + pub trait IntoSsl { fn into_ssl(self) -> Result<Ssl, SslError>; } |