diff --git a/common/src/network/client_webtransport.rs b/common/src/network/client_webtransport.rs index f0d38c2..34e1a3b 100644 --- a/common/src/network/client_webtransport.rs +++ b/common/src/network/client_webtransport.rs @@ -4,7 +4,7 @@ use bevy::prelude::*; use lightyear::prelude::client::*; use lightyear::prelude::*; -use thiserror::Error; +use crate::network::DEFAULT_PORT; pub struct ConnectWebTransportCommand { server_addr: SocketAddr, @@ -13,9 +13,8 @@ pub struct ConnectWebTransportCommand { impl ConnectWebTransportCommand { pub fn new(server_addr: &str, certificate_digest: String) -> Result { - let server_addr = to_socket_addr_with_default_port(server_addr, super::DEFAULT_PORT)?; Ok(Self { - server_addr, + server_addr: resolve_addr(&server_addr, DEFAULT_PORT)?, certificate_digest, }) } @@ -41,23 +40,31 @@ impl Command for ConnectWebTransportCommand { // TODO: Move this to its own `utils` module? // FIXME: Hostname resolving does not work on web. -fn to_socket_addr_with_default_port(addr: &str, default_port: u16) -> Result { - let has_port = match (addr.rfind(']'), addr.rfind(':')) { +fn resolve_addr(addr: &str, default_port: u16) -> Result { + let addr = with_default_port(addr, default_port); + let socket_addrs = addr.to_socket_addrs()?.collect::>(); + if let Some(ipv4) = socket_addrs.iter().find(|a| a.is_ipv4()) { + Ok(*ipv4) // Prefer first IPv4 address found.. + } else if let Some(ipv6) = socket_addrs.first() { + Ok(*ipv6) // ..otherwise fallback to IPv6. + } else { + Err(std::io::Error::other("hostname could not be resolved").into()) + } +} + +fn with_default_port(addr: &str, default_port: u16) -> String { + if is_port_specified(addr) { + addr.to_string() + } else { + format!("{addr}:{default_port}") + } +} + +fn is_port_specified(addr: &str) -> bool { + match (addr.rfind(']'), addr.rfind(':')) { // This doesn't match colons within IPv6 brackets, like `[::1]`. (Some(bracket), Some(colon)) if bracket < colon => true, (None, Some(_)) => true, _ => false, - }; - - let mut socket_addrs = if has_port { - addr.to_socket_addrs() - } else { - (addr, default_port).to_socket_addrs() - }?; - - socket_addrs.next().ok_or(ResolveError.into()) + } } - -#[derive(Error, Debug)] -#[error("hostname could not be resolved to any address")] -pub struct ResolveError;