diff options
| author | Steven Fackler <[email protected]> | 2015-12-09 22:02:02 -0800 |
|---|---|---|
| committer | Steven Fackler <[email protected]> | 2015-12-09 22:02:02 -0800 |
| commit | 8f56897043f8138980ce3376765b769c764d8701 (patch) | |
| tree | acb10fdbf1dccbaa62c2e7024f54e8a38146d37f /openssl/src | |
| parent | IT LIVES (diff) | |
| download | rust-openssl-8f56897043f8138980ce3376765b769c764d8701.tar.xz rust-openssl-8f56897043f8138980ce3376765b769c764d8701.zip | |
Implement read and write
Diffstat (limited to 'openssl/src')
| -rw-r--r-- | openssl/src/ssl/mod.rs | 226 | ||||
| -rw-r--r-- | openssl/src/ssl/tests/mod.rs | 12 |
2 files changed, 142 insertions, 96 deletions
diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 5d24fc32..e12d694d 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1350,102 +1350,6 @@ 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>; } @@ -1756,3 +1660,133 @@ impl<S: Read+Write> NonblockingSslStream<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)) + } + } +} + +impl<S> SslStreamNg<S> { + pub fn get_ref(&self) -> &S { + unsafe { + let bio = self.ssl.get_raw_rbio(); + bio::get_ref(bio) + } + } + + pub fn get_mut(&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), + } + } +} + +impl<S: Read> Read for SslStreamNg<S> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + let ret = self.ssl.read(buf); + if ret >= 0 { + return Ok(ret as usize); + } + + match self.make_error(ret) { + SslError::StreamError(e) => Err(e), + e => Err(io::Error::new(io::ErrorKind::Other, e)), + } + } +} + +impl<S: Write> Write for SslStreamNg<S> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + let ret = self.ssl.write(buf); + if ret > 0 { + return Ok(ret as usize); + } + + match self.make_error(ret) { + SslError::StreamError(e) => Err(e), + e => Err(io::Error::new(io::ErrorKind::Other, e)), + } + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index d1f34019..13d9371c 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -936,3 +936,15 @@ fn ng_connect() { let ctx = SslContext::new(Sslv23).unwrap(); SslStreamNg::connect(&ctx, stream).unwrap(); } + +#[test] +fn ng_get() { + let (_s, stream) = Server::new(); + let ctx = SslContext::new(Sslv23).unwrap(); + let mut stream = SslStreamNg::connect(&ctx, stream).unwrap(); + stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap(); + let mut resp = String::new(); + stream.read_to_string(&mut resp).unwrap(); + assert!(resp.starts_with("HTTP/1.0 200")); + assert!(resp.ends_with("</HTML>\r\n\r\n")); +} |