Reorganized client modules

xmppftw created

Change summary

tokio-xmpp/src/client/connect.rs |  37 --------
tokio-xmpp/src/client/login.rs   |  37 ++++++++
tokio-xmpp/src/client/mod.rs     | 143 +++++++++++++++++++++++++++++++++
tokio-xmpp/src/client/stream.rs  | 139 +-------------------------------
tokio-xmpp/src/lib.rs            |   5 
5 files changed, 183 insertions(+), 178 deletions(-)

Detailed changes

tokio-xmpp/src/client/connect.rs 🔗

@@ -1,37 +0,0 @@
-use sasl::common::Credentials;
-use xmpp_parsers::{jid::Jid, ns};
-
-use crate::{
-    client::{auth::auth, bind::bind},
-    connect::ServerConnector,
-    proto::XmppStream,
-    Error,
-};
-
-/// Log into an XMPP server as a client with a jid+pass
-/// does channel binding if supported
-pub async fn client_login<C: ServerConnector>(
-    server: C,
-    jid: Jid,
-    password: String,
-) -> Result<XmppStream<C::Stream>, Error> {
-    let username = jid.node().unwrap().as_str();
-    let password = password;
-
-    let xmpp_stream = server.connect(&jid, ns::JABBER_CLIENT).await?;
-
-    let channel_binding = C::channel_binding(xmpp_stream.stream.get_ref())?;
-
-    let creds = Credentials::default()
-        .with_username(username)
-        .with_password(password)
-        .with_channel_binding(channel_binding);
-    // Authenticated (unspecified) stream
-    let stream = auth(xmpp_stream, creds).await?;
-    // Authenticated XmppStream
-    let xmpp_stream = XmppStream::start(stream, jid, ns::JABBER_CLIENT.to_owned()).await?;
-
-    // XmppStream bound to user session
-    let xmpp_stream = bind(xmpp_stream).await?;
-    Ok(xmpp_stream)
-}

tokio-xmpp/src/client/auth.rs → tokio-xmpp/src/client/login.rs 🔗

@@ -7,9 +7,14 @@ use std::collections::HashSet;
 use std::str::FromStr;
 use tokio::io::{AsyncRead, AsyncWrite};
 use xmpp_parsers::sasl::{Auth, Challenge, Failure, Mechanism as XMPPMechanism, Response, Success};
+use xmpp_parsers::{jid::Jid, ns};
 
