diff --git a/tokio-xmpp/ChangeLog b/tokio-xmpp/ChangeLog index 205f2af9731c3a99102962bfa2f842f78e4f2a4a..756fb2238e7496ccd82eca4bb664942ee696cdd9 100644 --- a/tokio-xmpp/ChangeLog +++ b/tokio-xmpp/ChangeLog @@ -7,6 +7,10 @@ XXXX-YY-ZZ RELEASER 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 diff --git a/tokio-xmpp/src/connect.rs b/tokio-xmpp/src/connect.rs index ebd1781f725d22e95fcb77faa73ce6ac55c7cf23..d72b36762f08b8d7b01c3bf0890dff917f08720a 100644 --- a/tokio-xmpp/src/connect.rs +++ b/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 impl std::future::Future, Self::Error>> + Send; + ) -> impl std::future::Future, 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 { + fn channel_binding(_stream: &Self::Stream) -> Result { Ok(ChannelBinding::None) } } diff --git a/tokio-xmpp/src/starttls/error.rs b/tokio-xmpp/src/starttls/error.rs index cab2dc943c542f3a9eb463f93b24efe7cd5978c5..5de28217692531adf5a445563b9fb2681c1a81e5 100644 --- a/tokio-xmpp/src/starttls/error.rs +++ b/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 for Error { - fn from(e: crate::error::Error) -> Self { - Error::TokioXMPP(e) - } -} - impl From for Error { fn from(e: TlsError) -> Self { - Error::Tls(e) + Self::Tls(e) } } #[cfg(all(feature = "tls-rust", not(feature = "tls-native")))] impl From for Error { fn from(e: InvalidDnsNameError) -> Self { - Error::DnsNameError(e) + Self::DnsNameError(e) } } diff --git a/tokio-xmpp/src/starttls/happy_eyeballs.rs b/tokio-xmpp/src/starttls/happy_eyeballs.rs index 8a73297c40dea93bf3f8a708ac483c7c070909c8..0ce5c8eafe5b2af8e70a85755bf106ae936f4f9d 100644 --- a/tokio-xmpp/src/starttls/happy_eyeballs.rs +++ b/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 { - 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 Result { - 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 { diff --git a/tokio-xmpp/src/starttls/mod.rs b/tokio-xmpp/src/starttls/mod.rs index 277d0905507043d0f3445b38cfa03e076dd179aa..673fc96f47c117357b9dc6acabd3e9b2b9ad5979 100644 --- a/tokio-xmpp/src/starttls/mod.rs +++ b/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; - type Error = Error; async fn connect(&self, jid: &Jid, ns: &str) -> Result, 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( 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( xmpp_stream: XMPPStream, ) -> Result, 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(), diff --git a/tokio-xmpp/src/tcp/mod.rs b/tokio-xmpp/src/tcp/mod.rs index 321ceca337be8f778a242d0bbf5149e00ca8566b..508d76273830c40d381b1e39dfa1cb9744087e4f 100644 --- a/tokio-xmpp/src/tcp/mod.rs +++ b/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, Self::Error> { + ) -> Result, Error> { let stream = TcpStream::connect(&*self.0) .await .map_err(|e| crate::Error::Io(e))?;