Only expose one error type in crate root

xmppftw created

Change summary

tokio-xmpp/ChangeLog                      |  4 +++
tokio-xmpp/src/connect.rs                 |  7 ++---
tokio-xmpp/src/starttls/error.rs          | 27 ++++++++++--------------
tokio-xmpp/src/starttls/happy_eyeballs.rs | 25 ++++++++++------------
tokio-xmpp/src/starttls/mod.rs            | 19 +++++++----------
tokio-xmpp/src/tcp/mod.rs                 | 13 ++---------
6 files changed, 40 insertions(+), 55 deletions(-)

Detailed changes

tokio-xmpp/ChangeLog 🔗

@@ -7,6 +7,10 @@ XXXX-YY-ZZ RELEASER <admin@example.com>
         which was not used and has been completely removed (!418)
       - `ProtocolError` and `AuthError` are no longer exported in crate root;
         access them from `error` module (!423)
+      - `connect::ServerConnector` no longer has `Error` associated type, the methods return tokio_xmpp::Error directly,
+        where Connection variant contains any error type that implements connect::ServerConnectorError (!421)
+      - `starttls::Error` no longer has `TokioXMPP` variant ; only tokio_xmpp::Error can contain starttls::Error,
+        not the other way around (!421)
 
 Version 4.0.0:
 2024-07-26 Maxime “pep” Buquet <pep@bouah.net>

tokio-xmpp/src/connect.rs 🔗

@@ -5,6 +5,7 @@ use tokio::io::{AsyncRead, AsyncWrite};
 use xmpp_parsers::jid::Jid;
 
 use crate::xmpp_stream::XMPPStream;
+use crate::Error;
 
 /// trait returned wrapped in XMPPStream by ServerConnector
 pub trait AsyncReadAndWrite: AsyncRead + AsyncWrite + Unpin + Send {}
@@ -17,19 +18,17 @@ pub trait ServerConnectorError: std::error::Error + Sync + Send {}
 pub trait ServerConnector: Clone + core::fmt::Debug + Send + Unpin + 'static {
     /// The type of Stream this ServerConnector produces
     type Stream: AsyncReadAndWrite;
-    /// Error type to return
-    type Error: ServerConnectorError;
     /// This must return the connection ready to login, ie if starttls is involved, after TLS has been started, and then after the <stream headers are exchanged
     fn connect(
         &self,
         jid: &Jid,
         ns: &str,
-    ) -> impl std::future::Future<Output = Result<XMPPStream<Self::Stream>, Self::Error>> + Send;
+    ) -> impl std::future::Future<Output = Result<XMPPStream<Self::Stream>, Error>> + Send;
 
     /// Return channel binding data if available
     /// do not fail if channel binding is simply unavailable, just return Ok(None)
     /// this should only be called after the TLS handshake is finished
-    fn channel_binding(_stream: &Self::Stream) -> Result<ChannelBinding, Self::Error> {
+    fn channel_binding(_stream: &Self::Stream) -> Result<ChannelBinding, Error> {
         Ok(ChannelBinding::None)
     }
 }

tokio-xmpp/src/starttls/error.rs 🔗

@@ -10,6 +10,8 @@ use tokio_rustls::rustls::pki_types::InvalidDnsNameError;
 #[cfg(all(feature = "tls-rust", not(feature = "tls-native")))]
 use tokio_rustls::rustls::Error as TlsError;
 
+use super::ServerConnectorError;
+
 /// StartTLS ServerConnector Error
 #[derive(Debug)]
 pub enum Error {
@@ -25,41 +27,34 @@ pub enum Error {
     #[cfg(all(feature = "tls-rust", not(feature = "tls-native")))]
     /// DNS name parsing error
     DnsNameError(InvalidDnsNameError),
-    /// tokio-xmpp error
-    TokioXMPP(crate::error::Error),
 }
 
+impl ServerConnectorError for Error {}
+
 impl fmt::Display for Error {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Error::Dns(e) => write!(fmt, "{:?}", e),
-            Error::Resolve(e) => write!(fmt, "{:?}", e),
-            Error::Idna => write!(fmt, "IDNA error"),
-            Error::Tls(e) => write!(fmt, "TLS error: {}", e),
+            Self::Dns(e) => write!(fmt, "{:?}", e),
+            Self::Resolve(e) => write!(fmt, "{:?}", e),
+            Self::Idna => write!(fmt, "IDNA error"),
+            Self::Tls(e) => write!(fmt, "TLS error: {}", e),
             #[cfg(all(feature = "tls-rust", not(feature = "tls-native")))]
-            Error::DnsNameError(e) => write!(fmt, "DNS name error: {}", e),
-            Error::TokioXMPP(e) => write!(fmt, "TokioXMPP error: {}", e),
+            Self::DnsNameError(e) => write!(fmt, "DNS name error: {}", e),
         }
     }
 }
 
 impl StdError for Error {}
 
