transport.rs

  1//! Provides transports for the xml streams.
  2
  3use std::io::prelude::*;
  4
  5use std::net::{TcpStream, Shutdown};
  6
  7use xml::reader::{EventReader, XmlEvent as XmlReaderEvent};
  8use xml::writer::{EventWriter, XmlEvent as XmlWriterEvent, EmitterConfig};
  9
 10use std::sync::{Arc, Mutex};
 11
 12use ns;
 13
 14use minidom;
 15
 16use locked_io::LockedIO;
 17
 18use error::Error;
 19
 20#[allow(unused_imports)]
 21use openssl::ssl::{SslMethod, Ssl, SslContextBuilder, SslStream, SSL_VERIFY_NONE, SslConnectorBuilder};
 22
 23use sasl::ChannelBinding;
 24
 25/// A trait which transports are required to implement.
 26pub trait Transport {
 27    /// Writes an `xml::writer::XmlEvent` to the stream.
 28    fn write_event<'a, E: Into<XmlWriterEvent<'a>>>(&mut self, event: E) -> Result<(), Error>;
 29
 30    /// Reads an `xml::reader::XmlEvent` from the stream.
 31    fn read_event(&mut self) -> Result<XmlReaderEvent, Error>;
 32
 33    /// Writes a `minidom::Element` to the stream.
 34    fn write_element(&mut self, element: &minidom::Element) -> Result<(), Error>;
 35
 36    /// Reads a `minidom::Element` from the stream.
 37    fn read_element(&mut self) -> Result<minidom::Element, Error>;
 38
 39    /// Resets the stream.
 40    fn reset_stream(&mut self);
 41
 42    /// Gets channel binding data.
 43    fn channel_bind(&self) -> ChannelBinding {
 44        ChannelBinding::None
 45    }
 46}
 47
 48/// A plain text transport, completely unencrypted.
 49pub struct PlainTransport {
 50    inner: Arc<Mutex<TcpStream>>, // TODO: this feels rather ugly
 51    reader: EventReader<LockedIO<TcpStream>>, // TODO: especially feels ugly because
 52                                              //       this read would keep the lock
 53                                              //       held very long (potentially)
 54    writer: EventWriter<LockedIO<TcpStream>>,
 55}
 56
 57impl Transport for PlainTransport {
 58    fn write_event<'a, E: Into<XmlWriterEvent<'a>>>(&mut self, event: E) -> Result<(), Error> {
 59        Ok(self.writer.write(event)?)
 60    }
 61
 62    fn read_event(&mut self) -> Result<XmlReaderEvent, Error> {
 63        Ok(self.reader.next()?)
 64    }
 65
 66    fn write_element(&mut self, element: &minidom::Element) -> Result<(), Error> {
 67        println!("SENT: {:?}", element);
 68        Ok(element.write_to(&mut self.writer)?)
 69    }
 70
 71    fn read_element(&mut self) -> Result<minidom::Element, Error> {
 72        let element = minidom::Element::from_reader(&mut self.reader)?;
 73        println!("RECV: {:?}", element);
 74        Ok(element)
 75    }
 76
 77    fn reset_stream(&mut self) {
 78        let locked_io = LockedIO::from(self.inner.clone());
 79        self.reader = EventReader::new(locked_io.clone());
 80        self.writer = EventWriter::new_with_config(locked_io, EmitterConfig {
 81            line_separator: "".into(),
 82            perform_indent: false,
 83            normalize_empty_elements: false,
 84            .. Default::default()
 85        });
 86    }
 87
 88    fn channel_bind(&self) -> ChannelBinding {
 89        // TODO: channel binding
 90        ChannelBinding::None
 91    }
 92}
 93
 94impl PlainTransport {
 95    /// Connects to a server without any encryption.
 96    pub fn connect(host: &str, port: u16) -> Result<PlainTransport, Error> {
 97        let tcp_stream = TcpStream::connect((host, port))?;
 98        let parser = EventReader::new(tcp_stream);
 99        let parser_stream = parser.into_inner();
100        let stream = Arc::new(Mutex::new(parser_stream));
101        let locked_io = LockedIO::from(stream.clone());
102        let reader = EventReader::new(locked_io.clone());
103        let writer = EventWriter::new_with_config(locked_io, EmitterConfig {
104            line_separator: "".into(),
105            perform_indent: false,
106            normalize_empty_elements: false,
107            .. Default::default()
108        });
109        Ok(PlainTransport {
110            inner: stream,
111            reader: reader,
112            writer: writer,
113        })
114    }
115
116    /// Closes the stream.
117    pub fn close(&mut self) {
118        self.inner.lock()
119                  .unwrap()
120                  .shutdown(Shutdown::Both)
121                  .unwrap(); // TODO: safety, return value and such
122    }
123}
124
125/// A transport which uses STARTTLS.
126pub struct SslTransport {
127    inner: Arc<Mutex<SslStream<TcpStream>>>, // TODO: this feels rather ugly
128    reader: EventReader<LockedIO<SslStream<TcpStream>>>, // TODO: especially feels ugly because
129                                                         //       this read would keep the lock
130                                                         //       held very long (potentially)
131    writer: EventWriter<LockedIO<SslStream<TcpStream>>>,
132}
133
134impl Transport for SslTransport {
135    fn write_event<'a, E: Into<XmlWriterEvent<'a>>>(&mut self, event: E) -> Result<(), Error> {
136        Ok(self.writer.write(event)?)
137    }
138
139    fn read_event(&mut self) -> Result<XmlReaderEvent, Error> {
140        Ok(self.reader.next()?)
141    }
142
143    fn write_element(&mut self, element: &minidom::Element) -> Result<(), Error> {
144        Ok(element.write_to(&mut self.writer)?)
145    }
146
147    fn read_element(&mut self) -> Result<minidom::Element, Error> {
148        Ok(minidom::Element::from_reader(&mut self.reader)?)
149    }
150
151    fn reset_stream(&mut self) {
152        let locked_io = LockedIO::from(self.inner.clone());
153        self.reader = EventReader::new(locked_io.clone());
154        self.writer = EventWriter::new_with_config(locked_io, EmitterConfig {
155            line_separator: "".into(),
156            perform_indent: false,
157            normalize_empty_elements: false,
158            .. Default::default()
159        });
160    }
161
162    fn channel_bind(&self) -> ChannelBinding {
163        // TODO: channel binding
164        ChannelBinding::None
165    }
166}
167
168impl SslTransport {
169    /// Connects to a server using STARTTLS.
170    pub fn connect(host: &str, port: u16) -> Result<SslTransport, Error> {
171        // TODO: very quick and dirty, blame starttls
172        let mut stream = TcpStream::connect((host, port))?;
173        write!(stream, "<stream:stream xmlns='{}' xmlns:stream='{}' to='{}' version='1.0'>"
174                     , ns::CLIENT, ns::STREAM, host)?;
175        write!(stream, "<starttls xmlns='{}'/>"
176                     , ns::TLS)?;
177        let mut parser = EventReader::new(stream);
178        loop { // TODO: possibly a timeout?
179            match parser.next()? {
180                XmlReaderEvent::StartElement { name, .. } => {
181                    if let Some(ns) = name.namespace {
182                        if ns == ns::TLS && name.local_name == "proceed" {
183                            break;
184                        }
185                        else if ns == ns::STREAM && name.local_name == "error" {
186                            return Err(Error::StreamError);
187                        }
188                    }
189                },
190                _ => {},
191            }
192        }
193        let stream = parser.into_inner();
194        #[cfg(feature = "insecure")]
195        let ssl_stream = {
196            let mut ctx = SslContextBuilder::new(SslMethod::tls())?;
197            ctx.set_verify(SSL_VERIFY_NONE);
198            let ssl = Ssl::new(&ctx.build())?;
199            ssl.connect(stream)?
200        };
201        #[cfg(not(feature = "insecure"))]
202        let ssl_stream = {
203            let ssl_connector = SslConnectorBuilder::new(SslMethod::tls())?.build();
204            ssl_connector.connect(host, stream)?
205        };
206        let ssl_stream = Arc::new(Mutex::new(ssl_stream));
207        let locked_io = LockedIO::from(ssl_stream.clone());
208        let reader = EventReader::new(locked_io.clone());
209        let writer = EventWriter::new_with_config(locked_io, EmitterConfig {
210            line_separator: "".into(),
211            perform_indent: false,
212            normalize_empty_elements: false,
213            .. Default::default()
214        });
215        Ok(SslTransport {
216            inner: ssl_stream,
217            reader: reader,
218            writer: writer,
219        })
220    }
221
222    /// Closes the stream.
223    pub fn close(&mut self) {
224        self.inner.lock()
225                  .unwrap()
226                  .shutdown()
227                  .unwrap(); // TODO: safety, return value and such
228    }
229}