1use futures::stream::StreamExt;
2use std::marker::Unpin;
3use tokio::io::{AsyncRead, AsyncWrite};
4use xmpp_parsers::component::Handshake;
5
6use crate::xmpp_codec::Packet;
7use crate::xmpp_stream::XMPPStream;
8use crate::{AuthError, Error};
9
10const NS_JABBER_COMPONENT_ACCEPT: &str = "jabber:component:accept";
11
12pub async fn auth<S: AsyncRead + AsyncWrite + Unpin>(
13 stream: &mut XMPPStream<S>,
14 password: String,
15) -> Result<(), Error> {
16 let nonza = Handshake::from_password_and_stream_id(&password, &stream.id);
17 stream.send_stanza(nonza).await?;
18
19 loop {
20 match stream.next().await {
21 Some(Ok(Packet::Stanza(ref stanza)))
22 if stanza.is("handshake", NS_JABBER_COMPONENT_ACCEPT) =>
23 {
24 return Ok(());
25 }
26 Some(Ok(Packet::Stanza(ref stanza)))
27 if stanza.is("error", "http://etherx.jabber.org/streams") =>
28 {
29 return Err(AuthError::ComponentFail.into());
30 }
31 Some(_) => {}
32 None => return Err(Error::Disconnected),
33 }
34 }
35}