diff --git a/tokio-xmpp/src/component/connect.rs b/tokio-xmpp/src/component/connect.rs deleted file mode 100644 index a7fb16241073baf2c0ecfbdd999bf66bf5b80919..0000000000000000000000000000000000000000 --- a/tokio-xmpp/src/component/connect.rs +++ /dev/null @@ -1,15 +0,0 @@ -use xmpp_parsers::{jid::Jid, ns}; - -use crate::{component::auth::auth, connect::ServerConnector, proto::XmppStream, Error}; - -/// Log into an XMPP server as a client with a jid+pass -pub async fn component_login( - connector: C, - jid: Jid, - password: String, -) -> Result, Error> { - let password = password; - let mut xmpp_stream = connector.connect(&jid, ns::COMPONENT).await?; - auth(&mut xmpp_stream, password).await?; - Ok(xmpp_stream) -} diff --git a/tokio-xmpp/src/component/auth.rs b/tokio-xmpp/src/component/login.rs similarity index 61% rename from tokio-xmpp/src/component/auth.rs rename to tokio-xmpp/src/component/login.rs index 0bb10b01891ca7ff0f0d42b4750b166ee66d8c01..d72781dbe91426663db06ab07bd487d4ba402ea2 100644 --- a/tokio-xmpp/src/component/auth.rs +++ b/tokio-xmpp/src/component/login.rs @@ -1,9 +1,24 @@ use futures::stream::StreamExt; use tokio::io::{AsyncRead, AsyncWrite}; -use xmpp_parsers::{component::Handshake, ns}; +use xmpp_parsers::{component::Handshake, jid::Jid, ns}; -use crate::error::{AuthError, Error}; -use crate::proto::{Packet, XmppStream}; +use crate::{ + connect::ServerConnector, + error::{AuthError, Error}, + proto::{Packet, XmppStream}, +}; + +/// Log into an XMPP server as a client with a jid+pass +pub async fn component_login( + connector: C, + jid: Jid, + password: String, +) -> Result, Error> { + let password = password; + let mut xmpp_stream = connector.connect(&jid, ns::COMPONENT).await?; + auth(&mut xmpp_stream, password).await?; + Ok(xmpp_stream) +} pub async fn auth( stream: &mut XmppStream, diff --git a/tokio-xmpp/src/component/mod.rs b/tokio-xmpp/src/component/mod.rs index eaf830944be8789fde984de231088da59d02802b..52391f14b4826778e48262a3656ce57038a414ea 100644 --- a/tokio-xmpp/src/component/mod.rs +++ b/tokio-xmpp/src/component/mod.rs @@ -1,27 +1,25 @@ //! 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. -use futures::{sink::SinkExt, task::Poll, Sink, Stream}; +use futures::sink::SinkExt; use minidom::Element; -use std::pin::Pin; use std::str::FromStr; -use std::task::Context; use xmpp_parsers::{jid::Jid, ns}; -use self::connect::component_login; - -use crate::connect::ServerConnector; -use crate::proto::{add_stanza_id, Packet, XmppStream}; -use crate::Error; +use crate::{ + component::login::component_login, + connect::ServerConnector, + proto::{add_stanza_id, XmppStream}, + Error, +}; #[cfg(any(feature = "starttls", feature = "insecure-tcp"))] use crate::connect::DnsConfig; #[cfg(feature = "insecure-tcp")] use crate::connect::TcpServerConnector; -mod auth; - -pub(crate) mod connect; +mod login; +mod stream; /// Component connection to an XMPP server /// @@ -33,20 +31,34 @@ pub struct Component { stream: XmppStream, } +impl Component { + /// Send stanza + pub async fn send_stanza(&mut self, stanza: Element) -> Result<(), Error> { + self.send(add_stanza_id(stanza, ns::COMPONENT_ACCEPT)).await + } + + /// End connection + pub async fn send_end(&mut self) -> Result<(), Error> { + self.close().await + } +} + #[cfg(feature = "insecure-tcp")] impl Component { /// Start a new XMPP component over plaintext TCP to localhost:5347 + #[cfg(feature = "insecure-tcp")] pub async fn new(jid: &str, password: &str) -> Result { Self::new_plaintext(jid, password, DnsConfig::addr("127.0.0.1:5347")).await } /// Start a new XMPP component over plaintext TCP + #[cfg(feature = "insecure-tcp")] pub async fn new_plaintext( jid: &str, password: &str, dns_config: DnsConfig, ) -> Result { - Self::new_with_connector(jid, password, TcpServerConnector::from(dns_config)).await + Component::new_with_connector(jid, password, TcpServerConnector::from(dns_config)).await } } @@ -65,65 +77,4 @@ impl Component { let stream = component_login(connector, jid.clone(), password).await?; Ok(Component { jid, stream }) } - - /// Send stanza - pub async fn send_stanza(&mut self, stanza: Element) -> Result<(), Error> { - self.send(add_stanza_id(stanza, ns::COMPONENT_ACCEPT)).await - } - - /// End connection - pub async fn send_end(&mut self) -> Result<(), Error> { - self.close().await - } -} - -impl Stream for Component { - type Item = Element; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - 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 - } - Poll::Ready(Some(Ok(_))) => - // unexpected - { - return Poll::Ready(None) - } - Poll::Ready(Some(Err(_))) => return Poll::Ready(None), - Poll::Ready(None) => return Poll::Ready(None), - Poll::Pending => return Poll::Pending, - } - } - } -} - -impl Sink for Component { - type Error = Error; - - 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()) - } - - fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - 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> { - 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> { - Pin::new(&mut self.stream) - .poll_close(cx) - .map_err(|e| e.into()) - } } diff --git a/tokio-xmpp/src/component/stream.rs b/tokio-xmpp/src/component/stream.rs new file mode 100644 index 0000000000000000000000000000000000000000..3ae62c050595ded87aa35bcec48234a835409706 --- /dev/null +++ b/tokio-xmpp/src/component/stream.rs @@ -0,0 +1,60 @@ +//! 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. +use futures::{task::Poll, Sink, Stream}; +use minidom::Element; +use std::pin::Pin; +use std::task::Context; + +use crate::{component::Component, connect::ServerConnector, proto::Packet, Error}; + +impl Stream for Component { + type Item = Element; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + 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 + } + Poll::Ready(Some(Ok(_))) => + // unexpected + { + return Poll::Ready(None) + } + Poll::Ready(Some(Err(_))) => return Poll::Ready(None), + Poll::Ready(None) => return Poll::Ready(None), + Poll::Pending => return Poll::Pending, + } + } + } +} + +impl Sink for Component { + type Error = Error; + + 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()) + } + + fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + 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> { + 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> { + Pin::new(&mut self.stream) + .poll_close(cx) + .map_err(|e| e.into()) + } +}