Commit ca71e008 authored by Steven Fackler's avatar Steven Fackler
Browse files

Fix Send + Sync-ness of SslStream

parent cb442568
Loading
Loading
Loading
Loading
+32 −29
Original line number Diff line number Diff line
@@ -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<S> {
pub struct BioMethod(compat::BIO_METHOD);

impl BioMethod {
    pub fn new<S: Read + Write>() -> BioMethod {
    fn new<S: Read + Write>() -> BioMethod {
        BioMethod(compat::BIO_METHOD::new::<S>())
    }
}

unsafe impl Sync for BioMethod {}
unsafe impl Send for BioMethod {}

pub fn new<S: Read + Write>(stream: S) -> Result<(*mut BIO, Arc<BioMethod>), ErrorStack> {
    let method = Arc::new(BioMethod::new::<S>());
pub fn new<S: Read + Write>(stream: S) -> Result<(*mut BIO, BioMethod), ErrorStack> {
    let method = BioMethod::new::<S>();

    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<S: Read + Write>() -> 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::<S>) != 0);
                assert!(ffi::BIO_meth_set_read(ptr, super::bread::<S>) != 0);
                assert!(ffi::BIO_meth_set_puts(ptr, super::bputs::<S>) != 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,19 +225,15 @@ 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<ffi::BIO_METHOD>,
    }
    pub struct BIO_METHOD(*mut ffi::BIO_METHOD);

    impl BIO_METHOD {
        pub fn new<S: Read + Write>() -> BIO_METHOD {
            BIO_METHOD {
                inner: UnsafeCell::new(ffi::BIO_METHOD {
            let ptr = Box::new(ffi::BIO_METHOD {
                type_: ffi::BIO_TYPE_NONE,
                name: b"rust\0".as_ptr() as *const _,
                bwrite: Some(super::bwrite::<S>),
@@ -250,12 +244,21 @@ mod compat {
                create: Some(super::create),
                destroy: Some(super::destroy::<S>),
                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::<ffi::BIO_METHOD>::from_raw(self.0);
            }
        }
    }

+5 −4
Original line number Diff line number Diff line
@@ -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<S> {
    ssl: Ssl,
    _method: Arc<BioMethod>, // 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<S>,
}

unsafe impl<S: Send> Send for SslStream<S> {}

impl<S> fmt::Debug for SslStream<S>
    where S: fmt::Debug
{
+8 −0
Original line number Diff line number Diff line
@@ -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<T: Send>() {}
    fn is_sync<T: Sync>() {}

    is_send::<SslStream<TcpStream>>();
    is_sync::<SslStream<TcpStream>>();
}