trying to flesh out Transport and the SslTransport implementation of it
This commit is contained in:
parent
12cbd17da7
commit
e5d549d1fe
2 changed files with 62 additions and 5 deletions
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue