xmpp_stream.rs

 1use std::sync::Arc;
 2use std::collections::HashMap;
 3use futures::*;
 4use tokio_io::{AsyncRead, AsyncWrite};
 5use tokio_io::codec::Framed;
 6use rustls::ClientConfig;
 7use xml;
 8
 9use xmpp_codec::*;
10use stream_start::*;
11use starttls::{NS_XMPP_TLS, StartTlsClient};
12
13pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams";
14
15pub struct XMPPStream<S> {
16    pub stream: Framed<S, XMPPCodec>,
17    pub stream_attrs: HashMap<String, String>,
18    pub stream_features: xml::Element,
19}
20
21impl<S: AsyncRead + AsyncWrite> XMPPStream<S> {
22    pub fn from_stream(stream: S, to: String) -> StreamStart<S> {
23        let xmpp_stream = AsyncRead::framed(stream, XMPPCodec::new());
24        StreamStart::from_stream(xmpp_stream, to)
25    }
26
27    pub fn into_inner(self) -> S {
28        self.stream.into_inner()
29    }
30
31    pub fn can_starttls(&self) -> bool {
32        self.stream_features
33            .get_child("starttls", Some(NS_XMPP_TLS))
34            .is_some()
35    }
36
37    pub fn starttls(self, arc_config: Arc<ClientConfig>) -> StartTlsClient<S> {
38        StartTlsClient::from_stream(self, arc_config)
39    }
40}
41
42impl<S: AsyncWrite> Sink for XMPPStream<S> {
43    type SinkItem = <Framed<S, XMPPCodec> as Sink>::SinkItem;
44    type SinkError = <Framed<S, XMPPCodec> as Sink>::SinkError;
45
46    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
47        self.stream.start_send(item)
48    }
49
50    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
51        self.stream.poll_complete()
52    }
53}
54
55impl<S: AsyncRead> Stream for XMPPStream<S> {
56    type Item = <Framed<S, XMPPCodec> as Stream>::Item;
57    type Error = <Framed<S, XMPPCodec> as Stream>::Error;
58
59    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
60        self.stream.poll()
61    }
62}