diff options
Diffstat (limited to '')
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | src/lib.rs | 110 |
2 files changed, 107 insertions, 6 deletions
@@ -7,3 +7,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +tokio = { version = "1.28", features = ["full"] } +trust-dns-resolver = "0.22.0" +xml-rs = "0.8.14" @@ -1,16 +1,114 @@ +// TODO: logging (dropped errors) +#![allow(unused_must_use)] +use std::{ + net::{IpAddr, SocketAddr}, + str::FromStr, +}; + +use tokio::net::TcpStream; + mod jid; -pub fn add(left: usize, right: usize) -> usize { - left + right +pub struct Jabber { + connection: Option<TcpStream>, + login: jid::JID, + password: String, +} + +impl Jabber { + fn new(login: jid::JID, password: String) -> Self { + Self { + connection: None, + login, + password, + } + } + async fn resolve_client(&self) -> Vec<SocketAddr> { + 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) { + socket_addrs.push(socket_addr); + return socket_addrs; + } + // ip + if let Ok(ip) = IpAddr::from_str(&self.login.domainpart) { + socket_addrs.push(SocketAddr::new(ip, 5222)); + socket_addrs.push(SocketAddr::new(ip, 5223)); + return socket_addrs; + } + + // if port specified return name resolutions with specified port + + // 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)) + .await + { + for srv in lookup { + resolver + .lookup_ip(srv.target().to_owned()) + .await + .map(|ips| { + for ip in ips { + socket_addrs.push(SocketAddr::new(ip, srv.port())) + } + }); + } + } + if let Ok(lookup) = resolver + .srv_lookup(format!("_xmpps-client._tcp.{}", self.login.domainpart)) + .await + { + for srv in lookup { + resolver + .lookup_ip(srv.target().to_owned()) + .await + .map(|ips| { + for ip in ips { + socket_addrs.push(SocketAddr::new(ip, srv.port())) + } + }); + } + } + + // in case cannot connect through SRV records + resolver.lookup_ip(&self.login.domainpart).await.map(|ips| { + for ip in ips { + socket_addrs.push(SocketAddr::new(ip, 5222)); + socket_addrs.push(SocketAddr::new(ip, 5223)); + } + }); + } + + socket_addrs + } + + async fn connect(&mut self) { + for socket_addr in self.resolve_client().await { + println!("trying {}", socket_addr); + if let Ok(stream) = TcpStream::connect(socket_addr).await { + println!("connected to {}", socket_addr); + self.connection = Some(stream); + return; + } + } + println!("could not connect") + } } #[cfg(test)] mod tests { + use crate::jid::JID; + use super::*; - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); + #[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) } } |