From 311e7406f051c86fd36410728ac3598572aa2b6f Mon Sep 17 00:00:00 2001 From: xmppftw Date: Tue, 6 Aug 2024 20:40:24 +0200 Subject: [PATCH] Make Client and Component more unified, and connectors too --- tokio-xmpp/ChangeLog | 5 + tokio-xmpp/examples/echo_component.rs | 21 ++-- tokio-xmpp/src/client/async_client.rs | 84 ++++++++----- tokio-xmpp/src/component/mod.rs | 36 ++++++ tokio-xmpp/src/connect/dns.rs | 173 ++++++++++++++++++++++++++ tokio-xmpp/src/connect/mod.rs | 93 ++------------ tokio-xmpp/src/connect/starttls.rs | 43 +++---- tokio-xmpp/src/connect/tcp.rs | 29 ++--- tokio-xmpp/src/error.rs | 10 ++ tokio-xmpp/src/lib.rs | 2 +- xmpp/src/builder.rs | 25 ++-- 11 files changed, 338 insertions(+), 183 deletions(-) create mode 100644 tokio-xmpp/src/connect/dns.rs diff --git a/tokio-xmpp/ChangeLog b/tokio-xmpp/ChangeLog index e1824a298fd06a7038036e22e7d97e7d369e5a37..04a32b0f57e111283993c69947fc6e56b424a48a 100644 --- a/tokio-xmpp/ChangeLog +++ b/tokio-xmpp/ChangeLog @@ -17,6 +17,11 @@ XXXX-YY-ZZ RELEASER please let us know and it will be reintegrated (!428) - `XMPPStream` was renamed `XmppStream` and is now published as `tokio_xmpp::proto::XmppStream` (!428) - `XmppCodec` was moved to proto module and is now published as `tokio_xmpp::proto::XmppCodec` (!428) + - `Component::new` and `Client::new only require jid/password argument (!428) + - `ServerConfig` and `Client::new_with_config` have been removed (!428) + - `Component` and `Client` now have `new_plaintext`, `new_starttls` and `new_with_connector` methods with same signature (!428) + `new_plaintext` and `new_starttls` take a DnsConfig struct for SRV/DNS resolution strategy, while `new_with_connector` takes + anything that implements ServerConnector Version 4.0.0: 2024-07-26 Maxime “pep” Buquet diff --git a/tokio-xmpp/examples/echo_component.rs b/tokio-xmpp/examples/echo_component.rs index 40502c267b60a3fbad0cecf7a1758041b9d577dd..87481140705365587570e9e279f03eb0fcb4eccf 100644 --- a/tokio-xmpp/examples/echo_component.rs +++ b/tokio-xmpp/examples/echo_component.rs @@ -3,11 +3,12 @@ use minidom::Element; use std::env::args; use std::process::exit; use std::str::FromStr; -use tokio_xmpp::connect::tcp::TcpComponent as Component; use xmpp_parsers::jid::Jid; use xmpp_parsers::message::{Body, Message, MessageType}; use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; +use tokio_xmpp::{connect::DnsConfig, Component}; + #[tokio::main] async fn main() { env_logger::init(); @@ -19,15 +20,21 @@ async fn main() { } let jid = &args[1]; let password = &args[2]; - let server = args - .get(3) - .unwrap() - .parse() - .unwrap_or("127.0.0.1:5347".to_owned()); + + let server = if let Some(server) = args.get(3) { + DnsConfig::addr(server) + } else { + DnsConfig::no_srv("127.0.0.1", 5347) + }; // Component instance println!("{} {} {}", jid, password, server); - let mut component = Component::new(jid, password, server).await.unwrap(); + + // If you don't need a custom server but default localhost:5347, you can use + // Component::new() directly + let mut component = Component::new_plaintext(jid, password, server) + .await + .unwrap(); // Make the two interfaces for sending and receiving independent // of each other so we can move one into a closure. diff --git a/tokio-xmpp/src/client/async_client.rs b/tokio-xmpp/src/client/async_client.rs index 5b74ec74b1c9558c101b5082793321890ee2e0d4..27dfef808cd0be6d4f26fc767f6446f4ba680353 100644 --- a/tokio-xmpp/src/client/async_client.rs +++ b/tokio-xmpp/src/client/async_client.rs @@ -14,10 +14,12 @@ use crate::{ Event, }; +#[cfg(any(feature = "starttls", feature = "insecure-tcp"))] +use crate::connect::DnsConfig; #[cfg(feature = "starttls")] -use crate::connect::starttls::ServerConfig; -#[cfg(feature = "starttls")] -use crate::AsyncConfig; +use crate::connect::StartTlsServerConnector; +#[cfg(feature = "insecure-tcp")] +use crate::connect::TcpServerConnector; /// XMPP client connection and state /// @@ -26,23 +28,14 @@ use crate::AsyncConfig; /// This implements the `futures` crate's [`Stream`](#impl-Stream) and /// [`Sink`](#impl-Sink) traits. pub struct Client { - config: Config, + jid: Jid, + password: String, + connector: C, state: ClientState, reconnect: bool, // TODO: tls_required=true } -/// XMPP client configuration -#[derive(Clone, Debug)] -pub struct Config { - /// jid of the account - pub jid: Jid, - /// password of the account - pub password: String, - /// server configuration for the account - pub server: C, -} - enum ClientState { Invalid, Disconnected, @@ -51,34 +44,63 @@ enum ClientState { } #[cfg(feature = "starttls")] -impl Client { +impl Client { /// Start a new XMPP client using StartTLS transport and autoreconnect /// /// Start polling the returned instance so that it will connect /// and yield events. - #[cfg(feature = "starttls")] pub fn new, P: Into>(jid: J, password: P) -> Self { - let config = AsyncConfig { - jid: jid.into(), - password: password.into(), - server: ServerConfig::UseSrv, - }; - let mut client = Self::new_with_config(config); + 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, P: Into>( + jid: J, + password: P, + dns_config: DnsConfig, + ) -> Self { + Self::new_with_connector(jid, password, StartTlsServerConnector::from(dns_config)) + } +} + +#[cfg(feature = "insecure-tcp")] +impl Client { + /// Start a new XMPP client with plaintext insecure connection and specific DNS config + pub fn new_plaintext, P: Into>( + jid: J, + password: P, + dns_config: DnsConfig, + ) -> Self { + Self::new_with_connector(jid, password, TcpServerConnector::from(dns_config)) + } } impl Client { /// Start a new client given that the JID is already parsed. - pub fn new_with_config(config: Config) -> Self { + pub fn new_with_connector, P: Into>( + jid: J, + password: P, + connector: C, + ) -> Self { + let jid = jid.into(); + let password = password.into(); + let connect = tokio::spawn(client_login( - config.server.clone(), - config.jid.clone(), - config.password.clone(), + connector.clone(), + jid.clone(), + password.clone(), )); let client = Client { - config, + jid, + password, + connector, state: ClientState::Connecting(connect), reconnect: false, }; @@ -151,9 +173,9 @@ impl Stream for Client { ClientState::Disconnected if self.reconnect => { // TODO: add timeout let connect = tokio::spawn(client_login( - self.config.server.clone(), - self.config.jid.clone(), - self.config.password.clone(), + self.connector.clone(), + self.jid.clone(), + self.password.clone(), )); self.state = ClientState::Connecting(connect); self.poll_next(cx) diff --git a/tokio-xmpp/src/component/mod.rs b/tokio-xmpp/src/component/mod.rs index 0a51362d0edba173e066b8ff64b8f0464969caa5..e66e966441936b0bb21d0a1cbc3e8de6b5a3a363 100644 --- a/tokio-xmpp/src/component/mod.rs +++ b/tokio-xmpp/src/component/mod.rs @@ -14,6 +14,13 @@ use crate::connect::ServerConnector; use crate::proto::{add_stanza_id, Packet, XmppStream}; use crate::Error; +#[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 auth; pub(crate) mod connect; @@ -28,6 +35,35 @@ pub struct Component { stream: XmppStream, } +#[cfg(feature = "insecure-tcp")] +impl Component { + /// Start a new XMPP component over plaintext TCP to localhost:5347 + 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 + pub async fn new_plaintext( + jid: &str, + password: &str, + dns_config: DnsConfig, + ) -> Result { + Self::new_with_connector(jid, password, TcpServerConnector::from(dns_config)).await + } +} + +#[cfg(feature = "starttls")] +impl Component { + /// Start a new XMPP component over StartTLS + pub async fn new_starttls( + jid: &str, + password: &str, + dns_config: DnsConfig, + ) -> Result { + Self::new_with_connector(jid, password, StartTlsServerConnector::from(dns_config)).await + } +} + impl Component { /// Start a new XMPP component pub async fn new_with_connector( diff --git a/tokio-xmpp/src/connect/dns.rs b/tokio-xmpp/src/connect/dns.rs new file mode 100644 index 0000000000000000000000000000000000000000..df896d66e70d07d445bb869f47c625afbe2005f8 --- /dev/null +++ b/tokio-xmpp/src/connect/dns.rs @@ -0,0 +1,173 @@ +#[cfg(feature = "dns")] +use futures::{future::select_ok, FutureExt}; +#[cfg(feature = "dns")] +use hickory_resolver::{ + config::LookupIpStrategy, name_server::TokioConnectionProvider, IntoName, TokioAsyncResolver, +}; +#[cfg(feature = "dns")] +use log::debug; +use std::net::SocketAddr; +use tokio::net::TcpStream; + +use crate::Error; + +/// StartTLS XMPP server connection configuration +#[derive(Clone, Debug)] +pub enum DnsConfig { + /// Use SRV record to find server host + #[cfg(feature = "dns")] + UseSrv { + /// Hostname to resolve + host: String, + /// TXT field eg. _xmpp-client._tcp + srv: String, + /// When SRV resolution fails what port to use + fallback_port: u16, + }, + + /// Manually define server host and port + #[allow(unused)] + #[cfg(feature = "dns")] + NoSrv { + /// Server host name + host: String, + /// Server port + port: u16, + }, + + /// Manually define IP: port (TODO: socket) + #[allow(unused)] + Addr { + /// IP:port + addr: String, + }, +} + +impl std::fmt::Display for DnsConfig { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + #[cfg(feature = "dns")] + Self::UseSrv { host, .. } => write!(f, "{}", host), + #[cfg(feature = "dns")] + Self::NoSrv { host, port } => write!(f, "{}:{}", host, port), + Self::Addr { addr } => write!(f, "{}", addr), + } + } +} + +impl DnsConfig { + /// Constructor for DnsConfig::UseSrv variant + #[cfg(feature = "dns")] + pub fn srv(host: &str, srv: &str, fallback_port: u16) -> Self { + Self::UseSrv { + host: host.to_string(), + srv: srv.to_string(), + fallback_port, + } + } + + /// Constructor for the default SRV resolution strategy for clients + #[cfg(feature = "dns")] + pub fn srv_default_client(host: &str) -> Self { + Self::UseSrv { + host: host.to_string(), + srv: "_xmpp-client._tcp".to_string(), + fallback_port: 5222, + } + } + + /// Constructor for DnsConfig::NoSrv variant + #[cfg(feature = "dns")] + pub fn no_srv(host: &str, port: u16) -> Self { + Self::NoSrv { + host: host.to_string(), + port, + } + } + + /// Constructor for DnsConfig::Addr variant + pub fn addr(addr: &str) -> Self { + Self::Addr { + addr: addr.to_string(), + } + } + + /// Try resolve the DnsConfig to a TcpStream + pub async fn resolve(&self) -> Result { + match self { + #[cfg(feature = "dns")] + Self::UseSrv { + host, + srv, + fallback_port, + } => Self::resolve_srv(host, srv, *fallback_port).await, + #[cfg(feature = "dns")] + Self::NoSrv { host, port } => Self::resolve_no_srv(host, *port).await, + Self::Addr { addr } => { + // TODO: Unix domain socket + let addr: SocketAddr = addr.parse()?; + return Ok(TcpStream::connect(&SocketAddr::new(addr.ip(), addr.port())).await?); + } + } + } + + #[cfg(feature = "dns")] + async fn resolve_srv(host: &str, srv: &str, fallback_port: u16) -> Result { + let ascii_domain = idna::domain_to_ascii(&host)?; + + if let Ok(ip) = ascii_domain.parse() { + debug!("Attempting connection to {ip}:{fallback_port}"); + return Ok(TcpStream::connect(&SocketAddr::new(ip, fallback_port)).await?); + } + + let resolver = TokioAsyncResolver::tokio_from_system_conf()?; + + let srv_domain = format!("{}.{}.", srv, ascii_domain).into_name()?; + let srv_records = resolver.srv_lookup(srv_domain.clone()).await.ok(); + + match srv_records { + Some(lookup) => { + // TODO: sort lookup records by priority/weight + for srv in lookup.iter() { + debug!("Attempting connection to {srv_domain} {srv}"); + if let Ok(stream) = + Self::resolve_no_srv(&srv.target().to_ascii(), srv.port()).await + { + return Ok(stream); + } + } + Err(Error::Disconnected) + } + None => { + // SRV lookup error, retry with hostname + debug!("Attempting connection to {host}:{fallback_port}"); + Self::resolve_no_srv(host, fallback_port).await + } + } + } + + #[cfg(feature = "dns")] + async fn resolve_no_srv(host: &str, port: u16) -> Result { + let ascii_domain = idna::domain_to_ascii(&host)?; + + if let Ok(ip) = ascii_domain.parse() { + return Ok(TcpStream::connect(&SocketAddr::new(ip, port)).await?); + } + + let (config, mut options) = hickory_resolver::system_conf::read_system_conf()?; + options.ip_strategy = LookupIpStrategy::Ipv4AndIpv6; + let resolver = TokioAsyncResolver::new(config, options, TokioConnectionProvider::default()); + + let ips = resolver.lookup_ip(ascii_domain).await?; + + // Happy Eyeballs: connect to all records in parallel, return the + // first to succeed + select_ok( + ips.into_iter() + .map(|ip| TcpStream::connect(SocketAddr::new(ip, port)).boxed()), + ) + .await + .map(|(result, _)| result) + .map_err(|_| Error::Disconnected) + } +} diff --git a/tokio-xmpp/src/connect/mod.rs b/tokio-xmpp/src/connect/mod.rs index 30a2d85025efa81e54055e92763cf18e7079357b..2d7cb5b36eb3766263bbd9761b12f9ca4105ba3c 100644 --- a/tokio-xmpp/src/connect/mod.rs +++ b/tokio-xmpp/src/connect/mod.rs @@ -1,17 +1,7 @@ //! `ServerConnector` provides streams for XMPP clients -#[cfg(feature = "dns")] -use futures::{future::select_ok, FutureExt}; -#[cfg(feature = "dns")] -use hickory_resolver::{ - config::LookupIpStrategy, name_server::TokioConnectionProvider, IntoName, TokioAsyncResolver, -}; -#[cfg(feature = "dns")] -use log::debug; use sasl::common::ChannelBinding; -use std::net::{IpAddr, SocketAddr}; use tokio::io::{AsyncRead, AsyncWrite}; -use tokio::net::TcpStream; use xmpp_parsers::jid::Jid; use crate::proto::XmppStream; @@ -19,8 +9,16 @@ use crate::Error; #[cfg(feature = "starttls")] pub mod starttls; +#[cfg(feature = "starttls")] +pub use starttls::StartTlsServerConnector; + #[cfg(feature = "insecure-tcp")] pub mod tcp; +#[cfg(feature = "insecure-tcp")] +pub use tcp::TcpServerConnector; + +mod dns; +pub use dns::DnsConfig; /// trait returned wrapped in XmppStream by ServerConnector pub trait AsyncReadAndWrite: AsyncRead + AsyncWrite + Unpin + Send {} @@ -47,78 +45,3 @@ pub trait ServerConnector: Clone + core::fmt::Debug + Send + Unpin + 'static { Ok(ChannelBinding::None) } } - -/// A simple wrapper to build [`TcpStream`] -pub struct Tcp; - -impl Tcp { - /// Connect directly to an IP/Port combo - pub async fn connect(ip: IpAddr, port: u16) -> Result { - Ok(TcpStream::connect(&SocketAddr::new(ip, port)).await?) - } - - /// Connect over TCP, resolving A/AAAA records (happy eyeballs) - #[cfg(feature = "dns")] - pub async fn resolve(domain: &str, port: u16) -> Result { - let ascii_domain = idna::domain_to_ascii(&domain)?; - - if let Ok(ip) = ascii_domain.parse() { - return Ok(TcpStream::connect(&SocketAddr::new(ip, port)).await?); - } - - let (config, mut options) = hickory_resolver::system_conf::read_system_conf()?; - options.ip_strategy = LookupIpStrategy::Ipv4AndIpv6; - let resolver = TokioAsyncResolver::new(config, options, TokioConnectionProvider::default()); - - let ips = resolver.lookup_ip(ascii_domain).await?; - - // Happy Eyeballs: connect to all records in parallel, return the - // first to succeed - select_ok( - ips.into_iter() - .map(|ip| TcpStream::connect(SocketAddr::new(ip, port)).boxed()), - ) - .await - .map(|(result, _)| result) - .map_err(|_| Error::Disconnected) - } - - /// Connect over TCP, resolving SRV records - #[cfg(feature = "dns")] - pub async fn resolve_with_srv( - domain: &str, - srv: &str, - fallback_port: u16, - ) -> Result { - let ascii_domain = idna::domain_to_ascii(&domain)?; - - if let Ok(ip) = ascii_domain.parse() { - debug!("Attempting connection to {ip}:{fallback_port}"); - return Ok(TcpStream::connect(&SocketAddr::new(ip, fallback_port)).await?); - } - - let resolver = TokioAsyncResolver::tokio_from_system_conf()?; - - let srv_domain = format!("{}.{}.", srv, ascii_domain).into_name()?; - let srv_records = resolver.srv_lookup(srv_domain.clone()).await.ok(); - - match srv_records { - Some(lookup) => { - // TODO: sort lookup records by priority/weight - for srv in lookup.iter() { - debug!("Attempting connection to {srv_domain} {srv}"); - match Self::resolve(&srv.target().to_ascii(), srv.port()).await { - Ok(stream) => return Ok(stream), - Err(_) => {} - } - } - Err(Error::Disconnected) - } - None => { - // SRV lookup error, retry with hostname - debug!("Attempting connection to {domain}:{fallback_port}"); - Self::resolve(domain, fallback_port).await - } - } - } -} diff --git a/tokio-xmpp/src/connect/starttls.rs b/tokio-xmpp/src/connect/starttls.rs index 7510fc089b82de61ab6568b24e5b08a898950283..8aa51b92a20cd5041f80a8b9c8f90d80a3085e56 100644 --- a/tokio-xmpp/src/connect/starttls.rs +++ b/tokio-xmpp/src/connect/starttls.rs @@ -37,40 +37,31 @@ use tokio::{ use xmpp_parsers::{jid::Jid, ns}; use crate::{ - connect::{ServerConnector, ServerConnectorError, Tcp}, + connect::{DnsConfig, ServerConnector, ServerConnectorError}, error::{Error, ProtocolError}, proto::{Packet, XmppStream}, - AsyncClient, + AsyncClient, Component, }; -/// AsyncClient that connects over StartTls -pub type StartTlsAsyncClient = AsyncClient; - -/// StartTLS XMPP server connection configuration -#[derive(Clone, Debug)] -pub enum ServerConfig { - /// Use SRV record to find server host - UseSrv, - #[allow(unused)] - /// Manually define server host and port - Manual { - /// Server host name - host: String, - /// Server port - port: u16, - }, +/// Client that connects over StartTls +pub type StartTlsClient = AsyncClient; +/// Component that connects over StartTls +pub type StartTlsComponent = Component; + +/// Connect via TCP+StartTLS to an XMPP server +#[derive(Debug, Clone)] +pub struct StartTlsServerConnector(pub DnsConfig); + +impl From for StartTlsServerConnector { + fn from(dns_config: DnsConfig) -> StartTlsServerConnector { + Self(dns_config) + } } -impl ServerConnector for ServerConfig { +impl ServerConnector for StartTlsServerConnector { type Stream = TlsStream; async fn connect(&self, jid: &Jid, ns: &str) -> Result, Error> { - // TCP connection - let tcp_stream = match self { - ServerConfig::UseSrv => { - Tcp::resolve_with_srv(jid.domain().as_str(), "_xmpp-client._tcp", 5222).await? - } - ServerConfig::Manual { host, port } => Tcp::resolve(host.as_str(), *port).await?, - }; + let tcp_stream = self.0.resolve().await?; // Unencryped XmppStream let xmpp_stream = XmppStream::start(tcp_stream, jid.clone(), ns.to_owned()).await?; diff --git a/tokio-xmpp/src/connect/tcp.rs b/tokio-xmpp/src/connect/tcp.rs index 5144d16016519adb5f5ceac2d3f427deeb2029dc..9f6123036ceee3814094234af32d5085bcc52867 100644 --- a/tokio-xmpp/src/connect/tcp.rs +++ b/tokio-xmpp/src/connect/tcp.rs @@ -1,44 +1,37 @@ //! `starttls::ServerConfig` provides a `ServerConnector` for starttls connections -use std::sync::Arc; - use tokio::net::TcpStream; -use crate::{connect::ServerConnector, proto::XmppStream, Component, Error}; +use crate::connect::DnsConfig; +use crate::{connect::ServerConnector, proto::XmppStream, AsyncClient, Component, Error}; /// Component that connects over TCP pub type TcpComponent = Component; +/// Client that connects over TCP +pub type TcpClient = AsyncClient; + /// Connect via insecure plaintext TCP to an XMPP server /// This should only be used over localhost or otherwise when you know what you are doing /// Probably mostly useful for Components #[derive(Debug, Clone)] -pub struct TcpServerConnector(Arc); +pub struct TcpServerConnector(pub DnsConfig); -impl TcpServerConnector { - /// Create a new connector with the given address - pub fn new(addr: String) -> Self { - Self(addr.into()) +impl From for TcpServerConnector { + fn from(dns_config: DnsConfig) -> TcpServerConnector { + Self(dns_config) } } impl ServerConnector for TcpServerConnector { type Stream = TcpStream; + async fn connect( &self, jid: &xmpp_parsers::jid::Jid, ns: &str, ) -> Result, Error> { - let stream = TcpStream::connect(&*self.0) - .await - .map_err(|e| crate::Error::Io(e))?; + let stream = self.0.resolve().await?; Ok(XmppStream::start(stream, jid.clone(), ns.to_owned()).await?) } } - -impl Component { - /// Start a new XMPP component - pub async fn new(jid: &str, password: &str, server: String) -> Result { - Self::new_with_connector(jid, password, TcpServerConnector::new(server)).await - } -} diff --git a/tokio-xmpp/src/error.rs b/tokio-xmpp/src/error.rs index 80a1496278589da5be60efa66297cfd60a8215c6..8963ad763afc0503f7b02b3009d36a28ea1b40dd 100644 --- a/tokio-xmpp/src/error.rs +++ b/tokio-xmpp/src/error.rs @@ -6,6 +6,7 @@ use sasl::client::MechanismError as SaslMechanismError; use std::error::Error as StdError; use std::fmt; use std::io::Error as IoError; +use std::net::AddrParseError; use std::str::Utf8Error; use xmpp_parsers::sasl::DefinedCondition as SaslDefinedCondition; @@ -44,6 +45,8 @@ pub enum Error { /// `idna` #[cfg(feature = "dns")] Idna, + /// Invalid IP/Port address + Addr(AddrParseError), } impl fmt::Display for Error { @@ -64,6 +67,7 @@ impl fmt::Display for Error { Error::Resolve(e) => write!(fmt, "{:?}", e), #[cfg(feature = "dns")] Error::Idna => write!(fmt, "IDNA error"), + Error::Addr(e) => write!(fmt, "Wrong network address: {e}"), } } } @@ -133,6 +137,12 @@ impl From for Error { } } +impl From for Error { + fn from(e: AddrParseError) -> Error { + Error::Addr(e) + } +} + /// XMPP protocol-level error #[derive(Debug)] pub enum ProtocolError { diff --git a/tokio-xmpp/src/lib.rs b/tokio-xmpp/src/lib.rs index 205d0f0000569480932dd56fddc196471fb4eaa5..b229cf405a1e47d6d57ad6a21f4b2aea6006f308 100644 --- a/tokio-xmpp/src/lib.rs +++ b/tokio-xmpp/src/lib.rs @@ -26,7 +26,7 @@ mod client; pub mod connect; pub mod proto; -pub use client::async_client::{Client as AsyncClient, Config as AsyncConfig}; +pub use client::async_client::Client as AsyncClient; mod component; pub use crate::component::Component; /// Detailed error types diff --git a/xmpp/src/builder.rs b/xmpp/src/builder.rs index 0620f76ba877fcc709bcb01bf3841fc8b30074c0..5f28541b2c612d007aa7707796ebccfaf51a7d69 100644 --- a/xmpp/src/builder.rs +++ b/xmpp/src/builder.rs @@ -6,14 +6,16 @@ use std::sync::Arc; use tokio::sync::RwLock; -use tokio_xmpp::connect::ServerConnector; +#[cfg(any(feature = "starttls-rust", feature = "starttls-native"))] +use tokio_xmpp::connect::{DnsConfig, StartTlsServerConnector}; use tokio_xmpp::{ + connect::ServerConnector, jid::{BareJid, Jid}, parsers::{ disco::{DiscoInfoResult, Feature, Identity}, ns, }, - AsyncClient as TokioXmppClient, AsyncConfig, + AsyncClient as TokioXmppClient, }; use crate::{Agent, ClientFeature}; @@ -52,15 +54,12 @@ pub struct ClientBuilder<'a, C: ServerConnector> { } #[cfg(any(feature = "starttls-rust", feature = "starttls-native"))] -impl ClientBuilder<'_, tokio_xmpp::connect::starttls::ServerConfig> { - pub fn new<'a>( - jid: BareJid, - password: &'a str, - ) -> ClientBuilder<'a, tokio_xmpp::connect::starttls::ServerConfig> { +impl ClientBuilder<'_, StartTlsServerConnector> { + pub fn new<'a>(jid: BareJid, password: &'a str) -> ClientBuilder<'a, StartTlsServerConnector> { Self::new_with_connector( - jid, + jid.clone(), password, - tokio_xmpp::connect::starttls::ServerConfig::UseSrv, + StartTlsServerConnector(DnsConfig::srv_default_client(jid.domain())), ) } } @@ -147,12 +146,8 @@ impl ClientBuilder<'_, C> { self.jid.clone().into() }; - let config = AsyncConfig { - jid, - password: self.password.into(), - server: self.server_connector.clone(), - }; - let mut client = TokioXmppClient::new_with_config(config); + let mut client = + TokioXmppClient::new_with_connector(jid, self.password, self.server_connector.clone()); client.set_reconnect(true); self.build_impl(client) }