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}