-impl From<crate::error::Error> for Error {
-    fn from(e: crate::error::Error) -> Self {
-        Error::TokioXMPP(e)
-    }
-}
-
 impl From<TlsError> for Error {
     fn from(e: TlsError) -> Self {
-        Error::Tls(e)
+        Self::Tls(e)
     }
 }
 
 #[cfg(all(feature = "tls-rust", not(feature = "tls-native")))]
 impl From<InvalidDnsNameError> for Error {
     fn from(e: InvalidDnsNameError) -> Self {
-        Error::DnsNameError(e)
+        Self::DnsNameError(e)
     }
 }

tokio-xmpp/src/starttls/happy_eyeballs.rs 🔗

@@ -1,4 +1,5 @@
-use super::error::Error;
+use super::error::Error as StartTlsError;
+use crate::Error;
 use futures::{future::select_ok, FutureExt};
 use hickory_resolver::{
     config::LookupIpStrategy, name_server::TokioConnectionProvider, IntoName, TokioAsyncResolver,
@@ -8,23 +9,21 @@ use std::net::SocketAddr;
 use tokio::net::TcpStream;
 
 pub async fn connect_to_host(domain: &str, port: u16) -> Result<TcpStream, Error> {
-    let ascii_domain = idna::domain_to_ascii(&domain).map_err(|_| Error::Idna)?;
+    let ascii_domain = idna::domain_to_ascii(&domain).map_err(|_| StartTlsError::Idna)?;
 
     if let Ok(ip) = ascii_domain.parse() {
-        return Ok(TcpStream::connect(&SocketAddr::new(ip, port))
-            .await
-            .map_err(|e| Error::from(crate::Error::Io(e)))?);
+        return Ok(TcpStream::connect(&SocketAddr::new(ip, port)).await?);
     }
 
     let (config, mut options) =
-        hickory_resolver::system_conf::read_system_conf().map_err(Error::Resolve)?;
+        hickory_resolver::system_conf::read_system_conf().map_err(StartTlsError::Resolve)?;
     options.ip_strategy = LookupIpStrategy::Ipv4AndIpv6;
     let resolver = TokioAsyncResolver::new(config, options, TokioConnectionProvider::default());
 
     let ips = resolver
         .lookup_ip(ascii_domain)
         .await
-        .map_err(Error::Resolve)?;
+        .map_err(StartTlsError::Resolve)?;
     // Happy Eyeballs: connect to all records in parallel, return the
     // first to succeed
     select_ok(
@@ -33,7 +32,7 @@ pub async fn connect_to_host(domain: &str, port: u16) -> Result<TcpStream, Error
     )
     .await
     .map(|(result, _)| result)
-    .map_err(|_| crate::Error::Disconnected.into())
+    .map_err(|_| crate::Error::Disconnected)
 }
 
 pub async fn connect_with_srv(
@@ -41,20 +40,18 @@ pub async fn connect_with_srv(
     srv: &str,
     fallback_port: u16,
 ) -> Result<TcpStream, Error> {
-    let ascii_domain = idna::domain_to_ascii(&domain).map_err(|_| Error::Idna)?;
+    let ascii_domain = idna::domain_to_ascii(&domain).map_err(|_| StartTlsError::Idna)?;
 
     if let Ok(ip) = ascii_domain.parse() {
         debug!("Attempting connection to {ip}:{fallback_port}");
-        return Ok(TcpStream::connect(&SocketAddr::new(ip, fallback_port))
-            .await
-            .map_err(|e| Error::from(crate::Error::Io(e)))?);
+        return Ok(TcpStream::connect(&SocketAddr::new(ip, fallback_port)).await?);
     }
 
-    let resolver = TokioAsyncResolver::tokio_from_system_conf().map_err(Error::Resolve)?;
+    let resolver = TokioAsyncResolver::tokio_from_system_conf().map_err(StartTlsError::Resolve)?;
 
     let srv_domain = format!("{}.{}.", srv, ascii_domain)
         .into_name()
-        .map_err(Error::Dns)?;
+        .map_err(StartTlsError::Dns)?;
     let srv_records = resolver.srv_lookup(srv_domain.clone()).await.ok();
 
     match srv_records {

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

@@ -28,10 +28,11 @@ use tokio::{
 use xmpp_parsers::{jid::Jid, ns};
 
 use crate::error::ProtocolError;
+use crate::Error;
 use crate::{connect::ServerConnector, xmpp_codec::Packet, AsyncClient, SimpleClient};
 use crate::{connect::ServerConnectorError, xmpp_stream::XMPPStream};
 
-use self::error::Error;
+use self::error::Error as StartTlsError;
 use self::happy_eyeballs::{connect_to_host, connect_with_srv};
 
 mod client;
@@ -58,11 +59,8 @@ pub enum ServerConfig {
     },
 }
 
-impl ServerConnectorError for Error {}
-
 impl ServerConnector for ServerConfig {
     type Stream = TlsStream<TcpStream>;
-    type Error = Error;
     async fn connect(&self, jid: &Jid, ns: &str) -> Result<XMPPStream<Self::Stream>, Error> {
         // TCP connection
         let tcp_stream = match self {
@@ -100,11 +98,9 @@ impl ServerConnector for ServerConfig {
                 // TODO: Add support for TLS 1.2 and earlier.
                 Some(tokio_rustls::rustls::ProtocolVersion::TLSv1_3) => {
                     let data = vec![0u8; 32];
-                    let data = connection.export_keying_material(
-                        data,
-                        b"EXPORTER-Channel-Binding",
-                        None,
-                    )?;
+                    let data = connection
+                        .export_keying_material(data, b"EXPORTER-Channel-Binding", None)
+                        .map_err(|e| StartTlsError::Tls(e))?;
                     ChannelBinding::TlsExporter(data)
                 }
                 _ => ChannelBinding::None,
@@ -121,7 +117,8 @@ async fn get_tls_stream<S: AsyncRead + AsyncWrite + Unpin>(
     let stream = xmpp_stream.into_inner();
     let tls_stream = TlsConnector::from(NativeTlsConnector::builder().build().unwrap())
         .connect(&domain, stream)
-        .await?;
+        .await
+        .map_err(|e| StartTlsError::Tls(e))?;
     Ok(tls_stream)
 }
 
@@ -130,7 +127,7 @@ async fn get_tls_stream<S: AsyncRead + AsyncWrite + Unpin>(
     xmpp_stream: XMPPStream<S>,
 ) -> Result<TlsStream<S>, Error> {
     let domain = xmpp_stream.jid.domain().to_string();
-    let domain = ServerName::try_from(domain)?;
+    let domain = ServerName::try_from(domain).map_err(|e| StartTlsError::DnsNameError(e))?;
     let stream = xmpp_stream.into_inner();
     let root_store = RootCertStore {
         roots: webpki_roots::TLS_SERVER_ROOTS.into(),

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

@@ -4,13 +4,9 @@ use std::sync::Arc;
 
 use tokio::net::TcpStream;
 
-use crate::{
-    connect::{ServerConnector, ServerConnectorError},
-    xmpp_stream::XMPPStream,
-    Component,
-};
+use crate::{connect::ServerConnector, xmpp_stream::XMPPStream, Component};
 
-use self::error::Error;
+use crate::Error;
 
 mod component;
 pub mod error;
@@ -31,16 +27,13 @@ impl TcpServerConnector {
     }
 }
 
-impl ServerConnectorError for Error {}
-
 impl ServerConnector for TcpServerConnector {
     type Stream = TcpStream;
-    type Error = Error;
     async fn connect(
         &self,
         jid: &xmpp_parsers::jid::Jid,
         ns: &str,
-    ) -> Result<XMPPStream<Self::Stream>, Self::Error> {
+    ) -> Result<XMPPStream<Self::Stream>, Error> {
         let stream = TcpStream::connect(&*self.0)
             .await
             .map_err(|e| crate::Error::Io(e))?;