use std::default::Default; use std::collections::HashMap; use futures::*; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::codec::Framed; use xml; use sasl::common::Credentials; use xmpp_codec::*; use stream_start::*; use starttls::{NS_XMPP_TLS, StartTlsClient}; use client_auth::ClientAuth; pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; pub struct XMPPStream { pub stream: Framed, pub stream_attrs: HashMap, pub stream_features: xml::Element, } impl XMPPStream { pub fn from_stream(stream: S, to: String) -> StreamStart { let xmpp_stream = AsyncRead::framed(stream, XMPPCodec::new()); StreamStart::from_stream(xmpp_stream, to) } pub fn into_inner(self) -> S { self.stream.into_inner() } pub fn restart(self) -> StreamStart { let to = self.stream_attrs.get("from") .map(|s| s.to_owned()) .unwrap_or_else(|| "".to_owned()); Self::from_stream(self.into_inner(), to.clone()) } pub fn can_starttls(&self) -> bool { self.stream_features .get_child("starttls", Some(NS_XMPP_TLS)) .is_some() } pub fn starttls(self) -> StartTlsClient { StartTlsClient::from_stream(self) } pub fn auth(self, username: &str, password: &str) -> Result, String> { let creds = Credentials::default() .with_username(username) .with_password(password); ClientAuth::new(self, creds) } } /// Proxy to self.stream impl Sink for XMPPStream { type SinkItem = as Sink>::SinkItem; type SinkError = as Sink>::SinkError; fn start_send(&mut self, item: Self::SinkItem) -> StartSend { self.stream.start_send(item) } fn poll_complete(&mut self) -> Poll<(), Self::SinkError> { self.stream.poll_complete() } } /// Proxy to self.stream impl Stream for XMPPStream { type Item = as Stream>::Item; type Error = as Stream>::Error; fn poll(&mut self) -> Poll, Self::Error> { self.stream.poll() } }