diff --git a/openssl/src/bio/mod.rs b/openssl/src/bio/mod.rs index 2f12f906..6229a5ec 100644 --- a/openssl/src/bio/mod.rs +++ b/openssl/src/bio/mod.rs @@ -1,7 +1,9 @@ use libc::{c_void, c_int}; -use std::old_io::{EndOfFile, IoResult, IoError, OtherIoError}; -use std::old_io::{Reader, Writer}; +use std::io; +use std::io::prelude::*; use std::ptr; +use std::cmp; +use std::num::Int; use ffi; use ssl::error::{SslError}; @@ -57,49 +59,45 @@ impl MemBio { } } -impl Reader for MemBio { - fn read(&mut self, buf: &mut [u8]) -> IoResult { +impl Read for MemBio { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let len = cmp::min(::max_value() as usize, buf.len()) as c_int; let ret = unsafe { - ffi::BIO_read(self.bio, buf.as_ptr() as *mut c_void, - buf.len() as c_int) + ffi::BIO_read(self.bio, buf.as_ptr() as *mut c_void, len) }; if ret <= 0 { let is_eof = unsafe { ffi::BIO_eof(self.bio) }; - let err = if is_eof { - IoError { - kind: EndOfFile, - desc: "MemBio EOF", - detail: None - } + if is_eof { + Ok(0) } else { - IoError { - kind: OtherIoError, - desc: "MemBio read error", - detail: Some(format!("{:?}", SslError::get())) - } - }; - Err(err) + Err(io::Error::new(io::ErrorKind::Other, + "MemBio read error", + Some(format!("{:?}", SslError::get())))) + } } else { Ok(ret as usize) } } } -impl Writer for MemBio { - fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { +impl Write for MemBio { + fn write(&mut self, buf: &[u8]) -> io::Result { + let len = cmp::min(::max_value() as usize, buf.len()) as c_int; let ret = unsafe { - ffi::BIO_write(self.bio, buf.as_ptr() as *const c_void, - buf.len() as c_int) + ffi::BIO_write(self.bio, buf.as_ptr() as *const c_void, len) }; - if buf.len() != ret as usize { - Err(IoError { - kind: OtherIoError, - desc: "MemBio write error", - detail: Some(format!("{:?}", SslError::get())) - }) + + if ret < 0 { + Err(io::Error::new(io::ErrorKind::Other, + "MemBio write error", + Some(format!("{:?}", SslError::get())))) } else { - Ok(()) + Ok(ret as usize) } } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } diff --git a/openssl/src/crypto/hash.rs b/openssl/src/crypto/hash.rs index f81532c9..29e180e5 100644 --- a/openssl/src/crypto/hash.rs +++ b/openssl/src/crypto/hash.rs @@ -1,6 +1,7 @@ use libc::c_uint; use std::iter::repeat; -use std::old_io::{IoError, Writer}; +use std::io::prelude::*; +use std::io; use ffi; @@ -73,10 +74,10 @@ use self::State::*; /// assert_eq!(res, spec); /// ``` /// -/// Use the `Writer` trait to supply the input in chunks. +/// Use the `Write` trait to supply the input in chunks. /// /// ``` -/// use std::old_io::Writer; +/// use std::io::prelude::*; /// use openssl::crypto::hash::{Hasher, Type}; /// let data = [b"\x42\xF4", b"\x97\xE0"]; /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2"; @@ -168,10 +169,14 @@ impl Hasher { } } -impl Writer for Hasher { +impl Write for Hasher { #[inline] - fn write_all(&mut self, buf: &[u8]) -> Result<(), IoError> { + fn write(&mut self, buf: &[u8]) -> io::Result { self.update(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -213,7 +218,7 @@ pub fn hash(t: Type, data: &[u8]) -> Vec { mod tests { use serialize::hex::{FromHex, ToHex}; use super::{hash, Hasher, Type}; - use std::old_io::Writer; + use std::io::prelude::*; fn hash_test(hashtype: Type, hashtest: &(&str, &str)) { let res = hash(hashtype, &*hashtest.0.from_hex().unwrap()); diff --git a/openssl/src/crypto/hmac.rs b/openssl/src/crypto/hmac.rs index 55007ceb..01874aec 100644 --- a/openssl/src/crypto/hmac.rs +++ b/openssl/src/crypto/hmac.rs @@ -16,7 +16,8 @@ use libc::{c_int, c_uint}; use std::iter::repeat; -use std::old_io::{IoError, Writer}; +use std::io; +use std::io::prelude::*; use crypto::hash::Type; use ffi; @@ -46,10 +47,10 @@ use self::State::*; /// assert_eq!(spec, res); /// ``` /// -/// Use the `Writer` trait to supply the input in chunks. +/// Use the `Write` trait to supply the input in chunks. /// /// ``` -/// use std::old_io::Writer; +/// use std::io::prelude::*; /// use openssl::crypto::hash::Type; /// use openssl::crypto::hmac::HMAC; /// let key = b"Jefe"; @@ -150,10 +151,14 @@ impl HMAC { } } -impl Writer for HMAC { +impl Write for HMAC { #[inline] - fn write_all(&mut self, buf: &[u8]) -> Result<(), IoError> { + fn write(&mut self, buf: &[u8]) -> io::Result { self.update(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -197,7 +202,7 @@ mod tests { use crypto::hash::Type; use crypto::hash::Type::*; use super::{hmac, HMAC}; - use std::old_io::Writer; + use std::io::prelude::*; fn test_hmac(ty: Type, tests: &[(Vec, Vec, Vec)]) { for &(ref key, ref data, ref res) in tests.iter() { diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index c20fae4f..ac910e0b 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -1,4 +1,5 @@ use libc::{c_int, c_uint, c_ulong}; +use std::io::prelude::*; use std::iter::repeat; use std::mem; use std::ptr; @@ -142,15 +143,16 @@ impl PKey { /// Stores private key as a PEM // FIXME: also add password and encryption - pub fn write_pem(&self, writer: &mut Writer/*, password: Option*/) -> Result<(), SslError> { + pub fn write_pem(&self, writer: &mut W/*, password: Option*/) -> Result<(), SslError> { let mut mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.get_handle(), self.evp, ptr::null(), ptr::null_mut(), -1, None, ptr::null_mut())); } - let buf = try!(mem_bio.read_to_end().map_err(StreamError)); - writer.write_all(buf.as_slice()).map_err(StreamError) + let mut buf = vec![]; + try!(mem_bio.read_to_end(&mut buf).map_err(StreamError)); + writer.write_all(&buf).map_err(StreamError) } /** diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 56720ae2..6f9d07d8 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -1,4 +1,5 @@ -#![feature(unsafe_destructor, core, old_io, std_misc, old_path)] +#![feature(unsafe_destructor, core, io, std_misc, path, os)] +#![cfg_attr(test, feature(net, fs))] #![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/openssl")] extern crate libc; diff --git a/openssl/src/ssl/error.rs b/openssl/src/ssl/error.rs index bb2a5557..81f38692 100644 --- a/openssl/src/ssl/error.rs +++ b/openssl/src/ssl/error.rs @@ -5,7 +5,7 @@ use libc::c_ulong; use std::error; use std::fmt; use std::ffi::CStr; -use std::old_io::IoError; +use std::io; use ffi; @@ -13,7 +13,7 @@ use ffi; #[derive(Debug, Clone, PartialEq, Eq)] pub enum SslError { /// The underlying stream reported an error - StreamError(IoError), + StreamError(io::Error), /// The SSL session has been closed by the other end SslSessionClosed, /// An error in the OpenSSL library diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 5d3549ff..ecf12905 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1,11 +1,17 @@ use libc::{c_int, c_void, c_long}; use std::ffi::{CStr, CString}; -use std::old_io::{IoResult, IoError, EndOfFile, OtherIoError, Stream, Reader, Writer}; -use std::mem; use std::fmt; +use std::io; +use std::io::prelude::*; +use std::ffi::AsOsStr; +use std::mem; use std::num::FromPrimitive; +use std::num::Int; +use std::path::Path; use std::ptr; use std::sync::{Once, ONCE_INIT, Arc}; +use std::ops::{Deref, DerefMut}; +use std::cmp; use bio::{MemBio}; use ffi; @@ -245,9 +251,9 @@ impl SslContext { #[allow(non_snake_case)] /// Specifies the file that contains trusted CA certificates. pub fn set_CA_file(&mut self, file: &Path) -> Option { + let file = CString::new(file.as_os_str().to_str().expect("invalid utf8")).unwrap(); wrap_ssl_result( unsafe { - let file = CString::new(file.as_vec()).unwrap(); ffi::SSL_CTX_load_verify_locations(*self.ctx, file.as_ptr(), ptr::null()) }) } @@ -255,9 +261,9 @@ impl SslContext { /// Specifies the file that contains certificate pub fn set_certificate_file(&mut self, file: &Path, file_type: X509FileType) -> Option { + let file = CString::new(file.as_os_str().to_str().expect("invalid utf8")).unwrap(); wrap_ssl_result( unsafe { - let file = CString::new(file.as_vec()).unwrap(); ffi::SSL_CTX_use_certificate_file(*self.ctx, file.as_ptr(), file_type as c_int) }) } @@ -265,9 +271,9 @@ impl SslContext { /// Specifies the file that contains private key pub fn set_private_key_file(&mut self, file: &Path, file_type: X509FileType) -> Option { + let file = CString::new(file.as_os_str().to_str().expect("invalid utf8")).unwrap(); wrap_ssl_result( unsafe { - let file = CString::new(file.as_vec()).unwrap(); ffi::SSL_CTX_use_PrivateKey_file(*self.ctx, file.as_ptr(), file_type as c_int) }) } @@ -287,13 +293,17 @@ struct MemBioRef<'ssl> { bio: MemBio, } -impl<'ssl> MemBioRef<'ssl> { - fn read(&mut self, buf: &mut [u8]) -> Option { - (&mut self.bio as &mut Reader).read(buf).ok() - } +impl<'ssl> Deref for MemBioRef<'ssl> { + type Target = MemBio; - fn write_all(&mut self, buf: &[u8]) { - let _ = (&mut self.bio as &mut Writer).write_all(buf); + fn deref(&self) -> &MemBio { + &self.bio + } +} + +impl<'ssl> DerefMut for MemBioRef<'ssl> { + fn deref_mut(&mut self) -> &mut MemBio { + &mut self.bio } } @@ -354,13 +364,13 @@ impl Ssl { } fn read(&self, buf: &mut [u8]) -> c_int { - unsafe { ffi::SSL_read(*self.ssl, buf.as_ptr() as *mut c_void, - buf.len() as c_int) } + let len = cmp::min(::max_value() as usize, buf.len()) as c_int; + unsafe { ffi::SSL_read(*self.ssl, buf.as_ptr() as *mut c_void, len) } } fn write(&self, buf: &[u8]) -> c_int { - unsafe { ffi::SSL_write(*self.ssl, buf.as_ptr() as *const c_void, - buf.len() as c_int) } + let len = cmp::min(::max_value() as usize, buf.len()) as c_int; + unsafe { ffi::SSL_write(*self.ssl, buf.as_ptr() as *const c_void, len) } } fn get_error(&self, ret: c_int) -> LibSslError { @@ -433,7 +443,7 @@ impl fmt::Debug for SslStream where S: fmt::Debug { } } -impl SslStream { +impl SslStream { fn new_base(ssl:Ssl, stream: S) -> SslStream { SslStream { stream: stream, @@ -507,11 +517,15 @@ impl SslStream { return Ok(ret); } - match self.ssl.get_error(ret) { + let e = self.ssl.get_error(ret); + match e { LibSslError::ErrorWantRead => { try_ssl_stream!(self.flush()); let len = try_ssl_stream!(self.stream.read(self.buf.as_mut_slice())); - self.ssl.get_rbio().write_all(&self.buf[..len]); + if len == 0 { + return Ok(0); + } + try_ssl_stream!(self.ssl.get_rbio().write_all(&self.buf[..len])); } LibSslError::ErrorWantWrite => { try_ssl_stream!(self.flush()) } LibSslError::ErrorZeroReturn => return Err(SslSessionClosed), @@ -521,14 +535,8 @@ impl SslStream { } } - fn write_through(&mut self) -> IoResult<()> { - loop { - match self.ssl.get_wbio().read(self.buf.as_mut_slice()) { - Some(len) => try!(self.stream.write_all(&self.buf[..len])), - None => break - }; - } - Ok(()) + fn write_through(&mut self) -> io::Result<()> { + io::copy(&mut *self.ssl.get_wbio(), &mut self.stream).map(|_| ()) } /// Get the compression currently in use. The result will be @@ -549,56 +557,32 @@ impl SslStream { } } -impl Reader for SslStream { - fn read(&mut self, buf: &mut [u8]) -> IoResult { +impl Read for SslStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result { match self.in_retry_wrapper(|ssl| { ssl.read(buf) }) { Ok(len) => Ok(len as usize), - Err(SslSessionClosed) => { - Err(IoError { - kind: EndOfFile, - desc: "SSL session closed", - detail: None - }) - } + Err(SslSessionClosed) => Ok(0), Err(StreamError(e)) => Err(e), Err(e @ OpenSslErrors(_)) => { - Err(IoError { - kind: OtherIoError, - desc: "OpenSSL error", - detail: Some(format!("{}", e)), - }) + Err(io::Error::new(io::ErrorKind::Other, "OpenSSL error", Some(format!("{}", e)))) } } } } -impl Writer for SslStream { - fn write_all(&mut self, mut buf: &[u8]) -> IoResult<()> { - while !buf.is_empty() { - match self.in_retry_wrapper(|ssl| ssl.write(buf)) { - Ok(len) => buf = &buf[len as usize..], - Err(SslSessionClosed) => { - return Err(IoError { - kind: EndOfFile, - desc: "SSL session closed", - detail: None, - }); - } - Err(StreamError(e)) => return Err(e), - Err(e @ OpenSslErrors(_)) => { - return Err(IoError { - kind: OtherIoError, - desc: "OpenSSL error", - detail: Some(format!("{}", e)), - }); - } +impl Write for SslStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + match self.in_retry_wrapper(|ssl| ssl.write(buf)) { + Ok(len) => Ok(len as usize), + Err(SslSessionClosed) => Ok(0), + Err(StreamError(e)) => return Err(e), + Err(e @ OpenSslErrors(_)) => { + Err(io::Error::new(io::ErrorKind::Other, "OpenSSL error", Some(format!("{}", e)))) } - try!(self.write_through()); } - Ok(()) } - fn flush(&mut self) -> IoResult<()> { + fn flush(&mut self) -> io::Result<()> { try!(self.write_through()); self.stream.flush() } @@ -606,15 +590,15 @@ impl Writer for SslStream { /// A utility type to help in cases where the use of SSL is decided at runtime. #[derive(Debug)] -pub enum MaybeSslStream where S: Stream { +pub enum MaybeSslStream where S: Read+Write { /// A connection using SSL Ssl(SslStream), /// A connection not using SSL Normal(S), } -impl Reader for MaybeSslStream where S: Stream { - fn read(&mut self, buf: &mut [u8]) -> IoResult { +impl Read for MaybeSslStream where S: Read+Write { + fn read(&mut self, buf: &mut [u8]) -> io::Result { match *self { MaybeSslStream::Ssl(ref mut s) => s.read(buf), MaybeSslStream::Normal(ref mut s) => s.read(buf), @@ -622,15 +606,15 @@ impl Reader for MaybeSslStream where S: Stream { } } -impl Writer for MaybeSslStream where S: Stream{ - fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { +impl Write for MaybeSslStream where S: Read+Write { + fn write(&mut self, buf: &[u8]) -> io::Result { match *self { - MaybeSslStream::Ssl(ref mut s) => s.write_all(buf), - MaybeSslStream::Normal(ref mut s) => s.write_all(buf), + MaybeSslStream::Ssl(ref mut s) => s.write(buf), + MaybeSslStream::Normal(ref mut s) => s.write(buf), } } - fn flush(&mut self) -> IoResult<()> { + fn flush(&mut self) -> io::Result<()> { match *self { MaybeSslStream::Ssl(ref mut s) => s.flush(), MaybeSslStream::Normal(ref mut s) => s.flush(), @@ -638,7 +622,7 @@ impl Writer for MaybeSslStream where S: Stream{ } } -impl MaybeSslStream where S: Stream { +impl MaybeSslStream where S: Read+Write { /// Returns a reference to the underlying stream. pub fn get_ref(&self) -> &S { match *self { diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index 4bb3c2ca..41e54baa 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -1,7 +1,8 @@ use serialize::hex::FromHex; -use std::old_io::net::tcp::TcpStream; -use std::old_io::{Writer}; -use std::thread; +use std::net::TcpStream; +use std::io; +use std::io::prelude::*; +use std::path::Path; use crypto::hash::Type::{SHA256}; use ssl::SslMethod::Sslv23; @@ -191,17 +192,6 @@ fn test_read() { let mut stream = SslStream::new(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); - stream.read_to_end().ok().expect("read error"); -} - -#[test] -fn test_clone() { - let stream = TcpStream::connect("127.0.0.1:15418").unwrap(); - let mut stream = SslStream::new(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); - let mut stream2 = stream.clone(); - let _t = thread::spawn(move || { - stream2.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); - stream2.flush().unwrap(); - }); - stream.read_to_end().ok().expect("read error"); + println!("written"); + io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); } diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 898ea633..97d3dbdb 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -1,4 +1,6 @@ use libc::{c_char, c_int, c_long, c_uint}; +use std::io; +use std::io::prelude::*; use std::cmp::Ordering; use std::ffi::CString; use std::iter::repeat; @@ -150,8 +152,10 @@ impl<'a, T: AsStr<'a>> ToStr for Vec { /// ``` /// # #[allow(unstable)] /// # fn main() { -/// use std::old_io::{File, Open, Write}; -/// # use std::old_io::fs; +/// use std::fs; +/// use std::fs::File; +/// use std::io::prelude::*; +/// use std::path::Path; /// /// use openssl::crypto::hash::Type; /// use openssl::x509::{KeyUsage, X509Generator}; @@ -165,15 +169,15 @@ impl<'a, T: AsStr<'a>> ToStr for Vec { /// /// let (cert, pkey) = gen.generate().unwrap(); /// -/// let cert_path = Path::new("doc_cert.pem"); -/// let mut file = File::open_mode(&cert_path, Open, Write).unwrap(); +/// let cert_path = "doc_cert.pem"; +/// let mut file = File::create(cert_path).unwrap(); /// assert!(cert.write_pem(&mut file).is_ok()); -/// # let _ = fs::unlink(&cert_path); +/// # let _ = fs::remove_file(cert_path); /// -/// let pkey_path = Path::new("doc_key.pem"); -/// let mut file = File::open_mode(&pkey_path, Open, Write).unwrap(); +/// let pkey_path = "doc_key.pem"; +/// let mut file = File::create(pkey_path).unwrap(); /// assert!(pkey.write_pem(&mut file).is_ok()); -/// # let _ = fs::unlink(&pkey_path); +/// # let _ = fs::remove_file(pkey_path); /// # } /// ``` pub struct X509Generator { @@ -369,10 +373,9 @@ impl<'ctx> X509<'ctx> { } /// Reads certificate from PEM, takes ownership of handle - pub fn from_pem(reader: &mut R) -> Result, SslError> where R: Reader { + pub fn from_pem(reader: &mut R) -> Result, SslError> where R: Read { let mut mem_bio = try!(MemBio::new()); - let buf = try!(reader.read_to_end().map_err(StreamError)); - try!(mem_bio.write_all(buf.as_slice()).map_err(StreamError)); + try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); unsafe { let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.get_handle(), @@ -412,14 +415,13 @@ impl<'ctx> X509<'ctx> { } /// Writes certificate as PEM - pub fn write_pem(&self, writer: &mut W) -> Result<(), SslError> where W: Writer{ + pub fn write_pem(&self, writer: &mut W) -> Result<(), SslError> where W: Write { let mut mem_bio = try!(MemBio::new()); unsafe { try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(), self.handle)); } - let buf = try!(mem_bio.read_to_end().map_err(StreamError)); - writer.write_all(buf.as_slice()).map_err(StreamError) + io::copy(&mut mem_bio, writer).map_err(StreamError).map(|_| ()) } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 4f24e70c..cbb3d902 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -1,6 +1,7 @@ use serialize::hex::FromHex; -use std::old_io::{File, Open, Read}; -use std::old_io::util::NullWriter; +use std::io; +use std::path::Path; +use std::fs::File; use crypto::hash::Type::{SHA256}; use x509::{X509, X509Generator}; @@ -22,9 +23,8 @@ fn test_cert_gen() { let (cert, pkey) = res.unwrap(); - let mut writer = NullWriter; - assert!(cert.write_pem(&mut writer).is_ok()); - assert!(pkey.write_pem(&mut writer).is_ok()); + assert!(cert.write_pem(&mut io::sink()).is_ok()); + assert!(pkey.write_pem(&mut io::sink()).is_ok()); // FIXME: check data in result to be correct, needs implementation // of X509 getters @@ -33,7 +33,7 @@ fn test_cert_gen() { #[test] fn test_cert_loading() { let cert_path = Path::new("test/cert.pem"); - let mut file = File::open_mode(&cert_path, Open, Read) + let mut file = File::open(&cert_path) .ok() .expect("Failed to open `test/cert.pem`");