diff --git a/src/ssl/ffi.rs b/src/ssl/ffi.rs index 788765fb..c3144545 100644 --- a/src/ssl/ffi.rs +++ b/src/ssl/ffi.rs @@ -1,14 +1,29 @@ +#[doc(hidden)]; + use std::libc::{c_int, c_void}; pub type SSL_CTX = c_void; pub type SSL_METHOD = c_void; +pub type SSL = c_void; +pub type BIO = c_void; +pub type BIO_METHOD = c_void; #[link_args = "-lssl"] -extern "C" { - fn SSL_library_init() -> c_int; - fn SSL_load_error_strings(); +extern "C" { } - fn SSL_CTX_new(method: *SSL_METHOD) -> *SSL_CTX; - fn SSLv23_method() -> *SSL_METHOD; - fn SSL_CTX_free(ctx: *SSL_CTX); -} +externfn!(fn SSL_library_init() -> c_int) +externfn!(fn SSL_load_error_strings()) + +externfn!(fn SSLv23_method() -> *SSL_METHOD) +externfn!(fn SSL_CTX_new(method: *SSL_METHOD) -> *SSL_CTX) +externfn!(fn SSL_CTX_free(ctx: *SSL_CTX)) + +externfn!(fn SSL_new(ctx: *SSL_CTX) -> *SSL) +externfn!(fn SSL_free(ssl: *SSL)) +externfn!(fn SSL_set_bio(ssl: *SSL, rbio: *BIO, wbio: *BIO)) +externfn!(fn SSL_set_connect_state(ssl: *SSL)) +externfn!(fn SSL_do_handshake(ssl: *SSL)) + +externfn!(fn BIO_s_mem() -> *BIO_METHOD) +externfn!(fn BIO_new(type_: *BIO_METHOD) -> *BIO) +externfn!(fn BIO_free(a: *BIO) -> c_int) diff --git a/src/ssl/lib.rs b/src/ssl/lib.rs index a7c5588f..a65d8eac 100644 --- a/src/ssl/lib.rs +++ b/src/ssl/lib.rs @@ -1,12 +1,13 @@ +use std::rt::io::{Stream, Decorator}; use std::unstable::atomics::{AtomicBool, INIT_ATOMIC_BOOL, Acquire, Release}; use std::task; +use std::ptr; mod ffi; static mut STARTED_INIT: AtomicBool = INIT_ATOMIC_BOOL; static mut FINISHED_INIT: AtomicBool = INIT_ATOMIC_BOOL; -#[fixed_stack_segment] pub fn init() { unsafe { if STARTED_INIT.swap(true, Acquire) { @@ -27,7 +28,6 @@ pub enum SslMethod { } impl SslMethod { - #[fixed_stack_segment] unsafe fn to_raw(&self) -> *ffi::SSL_METHOD { match *self { Sslv23 => ffi::SSLv23_method() @@ -40,18 +40,110 @@ pub struct SslCtx { } impl Drop for SslCtx { - #[fixed_stack_segment] fn drop(&mut self) { unsafe { ffi::SSL_CTX_free(self.ctx); } } } impl SslCtx { - #[fixed_stack_segment] pub fn new(method: SslMethod) -> SslCtx { init(); + + let ctx = unsafe { ffi::SSL_CTX_new(method.to_raw()) }; + assert!(ctx != ptr::null()); + SslCtx { - ctx: unsafe { ffi::SSL_CTX_new(method.to_raw()) } + ctx: ctx } } } + +struct Ssl { + ssl: *ffi::SSL +} + +impl Drop for Ssl { + fn drop(&mut self) { + unsafe { ffi::SSL_free(self.ssl); } + } +} + +impl Ssl { + fn new(ctx: &SslCtx) -> Ssl { + let ssl = unsafe { ffi::SSL_new(ctx.ctx) }; + assert!(ssl != ptr::null()); + + Ssl { ssl: ssl } + } + + fn set_bio(&self, rbio: &MemBio, wbio: &MemBio) { + unsafe { ffi::SSL_set_bio(self.ssl, rbio.bio, wbio.bio); } + } + + fn set_connect_state(&self) { + unsafe { ffi::SSL_set_connect_state(self.ssl); } + } +} + +struct MemBio { + bio: *ffi::BIO +} + +impl Drop for MemBio { + fn drop(&mut self) { + unsafe { ffi::BIO_free(self.bio); } + } +} + +impl MemBio { + fn new() -> MemBio { + let bio = unsafe { ffi::BIO_new(ffi::BIO_s_mem()) }; + assert!(bio != ptr::null()); + + MemBio { bio: bio } + } +} + +pub struct SslStream { + priv ctx: SslCtx, + priv ssl: Ssl, + priv rbio: MemBio, + priv wbio: MemBio, + priv stream: S +} + +impl SslStream { + pub fn new(ctx: SslCtx, stream: S) -> SslStream { + let ssl = Ssl::new(&ctx); + + let rbio = MemBio::new(); + let wbio = MemBio::new(); + + ssl.set_bio(&rbio, &wbio); + ssl.set_connect_state(); + + let stream = SslStream { + ctx: ctx, + ssl: ssl, + rbio: rbio, + wbio: wbio, + stream: stream + } + + stream + } +} + +impl Decorator for SslStream { + fn inner(self) -> S { + self.stream + } + + fn inner_ref<'a>(&'a self) -> &'a S { + &self.stream + } + + fn inner_mut_ref<'a>(&'a mut self) -> &'a mut S { + &mut self.stream + } +} diff --git a/src/ssl/test.rs b/src/ssl/test.rs index d54613ee..501c8626 100644 --- a/src/ssl/test.rs +++ b/src/ssl/test.rs @@ -1,8 +1,16 @@ extern mod ssl; -use ssl::{Sslv23, SslCtx}; +use std::rt::io::net::tcp::TcpStream; + +use ssl::{Sslv23, SslCtx, SslStream}; #[test] fn test_new_ctx() { SslCtx::new(Sslv23); } + +#[test] +fn test_new_sslstream() { + let stream = TcpStream::connect(FromStr::from_str("127.0.0.1:15418").unwrap()); + let stream = SslStream::new(SslCtx::new(Sslv23), stream); +}