trying to flesh out Transport and the SslTransport implementation of it

This commit is contained in:
lumi 2017-02-19 02:04:09 +01:00
parent 12cbd17da7
commit e5d549d1fe
2 changed files with 62 additions and 5 deletions

View file

@ -6,10 +6,12 @@ use openssl::ssl::HandshakeError;
use openssl::error::ErrorStack; use openssl::error::ErrorStack;
use xml::reader::Error as XmlError; use xml::reader::Error as XmlError;
use xml::writer::Error as EmitterError;
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
XmlError(XmlError), XmlError(XmlError),
EmitterError(EmitterError),
IoError(io::Error), IoError(io::Error),
HandshakeError(HandshakeError<TcpStream>), HandshakeError(HandshakeError<TcpStream>),
OpenSslErrorStack(ErrorStack), OpenSslErrorStack(ErrorStack),
@ -22,6 +24,12 @@ impl From<XmlError> for Error {
} }
} }
impl From<EmitterError> for Error {
fn from(err: EmitterError) -> Error {
Error::EmitterError(err)
}
}
impl From<io::Error> for Error { impl From<io::Error> for Error {
fn from(err: io::Error) -> Error { fn from(err: io::Error) -> Error {
Error::IoError(err) Error::IoError(err)

View file

@ -3,7 +3,10 @@ use std::io;
use std::net::{SocketAddr, TcpStream}; use std::net::{SocketAddr, TcpStream};
use xml::reader::{EventReader, XmlEvent}; use xml::reader::{EventReader, XmlEvent as XmlReaderEvent};
use xml::writer::{EventWriter, XmlEvent as XmlWriterEvent};
use std::sync::{Arc, Mutex};
use ns; use ns;
@ -11,8 +14,50 @@ use error::Error;
use openssl::ssl::{SslMethod, SslConnectorBuilder, SslStream}; use openssl::ssl::{SslMethod, SslConnectorBuilder, SslStream};
pub trait Transport {
fn write_event<'a, E: Into<XmlWriterEvent<'a>>>(&mut self, event: E) -> Result<(), Error>;
fn read_event(&mut self) -> Result<XmlReaderEvent, Error>;
}
struct LockedWrite<W: Write>(Arc<Mutex<W>>);
impl<W: Write> io::Write for LockedWrite<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let mut inner = self.0.lock().unwrap(); // TODO: make safer
inner.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
let mut inner = self.0.lock().unwrap(); // TODO: make safer
inner.flush()
}
}
struct LockedRead<R: Read>(Arc<Mutex<R>>);
impl<R: Read> io::Read for LockedRead<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut inner = self.0.lock().unwrap(); // TODO: make safer
inner.read(buf)
}
}
pub struct SslTransport { pub struct SslTransport {
inner: SslStream<TcpStream>, inner: Arc<Mutex<SslStream<TcpStream>>>, // TODO: this feels rather ugly
reader: EventReader<LockedRead<SslStream<TcpStream>>>, // TODO: especially feels ugly because
// this read would keep the lock
// held very long (potentially)
writer: EventWriter<LockedWrite<SslStream<TcpStream>>>,
}
impl Transport for SslTransport {
fn write_event<'a, E: Into<XmlWriterEvent<'a>>>(&mut self, event: E) -> Result<(), Error> {
Ok(self.writer.write(event)?)
}
fn read_event(&mut self) -> Result<XmlReaderEvent, Error> {
Ok(self.reader.next()?)
}
} }
impl SslTransport { impl SslTransport {
@ -26,7 +71,7 @@ impl SslTransport {
let mut parser = EventReader::new(stream); let mut parser = EventReader::new(stream);
loop { // TODO: possibly a timeout? loop { // TODO: possibly a timeout?
match parser.next()? { match parser.next()? {
XmlEvent::StartElement { name, namespace, .. } => { XmlReaderEvent::StartElement { name, namespace, .. } => {
if let Some(ns) = name.namespace { if let Some(ns) = name.namespace {
if ns == ns::TLS && name.local_name == "proceed" { if ns == ns::TLS && name.local_name == "proceed" {
break; break;
@ -41,9 +86,13 @@ impl SslTransport {
} }
let stream = parser.into_inner(); let stream = parser.into_inner();
let ssl_connector = SslConnectorBuilder::new(SslMethod::tls())?.build(); let ssl_connector = SslConnectorBuilder::new(SslMethod::tls())?.build();
let ssl_stream = ssl_connector.connect(host, stream)?; let ssl_stream = Arc::new(Mutex::new(ssl_connector.connect(host, stream)?));
let reader = EventReader::new(LockedRead(ssl_stream.clone()));
let writer = EventWriter::new(LockedWrite(ssl_stream.clone()));
Ok(SslTransport { Ok(SslTransport {
inner: ssl_stream inner: ssl_stream,
reader: reader,
writer: writer,
}) })
} }
} }