-use crate::error::{AuthError, Error, ProtocolError};
-use crate::proto::{Packet, XmppStream};
+use crate::{
+    client::bind::bind,
+    connect::ServerConnector,
+    error::{AuthError, Error, ProtocolError},
+    proto::{Packet, XmppStream},
+};
 
 pub async fn auth<S: AsyncRead + AsyncWrite + Unpin>(
     mut stream: XmppStream<S>,
@@ -82,3 +87,31 @@ pub async fn auth<S: AsyncRead + AsyncWrite + Unpin>(
 
     Err(AuthError::NoMechanism.into())
 }
+
+/// Log into an XMPP server as a client with a jid+pass
+/// does channel binding if supported
+pub async fn client_login<C: ServerConnector>(
+    server: C,
+    jid: Jid,
+    password: String,
+) -> Result<XmppStream<C::Stream>, Error> {
+    let username = jid.node().unwrap().as_str();
+    let password = password;
+
+    let xmpp_stream = server.connect(&jid, ns::JABBER_CLIENT).await?;
+
+    let channel_binding = C::channel_binding(xmpp_stream.stream.get_ref())?;
+
+    let creds = Credentials::default()
+        .with_username(username)
+        .with_password(password)
+        .with_channel_binding(channel_binding);
+    // Authenticated (unspecified) stream
+    let stream = auth(xmpp_stream, creds).await?;
+    // Authenticated XmppStream
+    let xmpp_stream = XmppStream::start(stream, jid, ns::JABBER_CLIENT.to_owned()).await?;
+
+    // XmppStream bound to user session
+    let xmpp_stream = bind(xmpp_stream).await?;
+    Ok(xmpp_stream)
+}

tokio-xmpp/src/client/mod.rs 🔗

@@ -1,6 +1,143 @@
-mod auth;
+use futures::sink::SinkExt;
+use minidom::Element;
+use xmpp_parsers::{jid::Jid, ns, stream_features::StreamFeatures};
+
+use crate::{
+    client::{login::client_login, stream::ClientState},
+    connect::ServerConnector,
+    error::Error,
+    proto::{add_stanza_id, Packet},
+};
+
+#[cfg(any(feature = "starttls", feature = "insecure-tcp"))]
+use crate::connect::DnsConfig;
+#[cfg(feature = "starttls")]
+use crate::connect::StartTlsServerConnector;
+#[cfg(feature = "insecure-tcp")]
+use crate::connect::TcpServerConnector;
+
 mod bind;
+mod login;
+mod stream;
+
+/// XMPP client connection and state
+///
+/// It is able to reconnect. TODO: implement session management.
+///
+/// This implements the `futures` crate's [`Stream`](#impl-Stream) and
+/// [`Sink`](#impl-Sink<Packet>) traits.
+pub struct Client<C: ServerConnector> {
+    jid: Jid,
+    password: String,
+    connector: C,
+    state: ClientState<C::Stream>,
+    reconnect: bool,
+    // TODO: tls_required=true
+}
+
+impl<C: ServerConnector> Client<C> {
+    /// Set whether to reconnect (`true`) or let the stream end
+    /// (`false`) when a connection to the server has ended.
+    pub fn set_reconnect(&mut self, reconnect: bool) -> &mut Self {
+        self.reconnect = reconnect;
+        self
+    }
+
+    /// Get the client's bound JID (the one reported by the XMPP
+    /// server).
+    pub fn bound_jid(&self) -> Option<&Jid> {
+        match self.state {
+            ClientState::Connected(ref stream) => Some(&stream.jid),
+            _ => None,
+        }
+    }
+
+    /// Send stanza
+    pub async fn send_stanza(&mut self, stanza: Element) -> Result<(), Error> {
+        self.send(Packet::Stanza(add_stanza_id(stanza, ns::JABBER_CLIENT)))
+            .await
+    }
+
+    /// Get the stream features (`<stream:features/>`) of the underlying stream
+    pub fn get_stream_features(&self) -> Option<&StreamFeatures> {
+        match self.state {
+            ClientState::Connected(ref stream) => Some(&stream.stream_features),
+            _ => None,
+        }
+    }
+
+    /// End connection by sending `</stream:stream>`
+    ///
+    /// You may expect the server to respond with the same. This
+    /// client will then drop its connection.
+    ///
+    /// Make sure to disable reconnect.
+    pub async fn send_end(&mut self) -> Result<(), Error> {
+        self.send(Packet::StreamEnd).await
+    }
+}
+
+#[cfg(feature = "starttls")]
+impl Client<StartTlsServerConnector> {
+    /// Start a new XMPP client using StartTLS transport and autoreconnect
+    ///
+    /// Start polling the returned instance so that it will connect
+    /// and yield events.
+    pub fn new<J: Into<Jid>, P: Into<String>>(jid: J, password: P) -> Self {
+        let jid = jid.into();
+        let mut client = Self::new_starttls(
+            jid.clone(),
+            password,
+            DnsConfig::srv(&jid.domain().to_string(), "_xmpp-client._tcp", 5222),
+        );
+        client.set_reconnect(true);
+        client
+    }
+
+    /// Start a new XMPP client with StartTLS transport and specific DNS config
+    pub fn new_starttls<J: Into<Jid>, P: Into<String>>(
+        jid: J,
+        password: P,
+        dns_config: DnsConfig,
+    ) -> Self {
+        Self::new_with_connector(jid, password, StartTlsServerConnector::from(dns_config))
+    }
+}
+
+#[cfg(feature = "insecure-tcp")]
+impl Client<TcpServerConnector> {
+    /// Start a new XMPP client with plaintext insecure connection and specific DNS config
+    pub fn new_plaintext<J: Into<Jid>, P: Into<String>>(
+        jid: J,
+        password: P,
+        dns_config: DnsConfig,
+    ) -> Self {
+        Self::new_with_connector(jid, password, TcpServerConnector::from(dns_config))
+    }
+}
 
-pub(crate) mod connect;
+impl<C: ServerConnector> Client<C> {
+    /// Start a new client given that the JID is already parsed.
+    pub fn new_with_connector<J: Into<Jid>, P: Into<String>>(
+        jid: J,
+        password: P,
+        connector: C,
+    ) -> Self {
+        let jid = jid.into();
+        let password = password.into();
 
-pub mod async_client;
+        let connect = tokio::spawn(client_login(
+            connector.clone(),
+            jid.clone(),
+            password.clone(),
+        ));
+        let client = Client {
+            jid,
+            password,
+            connector,
+            state: ClientState::Connecting(connect),
+            reconnect: false,
+        };
+        client
+    }
+}

tokio-xmpp/src/client/async_client.rs → tokio-xmpp/src/client/stream.rs 🔗

@@ -1,153 +1,24 @@
-use futures::{sink::SinkExt, task::Poll, Future, Sink, Stream};
-use minidom::Element;
+use futures::{task::Poll, Future, Sink, Stream};
 use std::mem::replace;
 use std::pin::Pin;
 use std::task::Context;
 use tokio::task::JoinHandle;
-use xmpp_parsers::{jid::Jid, ns, stream_features::StreamFeatures};
 
 use crate::{
-    client::connect::client_login,
+    client::login::client_login,
     connect::{AsyncReadAndWrite, ServerConnector},
     error::{Error, ProtocolError},
-    proto::{add_stanza_id, Packet, XmppStream},
-    Event,
+    proto::{Packet, XmppStream},
+    Client, Event,
 };
 
-#[cfg(any(feature = "starttls", feature = "insecure-tcp"))]
-use crate::connect::DnsConfig;
-#[cfg(feature = "starttls")]
-use crate::connect::StartTlsServerConnector;
-#[cfg(feature = "insecure-tcp")]
-use crate::connect::TcpServerConnector;
-
-/// XMPP client connection and state
-///
-/// It is able to reconnect. TODO: implement session management.
-///
-/// This implements the `futures` crate's [`Stream`](#impl-Stream) and
-/// [`Sink`](#impl-Sink<Packet>) traits.
-pub struct Client<C: ServerConnector> {
-    jid: Jid,
-    password: String,
-    connector: C,
-    state: ClientState<C::Stream>,
-    reconnect: bool,
-    // TODO: tls_required=true
-}
-
-enum ClientState<S: AsyncReadAndWrite> {
+pub(crate) enum ClientState<S: AsyncReadAndWrite> {
     Invalid,
     Disconnected,
     Connecting(JoinHandle<Result<XmppStream<S>, Error>>),
     Connected(XmppStream<S>),
 }
 
-#[cfg(feature = "starttls")]
-impl Client<StartTlsServerConnector> {
-    /// Start a new XMPP client using StartTLS transport and autoreconnect
-    ///
-    /// Start polling the returned instance so that it will connect
-    /// and yield events.
-    pub fn new<J: Into<Jid>, P: Into<String>>(jid: J, password: P) -> Self {
-        let jid = jid.into();
-        let mut client = Self::new_starttls(
-            jid.clone(),
-            password,
-            DnsConfig::srv(&jid.domain().to_string(), "_xmpp-client._tcp", 5222),
-        );
-        client.set_reconnect(true);
-        client
-    }
-
-    /// Start a new XMPP client with StartTLS transport and specific DNS config
-    pub fn new_starttls<J: Into<Jid>, P: Into<String>>(
-        jid: J,
-        password: P,
-        dns_config: DnsConfig,
-    ) -> Self {
-        Self::new_with_connector(jid, password, StartTlsServerConnector::from(dns_config))
-    }
-}
-
-#[cfg(feature = "insecure-tcp")]
-impl Client<TcpServerConnector> {
-    /// Start a new XMPP client with plaintext insecure connection and specific DNS config
-    pub fn new_plaintext<J: Into<Jid>, P: Into<String>>(
-        jid: J,
-        password: P,
-        dns_config: DnsConfig,
-    ) -> Self {
-        Self::new_with_connector(jid, password, TcpServerConnector::from(dns_config))
-    }
-}
-
-impl<C: ServerConnector> Client<C> {
-    /// Start a new client given that the JID is already parsed.
-    pub fn new_with_connector<J: Into<Jid>, P: Into<String>>(
-        jid: J,
-        password: P,
-        connector: C,
-    ) -> Self {
-        let jid = jid.into();
-        let password = password.into();
-
-        let connect = tokio::spawn(client_login(
-            connector.clone(),
-            jid.clone(),
-            password.clone(),
-        ));
-        let client = Client {
-            jid,
-            password,
-            connector,
-            state: ClientState::Connecting(connect),
-            reconnect: false,
-        };
-        client
-    }
-
-    /// Set whether to reconnect (`true`) or let the stream end
-    /// (`false`) when a connection to the server has ended.
-    pub fn set_reconnect(&mut self, reconnect: bool) -> &mut Self {
-        self.reconnect = reconnect;
-        self
-    }
-
-    /// Get the client's bound JID (the one reported by the XMPP
-    /// server).
-    pub fn bound_jid(&self) -> Option<&Jid> {
-        match self.state {
-            ClientState::Connected(ref stream) => Some(&stream.jid),
-            _ => None,
-        }
-    }
-
-    /// Send stanza
-    pub async fn send_stanza(&mut self, stanza: Element) -> Result<(), Error> {
-        self.send(Packet::Stanza(add_stanza_id(stanza, ns::JABBER_CLIENT)))
-            .await
-    }
-
-    /// Get the stream features (`<stream:features/>`) of the underlying stream
-    pub fn get_stream_features(&self) -> Option<&StreamFeatures> {
-        match self.state {
-            ClientState::Connected(ref stream) => Some(&stream.stream_features),
-            _ => None,
-        }
-    }
-
-    /// End connection by sending `</stream:stream>`
-    ///
-    /// You may expect the server to respond with the same. This
-    /// client will then drop its connection.
-    ///
-    /// Make sure to disable reconnect.
-    pub async fn send_end(&mut self) -> Result<(), Error> {
-        self.send(Packet::StreamEnd).await
-    }
-}
-
 /// Incoming XMPP events
 ///
 /// In an `async fn` you may want to use this with `use

tokio-xmpp/src/lib.rs 🔗

@@ -48,16 +48,17 @@ compile_error!(
 
 mod event;
 pub use event::Event;
-mod client;
 pub mod connect;
 pub mod proto;
 
-pub use client::async_client::Client;
+mod client;
+pub use client::Client;
 
 #[cfg(feature = "insecure-tcp")]
 mod component;
 #[cfg(feature = "insecure-tcp")]
 pub use crate::component::Component;
+
 /// Detailed error types
 pub mod error;