Skip to main content

tokio_xmpp/component/
mod.rs

1//! Components in XMPP are services/gateways that are logged into an
2//! XMPP server under a JID consisting of just a domain name. They are
3//! allowed to use any user and resource identifiers in their stanzas.
4use futures::sink::SinkExt;
5use std::str::FromStr;
6use xmpp_parsers::jid::Jid;
7
8use crate::{
9    component::login::component_login,
10    connect::ServerConnector,
11    event::ensure_stanza_id,
12    xmlstream::{Timeouts, XmppStream},
13    Error, Stanza,
14};
15
16#[cfg(any(feature = "starttls", feature = "insecure-tcp"))]
17use crate::connect::DnsConfig;
18#[cfg(feature = "insecure-tcp")]
19use crate::connect::TcpServerConnector;
20
21mod login;
22mod stream;
23
24/// Component connection to an XMPP server
25///
26/// This simplifies the `XmppStream` to a `Stream`/`Sink` of `Element`
27/// (stanzas). Connection handling however is up to the user.
28pub struct Component<C: ServerConnector> {
29    /// The component's Jabber-Id
30    pub jid: Jid,
31    stream: XmppStream<C::Stream>,
32}
33
34impl<C: ServerConnector> Component<C> {
35    /// Send stanza
36    pub async fn send_stanza(&mut self, mut stanza: Stanza) -> Result<(), Error> {
37        ensure_stanza_id(&mut stanza);
38        self.send(stanza).await
39    }
40
41    /// End connection
42    pub async fn send_end(&mut self) -> Result<(), Error> {
43        self.close().await
44    }
45}
46
47#[cfg(feature = "insecure-tcp")]
48impl Component<TcpServerConnector> {
49    /// Start a new XMPP component over plaintext TCP to localhost:5347
50    #[cfg(feature = "insecure-tcp")]
51    pub async fn new(jid: &str, password: &str) -> Result<Self, Error> {
52        Self::new_plaintext(
53            jid,
54            password,
55            DnsConfig::addr("127.0.0.1:5347"),
56            Timeouts::tight(),
57        )
58        .await
59    }
60
61    /// Start a new XMPP component over plaintext TCP
62    #[cfg(feature = "insecure-tcp")]
63    pub async fn new_plaintext(
64        jid: &str,
65        password: &str,
66        dns_config: DnsConfig,
67        timeouts: Timeouts,
68    ) -> Result<Self, Error> {
69        Component::new_with_connector(
70            jid,
71            password,
72            TcpServerConnector::from(dns_config),
73            timeouts,
74        )
75        .await
76    }
77}
78
79impl<C: ServerConnector> Component<C> {
80    /// Start a new XMPP component.
81    ///
82    /// Unfortunately [`StartTlsConnector`](crate::connect::StartTlsServerConnector) is not supported yet.
83    /// The tracking issue is [#143](https://gitlab.com/xmpp-rs/xmpp-rs/-/issues/143).
84    pub async fn new_with_connector(
85        jid: &str,
86        password: &str,
87        connector: C,
88        timeouts: Timeouts,
89    ) -> Result<Self, Error> {
90        let jid = Jid::from_str(jid)?;
91        let stream = component_login(connector, jid.clone(), password, timeouts).await?;
92        Ok(Component { jid, stream })
93    }
94}