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}