From abc3ffa7363ebd30101e15db7e02a7d44f323df9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?cel=20=F0=9F=8C=B8?= Date: Fri, 16 Jun 2023 17:13:01 +0100 Subject: [PATCH] refactor jabber client --- Cargo.toml | 4 +- src/lib.rs | 106 +++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 85 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ccec909..12a7f4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "lâmpada" +name = "lampada" authors = ["cel "] version = "0.0.1" edition = "2021" @@ -7,6 +7,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +quick-xml = { version = "0.29.0", features = ["async-tokio"] } tokio = { version = "1.28", features = ["full"] } trust-dns-resolver = "0.22.0" -xml-rs = "0.8.14" diff --git a/src/lib.rs b/src/lib.rs index 42eb7de..10c7172 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,36 +5,37 @@ use std::{ str::FromStr, }; -use tokio::net::TcpStream; +use jid::JID; +use quick_xml::{Reader, Writer}; +use tokio::net::{ + tcp::{OwnedReadHalf, OwnedWriteHalf}, + TcpStream, +}; -mod jid; +pub mod jid; -pub struct Jabber { - connection: Option, - login: jid::JID, +pub struct JabberData { + jid: jid::JID, password: String, } -impl Jabber { - fn new(login: jid::JID, password: String) -> Self { - Self { - connection: None, - login, - password, - } +impl JabberData { + pub fn new(jid: JID, password: String) -> Self { + Self { jid, password } } - async fn resolve_client(&self) -> Vec { + + async fn get_sockets(&self) -> Vec { let mut socket_addrs = Vec::new(); // if it's a socket/ip then just return that // socket - if let Ok(socket_addr) = SocketAddr::from_str(&self.login.domainpart) { + if let Ok(socket_addr) = SocketAddr::from_str(&self.jid.domainpart) { socket_addrs.push(socket_addr); return socket_addrs; } // ip - if let Ok(ip) = IpAddr::from_str(&self.login.domainpart) { + if let Ok(ip) = IpAddr::from_str(&self.jid.domainpart) { socket_addrs.push(SocketAddr::new(ip, 5222)); socket_addrs.push(SocketAddr::new(ip, 5223)); return socket_addrs; @@ -45,7 +46,7 @@ impl Jabber { // otherwise resolve if let Ok(resolver) = trust_dns_resolver::AsyncResolver::tokio_from_system_conf() { if let Ok(lookup) = resolver - .srv_lookup(format!("_xmpp-client._tcp.{}", self.login.domainpart)) + .srv_lookup(format!("_xmpp-client._tcp.{}", self.jid.domainpart)) .await { for srv in lookup { @@ -60,7 +61,7 @@ impl Jabber { } } if let Ok(lookup) = resolver - .srv_lookup(format!("_xmpps-client._tcp.{}", self.login.domainpart)) + .srv_lookup(format!("_xmpps-client._tcp.{}", self.jid.domainpart)) .await { for srv in lookup { @@ -76,7 +77,7 @@ impl Jabber { } // in case cannot connect through SRV records - resolver.lookup_ip(&self.login.domainpart).await.map(|ips| { + resolver.lookup_ip(&self.jid.domainpart).await.map(|ips| { for ip in ips { socket_addrs.push(SocketAddr::new(ip, 5222)); socket_addrs.push(SocketAddr::new(ip, 5223)); @@ -86,18 +87,67 @@ impl Jabber { socket_addrs } +} - async fn connect(&mut self) { - for socket_addr in self.resolve_client().await { +pub struct Jabber { + reader: Reader, + writer: Writer, + data: JabberData, +} + +#[derive(Debug)] +pub enum JabberError { + NotConnected, +} + +impl Jabber { + pub async fn connect(data: JabberData) -> Result { + for socket_addr in data.get_sockets().await { println!("trying {}", socket_addr); if let Ok(stream) = TcpStream::connect(socket_addr).await { println!("connected to {}", socket_addr); - self.connection = Some(stream); + let (read, write) = stream.into_split(); + return Ok(Self { + reader: Reader::from_reader(read), + writer: Writer::new(write), + data, + }); + } + } + Err(JabberError::NotConnected) + } + + async fn reconnect(&mut self) { + for socket_addr in self.data.get_sockets().await { + println!("trying {}", socket_addr); + if let Ok(stream) = TcpStream::connect(socket_addr).await { + println!("connected to {}", socket_addr); + let (read, write) = stream.into_split(); + self.reader = Reader::from_reader(read); + self.writer = Writer::new(write); return; } } println!("could not connect") } + + async fn begin_stream(&mut self) -> Result<(), JabberError> { + todo!() + } + + async fn starttls() -> Result<(), JabberError> { + todo!() + } + + async fn directtls() -> Result<(), JabberError> { + todo!() + } + + async fn auth(&mut self) -> Result<(), JabberError> { + todo!() + } + + async fn close(&mut self) {} } #[cfg(test)] @@ -108,7 +158,17 @@ mod tests { #[tokio::test] async fn get_sockets() { - let client = Jabber::new(JID::from_str("cel@blos.sm").unwrap(), "password".to_owned()); - println!("{:?}", client.resolve_client().await) + let data = JabberData::new(JID::from_str("cel@blos.sm").unwrap(), "password".to_owned()); + println!("{:?}", data.get_sockets().await) + } + + #[tokio::test] + async fn connect() { + Jabber::connect(JabberData::new( + JID::from_str("cel@blos.sm").unwrap(), + "password".to_owned(), + )) + .await + .unwrap(); } }