Skip to content

Commit

Permalink
feat(net): Add Ssl impls for security-framework
Browse files Browse the repository at this point in the history
Cloese #755
  • Loading branch information
sfackler committed Apr 16, 2016
1 parent caa796f commit f37315b
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 1 deletion.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ default-features = false
version = "0.7"
optional = true

[dependencies.security-framework]
version = "0.1.4"
optional = true

[dependencies.solicit]
version = "0.4"
default-features = false
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ extern crate time;
extern crate url;
#[cfg(feature = "openssl")]
extern crate openssl;
#[cfg(feature = "security-framework")]
extern crate security_framework;
#[cfg(feature = "serde-serialization")]
extern crate serde;
extern crate cookie;
Expand Down
115 changes: 114 additions & 1 deletion src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,14 +593,17 @@ impl<S: SslClient> NetworkConnector for HttpsConnector<S> {
}


#[cfg(not(feature = "openssl"))]
#[cfg(all(not(feature = "openssl"), not(feature = "security-framework")))]
#[doc(hidden)]
pub type DefaultConnector = HttpConnector;

#[cfg(feature = "openssl")]
#[doc(hidden)]
pub type DefaultConnector = HttpsConnector<self::openssl::Openssl>;

#[cfg(all(feature = "security-framework", not(feature = "openssl")))]
pub type DefaultConnector = HttpsConnector<self::security_framework::ClientWrapper>;

#[cfg(feature = "openssl")]
mod openssl {
use std::io;
Expand Down Expand Up @@ -702,6 +705,116 @@ mod openssl {
}
}

#[cfg(feature = "security-framework")]
pub mod security_framework {
use std::io;
use std::fmt;
use std::sync::{Arc, Mutex};
use std::net::{Shutdown, SocketAddr};
use std::time::Duration;
use security_framework::secure_transport::{SslStream, ClientBuilder, ServerBuilder};

use error::Error;
use net::{SslClient, SslServer, HttpStream, NetworkStream};

#[derive(Default)]
pub struct ClientWrapper(ClientBuilder);

impl ClientWrapper {
pub fn new(builder: ClientBuilder) -> ClientWrapper {
ClientWrapper(builder)
}
}

impl SslClient for ClientWrapper {
type Stream = Stream;

fn wrap_client(&self, stream: HttpStream, host: &str) -> ::Result<Stream> {
match self.0.handshake(host, stream) {
Ok(s) => Ok(Stream(Arc::new(Mutex::new(s)))),
Err(e) => Err(Error::Ssl(e.into())),
}
}
}

#[derive(Clone)]
pub struct ServerWrapper(Arc<ServerBuilder>);

impl ServerWrapper {
pub fn new(builder: ServerBuilder) -> ServerWrapper {
ServerWrapper(Arc::new(builder))
}
}

impl SslServer for ServerWrapper {
type Stream = Stream;

fn wrap_server(&self, stream: HttpStream) -> ::Result<Stream> {
match self.0.handshake(stream) {
Ok(s) => Ok(Stream(Arc::new(Mutex::new(s)))),
Err(e) => Err(Error::Ssl(e.into())),
}
}
}

#[derive(Clone)]
pub struct Stream(Arc<Mutex<SslStream<HttpStream>>>);

impl io::Read for Stream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.lock().unwrap_or_else(|e| e.into_inner()).read(buf)
}

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.0.lock().unwrap_or_else(|e| e.into_inner()).read_to_end(buf)
}

fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
self.0.lock().unwrap_or_else(|e| e.into_inner()).read_to_string(buf)
}

fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
self.0.lock().unwrap_or_else(|e| e.into_inner()).read_exact(buf)
}
}

impl io::Write for Stream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.lock().unwrap_or_else(|e| e.into_inner()).write(buf)
}

fn flush(&mut self) -> io::Result<()> {
self.0.lock().unwrap_or_else(|e| e.into_inner()).flush()
}

fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.0.lock().unwrap_or_else(|e| e.into_inner()).write_all(buf)
}

fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
self.0.lock().unwrap_or_else(|e| e.into_inner()).write_fmt(fmt)
}
}

impl NetworkStream for Stream {
fn peer_addr(&mut self) -> io::Result<SocketAddr> {
self.0.lock().unwrap_or_else(|e| e.into_inner()).get_mut().peer_addr()
}

fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.0.lock().unwrap_or_else(|e| e.into_inner()).get_mut().set_read_timeout(dur)
}

fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
self.0.lock().unwrap_or_else(|e| e.into_inner()).get_mut().set_write_timeout(dur)
}

fn close(&mut self, how: Shutdown) -> io::Result<()> {
self.0.lock().unwrap_or_else(|e| e.into_inner()).get_mut().close(how)
}
}
}

#[cfg(test)]
mod tests {
use mock::MockStream;
Expand Down

0 comments on commit f37315b

Please sign in to comment.