From ca71e008789027893654029fcc57346393e9d324 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 23 Oct 2016 20:55:31 -0700 Subject: [PATCH] Fix Send + Sync-ness of SslStream --- openssl/src/ssl/bio.rs | 61 +++++++++++++++++++----------------- openssl/src/ssl/mod.rs | 9 +++--- openssl/src/ssl/tests/mod.rs | 8 +++++ 3 files changed, 45 insertions(+), 33 deletions(-) diff --git a/openssl/src/ssl/bio.rs b/openssl/src/ssl/bio.rs index 968aad10..a0215c2f 100644 --- a/openssl/src/ssl/bio.rs +++ b/openssl/src/ssl/bio.rs @@ -7,7 +7,6 @@ use std::io::prelude::*; use std::mem; use std::ptr; use std::slice; -use std::sync::Arc; use cvt_p; use error::ErrorStack; @@ -22,15 +21,16 @@ pub struct StreamState { pub struct BioMethod(compat::BIO_METHOD); impl BioMethod { - pub fn new() -> BioMethod { + fn new() -> BioMethod { BioMethod(compat::BIO_METHOD::new::()) } } +unsafe impl Sync for BioMethod {} unsafe impl Send for BioMethod {} -pub fn new(stream: S) -> Result<(*mut BIO, Arc), ErrorStack> { - let method = Arc::new(BioMethod::new::()); +pub fn new(stream: S) -> Result<(*mut BIO, BioMethod), ErrorStack> { + let method = BioMethod::new::(); let state = Box::new(StreamState { stream: stream, @@ -188,9 +188,7 @@ mod compat { pub unsafe fn BIO_set_num(_bio: *mut ffi::BIO, _num: c_int) {} - pub struct BIO_METHOD { - inner: *mut ffi::BIO_METHOD, - } + pub struct BIO_METHOD(*mut ffi::BIO_METHOD); impl BIO_METHOD { pub fn new() -> BIO_METHOD { @@ -198,7 +196,7 @@ mod compat { let ptr = ffi::BIO_meth_new(ffi::BIO_TYPE_NONE, b"rust\0".as_ptr() as *const _); assert!(!ptr.is_null()); - let ret = BIO_METHOD { inner: ptr }; + let ret = BIO_METHOD(ptr); assert!(ffi::BIO_meth_set_write(ptr, super::bwrite::) != 0); assert!(ffi::BIO_meth_set_read(ptr, super::bread::) != 0); assert!(ffi::BIO_meth_set_puts(ptr, super::bputs::) != 0); @@ -210,14 +208,14 @@ mod compat { } pub fn get(&self) -> *mut ffi::BIO_METHOD { - self.inner + self.0 } } impl Drop for BIO_METHOD { fn drop(&mut self) { unsafe { - ffi::BIO_meth_free(self.inner); + ffi::BIO_meth_free(self.0); } } } @@ -227,35 +225,40 @@ mod compat { #[allow(bad_style)] mod compat { use std::io::{Read, Write}; - use std::cell::UnsafeCell; use ffi; use libc::{c_int, c_void}; - pub struct BIO_METHOD { - inner: UnsafeCell, - } + pub struct BIO_METHOD(*mut ffi::BIO_METHOD); impl BIO_METHOD { pub fn new() -> BIO_METHOD { - BIO_METHOD { - inner: UnsafeCell::new(ffi::BIO_METHOD { - type_: ffi::BIO_TYPE_NONE, - name: b"rust\0".as_ptr() as *const _, - bwrite: Some(super::bwrite::), - bread: Some(super::bread::), - bputs: Some(super::bputs::), - bgets: None, - ctrl: Some(super::ctrl::), - create: Some(super::create), - destroy: Some(super::destroy::), - callback_ctrl: None, - }), - } + let ptr = Box::new(ffi::BIO_METHOD { + type_: ffi::BIO_TYPE_NONE, + name: b"rust\0".as_ptr() as *const _, + bwrite: Some(super::bwrite::), + bread: Some(super::bread::), + bputs: Some(super::bputs::), + bgets: None, + ctrl: Some(super::ctrl::), + create: Some(super::create), + destroy: Some(super::destroy::), + callback_ctrl: None, + }); + + BIO_METHOD(Box::into_raw(ptr)) } pub fn get(&self) -> *mut ffi::BIO_METHOD { - self.inner.get() + self.0 + } + } + + impl Drop for BIO_METHOD { + fn drop(&mut self) { + unsafe { + Box::::from_raw(self.0); + } } } diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 6e5a2c09..92e0c159 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -13,7 +13,7 @@ use std::ops::{Deref, DerefMut}; use std::path::Path; use std::ptr; use std::str; -use std::sync::{Mutex, Arc}; +use std::sync::Mutex; use libc::{c_uchar, c_uint}; use std::slice; use std::marker::PhantomData; @@ -1023,6 +1023,9 @@ impl SslRef { pub struct Ssl(*mut ffi::SSL); +unsafe impl Sync for Ssl {} +unsafe impl Send for Ssl {} + impl fmt::Debug for Ssl { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut builder = fmt.debug_struct("Ssl"); @@ -1128,12 +1131,10 @@ impl Ssl { /// A stream wrapper which handles SSL encryption for an underlying stream. pub struct SslStream { ssl: Ssl, - _method: Arc, // NOTE: this *must* be after the Ssl field so things drop right + _method: BioMethod, // NOTE: this *must* be after the Ssl field so things drop right _p: PhantomData, } -unsafe impl Send for SslStream {} - impl fmt::Debug for SslStream where S: fmt::Debug { diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 45c5b215..d11073f2 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -1083,3 +1083,11 @@ fn invalid_hostname() { let s = TcpStream::connect("google.com:443").unwrap(); assert!(ssl.connect(s).is_err()); } + +fn _check_kinds() { + fn is_send() {} + fn is_sync() {} + + is_send::>(); + is_sync::>(); +}