1use std::io::prelude::*;
2
3use std::net::TcpStream;
4
5use xml::reader::{EventReader, XmlEvent as XmlReaderEvent};
6use xml::writer::{EventWriter, XmlEvent as XmlWriterEvent, EmitterConfig};
7
8use std::sync::{Arc, Mutex};
9
10use ns;
11
12use minidom;
13
14use locked_io::LockedIO;
15
16use error::Error;
17
18use openssl::ssl::{SslMethod, SslConnectorBuilder, SslStream};
19
20pub trait Transport {
21 fn write_event<'a, E: Into<XmlWriterEvent<'a>>>(&mut self, event: E) -> Result<(), Error>;
22 fn read_event(&mut self) -> Result<XmlReaderEvent, Error>;
23
24 fn write_element(&mut self, element: &minidom::Element) -> Result<(), Error>;
25 fn read_element(&mut self) -> Result<minidom::Element, Error>;
26
27 fn reset_stream(&mut self);
28}
29
30pub struct SslTransport {
31 inner: Arc<Mutex<SslStream<TcpStream>>>, // TODO: this feels rather ugly
32 reader: EventReader<LockedIO<SslStream<TcpStream>>>, // TODO: especially feels ugly because
33 // this read would keep the lock
34 // held very long (potentially)
35 writer: EventWriter<LockedIO<SslStream<TcpStream>>>,
36}
37
38impl Transport for SslTransport {
39 fn write_event<'a, E: Into<XmlWriterEvent<'a>>>(&mut self, event: E) -> Result<(), Error> {
40 Ok(self.writer.write(event)?)
41 }
42
43 fn read_event(&mut self) -> Result<XmlReaderEvent, Error> {
44 Ok(self.reader.next()?)
45 }
46
47 fn write_element(&mut self, element: &minidom::Element) -> Result<(), Error> {
48 Ok(element.write_to(&mut self.writer)?)
49 }
50
51 fn read_element(&mut self) -> Result<minidom::Element, Error> {
52 Ok(minidom::Element::from_reader(&mut self.reader)?)
53 }
54
55 fn reset_stream(&mut self) {
56 let locked_io = LockedIO::from(self.inner.clone());
57 self.reader = EventReader::new(locked_io.clone());
58 self.writer = EventWriter::new_with_config(locked_io, EmitterConfig {
59 line_separator: "".into(),
60 perform_indent: false,
61 normalize_empty_elements: false,
62 .. Default::default()
63 });
64 }
65}
66
67impl SslTransport {
68 pub fn connect(host: &str, port: u16) -> Result<SslTransport, Error> {
69 // TODO: very quick and dirty, blame starttls
70 let mut stream = TcpStream::connect((host, port))?;
71 write!(stream, "<stream:stream xmlns='{}' xmlns:stream='{}' to='{}' version='1.0'>"
72 , ns::CLIENT, ns::STREAM, host)?;
73 write!(stream, "<starttls xmlns='{}'/>"
74 , ns::TLS)?;
75 let mut parser = EventReader::new(stream);
76 loop { // TODO: possibly a timeout?
77 match parser.next()? {
78 XmlReaderEvent::StartElement { name, .. } => {
79 if let Some(ns) = name.namespace {
80 if ns == ns::TLS && name.local_name == "proceed" {
81 break;
82 }
83 else if ns == ns::STREAM && name.local_name == "error" {
84 return Err(Error::StreamError);
85 }
86 }
87 },
88 _ => {},
89 }
90 }
91 let stream = parser.into_inner();
92 let ssl_connector = SslConnectorBuilder::new(SslMethod::tls())?.build();
93 let ssl_stream = Arc::new(Mutex::new(ssl_connector.connect(host, stream)?));
94 let locked_io = LockedIO::from(ssl_stream.clone());
95 let reader = EventReader::new(locked_io.clone());
96 let writer = EventWriter::new_with_config(locked_io, EmitterConfig {
97 line_separator: "".into(),
98 perform_indent: false,
99 normalize_empty_elements: false,
100 .. Default::default()
101 });
102 Ok(SslTransport {
103 inner: ssl_stream,
104 reader: reader,
105 writer: writer,
106 })
107 }
108
109 pub fn close(&mut self) {
110 self.inner.lock()
111 .unwrap()
112 .shutdown()
113 .unwrap(); // TODO: safety, return value and such
114 }
115}