auth.rs

 1use std::mem::replace;
 2use futures::{Future, Poll, Async, sink, Sink, Stream};
 3use tokio_io::{AsyncRead, AsyncWrite};
 4use minidom::Element;
 5use xmpp_parsers::component::Handshake;
 6
 7use xmpp_codec::Packet;
 8use xmpp_stream::XMPPStream;
 9
10const NS_JABBER_COMPONENT_ACCEPT: &str = "jabber:component:accept";
11
12pub struct ComponentAuth<S: AsyncWrite> {
13    state: ComponentAuthState<S>,
14}
15
16enum ComponentAuthState<S: AsyncWrite> {
17    WaitSend(sink::Send<XMPPStream<S>>),
18    WaitRecv(XMPPStream<S>),
19    Invalid,
20}
21
22impl<S: AsyncWrite> ComponentAuth<S> {
23    pub fn new(stream: XMPPStream<S>, password: String) -> Result<Self, String> {
24        // FIXME: huge hack, shouldn’t be an element!
25        let sid = stream.stream_features.name().to_owned();
26        let mut this = ComponentAuth {
27            state: ComponentAuthState::Invalid,
28        };
29        this.send(
30            stream,
31            Handshake::from_password_and_stream_id(&password, &sid)
32        );
33        return Ok(this);
34    }
35
36    fn send(&mut self, stream: XMPPStream<S>, handshake: Handshake) {
37        let nonza = Element::from(handshake);
38        let send = stream.send(Packet::Stanza(nonza));
39
40        self.state = ComponentAuthState::WaitSend(send);
41    }
42}
43
44impl<S: AsyncRead + AsyncWrite> Future for ComponentAuth<S> {
45    type Item = XMPPStream<S>;
46    type Error = String;
47
48    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
49        let state = replace(&mut self.state, ComponentAuthState::Invalid);
50
51        match state {
52            ComponentAuthState::WaitSend(mut send) =>
53                match send.poll() {
54                    Ok(Async::Ready(stream)) => {
55                        self.state = ComponentAuthState::WaitRecv(stream);
56                        self.poll()
57                    },
58                    Ok(Async::NotReady) => {
59                        self.state = ComponentAuthState::WaitSend(send);
60                        Ok(Async::NotReady)
61                    },
62                    Err(e) =>
63                        Err(format!("{}", e)),
64                },
65            ComponentAuthState::WaitRecv(mut stream) =>
66                match stream.poll() {
67                    Ok(Async::Ready(Some(Packet::Stanza(ref stanza))))
68                        if stanza.is("handshake", NS_JABBER_COMPONENT_ACCEPT) =>
69                    {
70                        self.state = ComponentAuthState::Invalid;
71                        Ok(Async::Ready(stream))
72                    },
73                    Ok(Async::Ready(Some(Packet::Stanza(ref stanza))))
74                        if stanza.is("error", "http://etherx.jabber.org/streams") =>
75                    {
76                        let e = "Authentication failure";
77                        Err(e.to_owned())
78                    },
79                    Ok(Async::Ready(event)) => {
80                        println!("ComponentAuth ignore {:?}", event);
81                        Ok(Async::NotReady)
82                    },
83                    Ok(_) => {
84                        self.state = ComponentAuthState::WaitRecv(stream);
85                        Ok(Async::NotReady)
86                    },
87                    Err(e) =>
88                        Err(format!("{}", e)),
89                },
90            ComponentAuthState::Invalid =>
91                unreachable!(),
92        }
93    }
94}