2018-08-02 19:58:19 +02:00
|
|
|
//! Components in XMPP are services/gateways that are logged into an
|
|
|
|
|
//! XMPP server under a JID consisting of just a domain name. They are
|
|
|
|
|
//! allowed to use any user and resource identifiers in their stanzas.
|
2020-03-05 01:25:24 +01:00
|
|
|
use futures::{sink::SinkExt, task::Poll, Sink, Stream};
|
|
|
|
|
use std::pin::Pin;
|
2017-07-22 01:59:51 +01:00
|
|
|
use std::str::FromStr;
|
2020-03-05 01:25:24 +01:00
|
|
|
use std::task::Context;
|
2020-05-30 01:19:06 +02:00
|
|
|
use xmpp_parsers::{ns, Element, Jid};
|
2017-07-22 01:59:51 +01:00
|
|
|
|
2023-12-30 22:08:37 -05:00
|
|
|
use self::connect::component_login;
|
|
|
|
|
|
2017-07-22 01:59:51 +01:00
|
|
|
use super::xmpp_codec::Packet;
|
2018-09-06 17:46:06 +02:00
|
|
|
use super::Error;
|
2023-12-30 22:08:37 -05:00
|
|
|
use crate::connect::ServerConnector;
|
2023-06-04 19:27:46 +02:00
|
|
|
use crate::xmpp_stream::add_stanza_id;
|
2023-12-30 22:08:37 -05:00
|
|
|
use crate::xmpp_stream::XMPPStream;
|
2017-07-22 01:59:51 +01:00
|
|
|
|
|
|
|
|
mod auth;
|
|
|
|
|
|
2023-12-30 22:08:37 -05:00
|
|
|
pub(crate) mod connect;
|
|
|
|
|
|
2018-08-02 19:58:19 +02:00
|
|
|
/// Component connection to an XMPP server
|
2020-03-05 01:25:24 +01:00
|
|
|
///
|
|
|
|
|
/// This simplifies the `XMPPStream` to a `Stream`/`Sink` of `Element`
|
|
|
|
|
/// (stanzas). Connection handling however is up to the user.
|
2023-12-30 22:08:37 -05:00
|
|
|
pub struct Component<C: ServerConnector> {
|
2018-08-02 19:58:19 +02:00
|
|
|
/// The component's Jabber-Id
|
2017-07-22 01:59:51 +01:00
|
|
|
pub jid: Jid,
|
2023-12-30 22:08:37 -05:00
|
|
|
stream: XMPPStream<C::Stream>,
|
2017-07-22 01:59:51 +01:00
|
|
|
}
|
|
|
|
|
|
2023-12-30 22:08:37 -05:00
|
|
|
impl<C: ServerConnector> Component<C> {
|
2018-08-02 19:58:19 +02:00
|
|
|
/// Start a new XMPP component
|
2024-01-01 01:13:51 -05:00
|
|
|
pub async fn new_with_connector(
|
|
|
|
|
jid: &str,
|
|
|
|
|
password: &str,
|
|
|
|
|
connector: C,
|
|
|
|
|
) -> Result<Self, Error> {
|
2018-08-02 20:10:26 +02:00
|
|
|
let jid = Jid::from_str(jid)?;
|
2017-07-22 01:59:51 +01:00
|
|
|
let password = password.to_owned();
|
2023-12-30 22:08:37 -05:00
|
|
|
let stream = component_login(connector, jid.clone(), password).await?;
|
2020-03-05 01:25:24 +01:00
|
|
|
Ok(Component { jid, stream })
|
2017-07-22 01:59:51 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-05 01:25:24 +01:00
|
|
|
/// Send stanza
|
|
|
|
|
pub async fn send_stanza(&mut self, stanza: Element) -> Result<(), Error> {
|
2023-06-04 19:27:46 +02:00
|
|
|
self.send(add_stanza_id(stanza, ns::COMPONENT_ACCEPT)).await
|
2020-03-05 01:25:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// End connection
|
|
|
|
|
pub async fn send_end(&mut self) -> Result<(), Error> {
|
|
|
|
|
self.close().await
|
2017-07-22 01:59:51 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-30 22:08:37 -05:00
|
|
|
impl<C: ServerConnector> Stream for Component<C> {
|
2020-03-05 01:25:24 +01:00
|
|
|
type Item = Element;
|
2017-07-22 01:59:51 +01:00
|
|
|
|
2020-03-05 01:25:24 +01:00
|
|
|
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
|
|
|
|
loop {
|
|
|
|
|
match Pin::new(&mut self.stream).poll_next(cx) {
|
|
|
|
|
Poll::Ready(Some(Ok(Packet::Stanza(stanza)))) => return Poll::Ready(Some(stanza)),
|
|
|
|
|
Poll::Ready(Some(Ok(Packet::Text(_)))) => {
|
|
|
|
|
// retry
|
2018-12-18 19:04:31 +01:00
|
|
|
}
|
2020-03-05 01:25:24 +01:00
|
|
|
Poll::Ready(Some(Ok(_))) =>
|
|
|
|
|
// unexpected
|
|
|
|
|
{
|
|
|
|
|
return Poll::Ready(None)
|
2017-07-22 01:59:51 +01:00
|
|
|
}
|
2020-03-05 01:25:24 +01:00
|
|
|
Poll::Ready(Some(Err(_))) => return Poll::Ready(None),
|
|
|
|
|
Poll::Ready(None) => return Poll::Ready(None),
|
|
|
|
|
Poll::Pending => return Poll::Pending,
|
2018-12-18 19:04:31 +01:00
|
|
|
}
|
2017-07-22 01:59:51 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-30 22:08:37 -05:00
|
|
|
impl<C: ServerConnector> Sink<Element> for Component<C> {
|
2020-03-05 01:25:24 +01:00
|
|
|
type Error = Error;
|
2017-07-22 01:59:51 +01:00
|
|
|
|
2020-03-05 01:25:24 +01:00
|
|
|
fn start_send(mut self: Pin<&mut Self>, item: Element) -> Result<(), Self::Error> {
|
|
|
|
|
Pin::new(&mut self.stream)
|
|
|
|
|
.start_send(Packet::Stanza(item))
|
|
|
|
|
.map_err(|e| e.into())
|
2017-07-22 01:59:51 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-05 01:25:24 +01:00
|
|
|
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
|
Pin::new(&mut self.stream)
|
|
|
|
|
.poll_ready(cx)
|
|
|
|
|
.map_err(|e| e.into())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
|
Pin::new(&mut self.stream)
|
|
|
|
|
.poll_flush(cx)
|
|
|
|
|
.map_err(|e| e.into())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
|
Pin::new(&mut self.stream)
|
|
|
|
|
.poll_close(cx)
|
|
|
|
|
.map_err(|e| e.into())
|
2017-07-22 01:59:51 +01:00
|
|
|
}
|
|
|
|
|
}
|