xmpp_stream.rs

 1use std::default::Default;
 2use std::collections::HashMap;
 3use futures::*;
 4use tokio_io::{AsyncRead, AsyncWrite};
 5use tokio_io::codec::Framed;
 6use xml;
 7use sasl::common::{Credentials, ChannelBinding};
 8use jid::Jid;
 9
10use xmpp_codec::*;
11use stream_start::*;
12use starttls::{NS_XMPP_TLS, StartTlsClient};
13use client_auth::ClientAuth;
14use client_bind::ClientBind;
15
16pub const NS_XMPP_STREAM: &str = "http://etherx.jabber.org/streams";
17
18pub struct XMPPStream<S> {
19    pub jid: Jid,
20    pub stream: Framed<S, XMPPCodec>,
21    pub stream_attrs: HashMap<String, String>,
22    pub stream_features: xml::Element,
23}
24
25impl<S: AsyncRead + AsyncWrite> XMPPStream<S> {
26    pub fn new(jid: Jid,
27               stream: Framed<S, XMPPCodec>,
28               stream_attrs: HashMap<String, String>,
29               stream_features: xml::Element) -> Self {
30        XMPPStream { jid, stream, stream_attrs, stream_features }
31    }
32
33    pub fn from_stream(stream: S, jid: Jid) -> StreamStart<S> {
34        let xmpp_stream = AsyncRead::framed(stream, XMPPCodec::new());
35        StreamStart::from_stream(xmpp_stream, jid)
36    }
37
38    pub fn into_inner(self) -> S {
39        self.stream.into_inner()
40    }
41
42    pub fn restart(self) -> StreamStart<S> {
43        Self::from_stream(self.stream.into_inner(), self.jid)
44    }
45
46    pub fn can_starttls(&self) -> bool {
47        self.stream_features
48            .get_child("starttls", Some(NS_XMPP_TLS))
49            .is_some()
50    }
51
52    pub fn starttls(self) -> StartTlsClient<S> {
53        StartTlsClient::from_stream(self)
54    }
55
56    pub fn auth(self, username: String, password: String) -> Result<ClientAuth<S>, String> {
57        let creds = Credentials::default()
58            .with_username(username)
59            .with_password(password)
60            .with_channel_binding(ChannelBinding::None);
61        ClientAuth::new(self, creds)
62    }
63
64    pub fn bind(self) -> ClientBind<S> {
65        ClientBind::new(self)
66    }
67}
68
69/// Proxy to self.stream
70impl<S: AsyncWrite> Sink for XMPPStream<S> {
71    type SinkItem = <Framed<S, XMPPCodec> as Sink>::SinkItem;
72    type SinkError = <Framed<S, XMPPCodec> as Sink>::SinkError;
73
74    fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
75        self.stream.start_send(item)
76    }
77
78    fn poll_complete(&mut self) -> Poll<(), Self::SinkError> {
79        self.stream.poll_complete()
80    }
81}
82
83/// Proxy to self.stream
84impl<S: AsyncRead> Stream for XMPPStream<S> {
85    type Item = <Framed<S, XMPPCodec> as Stream>::Item;
86    type Error = <Framed<S, XMPPCodec> as Stream>::Error;
87
88    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
89        self.stream.poll()
90    }
91}