//! `XMPPStream` is the common container for all XMPP network connections use futures::{Poll, Stream, Sink, StartSend}; use futures::sink::Send; use tokio_io::{AsyncRead, AsyncWrite}; use tokio_codec::Framed; use minidom::Element; use jid::Jid; use crate::xmpp_codec::{XMPPCodec, Packet}; use crate::stream_start::StreamStart; /// namespace pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams"; /// Wraps a `stream` pub struct XMPPStream { /// The local Jabber-Id pub jid: Jid, /// Codec instance pub stream: Framed, /// `` for XMPP version 1.0 pub stream_features: Element, /// Root namespace /// /// This is different for either c2s, s2s, or component /// connections. pub ns: String, } impl XMPPStream { /// Constructor pub fn new(jid: Jid, stream: Framed, ns: String, stream_features: Element) -> Self { XMPPStream { jid, stream, stream_features, ns } } /// Send a `` start tag pub fn start(stream: S, jid: Jid, ns: String) -> StreamStart { let xmpp_stream = Framed::new(stream, XMPPCodec::new()); StreamStart::from_stream(xmpp_stream, jid, ns) } /// Unwraps the inner stream pub fn into_inner(self) -> S { self.stream.into_inner() } /// Re-run `start()` pub fn restart(self) -> StreamStart { Self::start(self.stream.into_inner(), self.jid, self.ns) } } impl XMPPStream { /// Convenience method pub fn send_stanza>(self, e: E) -> Send { self.send(Packet::Stanza(e.into())) } } /// 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() } }