tokio_xmpp/component/
login.rs1use std::io;
2
3use futures::{SinkExt, StreamExt};
4use tokio::io::{AsyncBufRead, AsyncWrite};
5use xmpp_parsers::{component::Handshake, jid::Jid, ns};
6
7use crate::component::ServerConnector;
8use crate::error::{AuthError, Error};
9use crate::xmlstream::{ReadError, Timeouts, XmppStream, XmppStreamElement};
10
11pub async fn component_login<C: ServerConnector>(
13 connector: C,
14 jid: Jid,
15 password: &str,
16 timeouts: Timeouts,
17) -> Result<XmppStream<C::Stream>, Error> {
18 let (mut stream, _) = connector.connect(&jid, ns::COMPONENT, timeouts).await?;
19 let header = stream.take_header();
20 let mut stream = stream.skip_features();
21 let stream_id = match header.id {
22 Some(id) => id.into_owned(),
23 None => {
24 return Err(io::Error::new(
25 io::ErrorKind::InvalidData,
26 "stream id missing on component stream",
27 )
28 .into())
29 }
30 };
31 auth(&mut stream, stream_id, password).await?;
32 Ok(stream)
33}
34
35pub async fn auth<S: AsyncBufRead + AsyncWrite + Unpin>(
36 stream: &mut XmppStream<S>,
37 stream_id: String,
38 password: &str,
39) -> Result<(), Error> {
40 let nonza = Handshake::from_stream_id_and_password(stream_id, password);
41 stream
42 .send(&XmppStreamElement::ComponentHandshake(nonza))
43 .await?;
44
45 loop {
46 match stream.next().await {
47 Some(Ok(XmppStreamElement::ComponentHandshake(_))) => {
48 return Ok(());
49 }
50 Some(Ok(_)) => {
51 return Err(AuthError::ComponentFail.into());
52 }
53 Some(Err(ReadError::SoftTimeout)) => (),
54 Some(Err(ReadError::HardError(e))) => return Err(e.into()),
55 Some(Err(ReadError::ParseError(e))) => {
56 return Err(io::Error::new(io::ErrorKind::InvalidData, e).into())
57 }
58 Some(Err(ReadError::StreamFooterReceived)) | None => return Err(Error::Disconnected),
59 }
60 }
61}