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
47 .next()
48 .await
49 .map(|v| v.map(|v| v.into_read_error()).flatten())
50 {
51 Some(Ok(XmppStreamElement::ComponentHandshake(_))) => {
52 return Ok(());
53 }
54 Some(Ok(_)) => {
55 return Err(AuthError::ComponentFail.into());
56 }
57 Some(Err(ReadError::SoftTimeout)) => (),
58 Some(Err(ReadError::HardError(e))) => return Err(e.into()),
59 Some(Err(ReadError::ParseError(e))) => {
60 return Err(io::Error::new(io::ErrorKind::InvalidData, e).into())
61 }
62 Some(Err(ReadError::StreamFooterReceived)) | None => return Err(Error::Disconnected),
63 }
64 }
65}