feat(net): Add Ssl impls for security-framework

Cloese #755
This commit is contained in:
Steven Fackler
2016-04-16 12:46:25 -07:00
parent caa796f98d
commit f37315b270
3 changed files with 120 additions and 1 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -593,7 +593,7 @@ 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;
@@ -601,6 +601,9 @@ pub type DefaultConnector = HttpConnector;
#[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;
@@ -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;