xmpp-rs/tokio-xmpp/src/component/login.rs
Emmanuel Gil Peyrot c497967b1c xmpp-parsers: Reduce component handshake allocations
This function always appends to an existing string, so by passing it a
String directly we can avoid superfluous allocations.

Also tokio-xmpp was doing a bunch of &str to String for no reason around
there, let’s remove that too.
2025-02-10 17:06:15 +00:00

61 lines
2 KiB
Rust

use std::io;
use futures::{SinkExt, StreamExt};
use tokio::io::{AsyncBufRead, AsyncWrite};
use xmpp_parsers::{component::Handshake, jid::Jid, ns};
use crate::component::ServerConnector;
use crate::error::{AuthError, Error};
use crate::xmlstream::{ReadError, Timeouts, XmppStream, XmppStreamElement};
/// Log into an XMPP server as a client with a jid+pass
pub async fn component_login<C: ServerConnector>(
connector: C,
jid: Jid,
password: &str,
timeouts: Timeouts,
) -> Result<XmppStream<C::Stream>, Error> {
let (mut stream, _) = connector.connect(&jid, ns::COMPONENT, timeouts).await?;
let header = stream.take_header();
let mut stream = stream.skip_features();
let stream_id = match header.id {
Some(id) => id.into_owned(),
None => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"stream id missing on component stream",
)
.into())
}
};
auth(&mut stream, stream_id, password).await?;
Ok(stream)
}
pub async fn auth<S: AsyncBufRead + AsyncWrite + Unpin>(
stream: &mut XmppStream<S>,
stream_id: String,
password: &str,
) -> Result<(), Error> {
let nonza = Handshake::from_stream_id_and_password(stream_id, password);
stream
.send(&XmppStreamElement::ComponentHandshake(nonza))
.await?;
loop {
match stream.next().await {
Some(Ok(XmppStreamElement::ComponentHandshake(_))) => {
return Ok(());
}
Some(Ok(_)) => {
return Err(AuthError::ComponentFail.into());
}
Some(Err(ReadError::SoftTimeout)) => (),
Some(Err(ReadError::HardError(e))) => return Err(e.into()),
Some(Err(ReadError::ParseError(e))) => {
return Err(io::Error::new(io::ErrorKind::InvalidData, e).into())
}
Some(Err(ReadError::StreamFooterReceived)) | None => return Err(Error::Disconnected),
}
}
}