mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Revert "Merge branch 'sharp/revert-quinn' into 'master'"
This reverts merge request !2315
This commit is contained in:
parent
88ba97b35a
commit
99304ffddd
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -5483,6 +5483,7 @@ dependencies = [
|
|||||||
"hashbrown",
|
"hashbrown",
|
||||||
"image",
|
"image",
|
||||||
"num 0.4.0",
|
"num 0.4.0",
|
||||||
|
"quinn",
|
||||||
"rayon",
|
"rayon",
|
||||||
"ron",
|
"ron",
|
||||||
"rustyline",
|
"rustyline",
|
||||||
@ -5752,6 +5753,7 @@ dependencies = [
|
|||||||
"portpicker",
|
"portpicker",
|
||||||
"prometheus",
|
"prometheus",
|
||||||
"prometheus-hyper",
|
"prometheus-hyper",
|
||||||
|
"quinn",
|
||||||
"rand 0.8.3",
|
"rand 0.8.3",
|
||||||
"rand_distr",
|
"rand_distr",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
@ -18,11 +18,12 @@ common-base = { package = "veloren-common-base", path = "../common/base" }
|
|||||||
common-state = { package = "veloren-common-state", path = "../common/state", default-features = false }
|
common-state = { package = "veloren-common-state", path = "../common/state", default-features = false }
|
||||||
common-systems = { package = "veloren-common-systems", path = "../common/systems", default-features = false }
|
common-systems = { package = "veloren-common-systems", path = "../common/systems", default-features = false }
|
||||||
common-net = { package = "veloren-common-net", path = "../common/net" }
|
common-net = { package = "veloren-common-net", path = "../common/net" }
|
||||||
network = { package = "veloren-network", path = "../network", features = ["compression"], default-features = false }
|
network = { package = "veloren-network", path = "../network", features = ["compression","quic"], default-features = false }
|
||||||
|
|
||||||
byteorder = "1.3.2"
|
byteorder = "1.3.2"
|
||||||
futures-util = "0.3.7"
|
futures-util = "0.3.7"
|
||||||
tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] }
|
tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] }
|
||||||
|
quinn = "0.7.2"
|
||||||
image = { version = "0.23.12", default-features = false, features = ["png"] }
|
image = { version = "0.23.12", default-features = false, features = ["png"] }
|
||||||
num = "0.4"
|
num = "0.4"
|
||||||
tracing = { version = "0.1", default-features = false }
|
tracing = { version = "0.1", default-features = false }
|
||||||
|
@ -4,33 +4,43 @@ use tracing::trace;
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ConnectionArgs {
|
pub enum ConnectionArgs {
|
||||||
IpAndPort(Vec<SocketAddr>),
|
///hostname: (hostname|ip):[<port>]
|
||||||
|
Quic {
|
||||||
|
hostname: String,
|
||||||
|
prefer_ipv6: bool,
|
||||||
|
},
|
||||||
|
///hostname: (hostname|ip):[<port>]
|
||||||
|
Tcp {
|
||||||
|
hostname: String,
|
||||||
|
prefer_ipv6: bool,
|
||||||
|
},
|
||||||
Mpsc(u64),
|
Mpsc(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConnectionArgs {
|
impl ConnectionArgs {
|
||||||
const DEFAULT_PORT: u16 = 14004;
|
const DEFAULT_PORT: u16 = 14004;
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse ip address or resolves hostname.
|
/// Parse ip address or resolves hostname.
|
||||||
/// Note: If you use an ipv6 address, the number after the last
|
/// Note: If you use an ipv6 address, the number after the last
|
||||||
/// colon will be used as the port unless you use [] around the address.
|
/// colon will be used as the port unless you use [] around the address.
|
||||||
pub async fn resolve(
|
pub(crate) async fn resolve(
|
||||||
/* <hostname/ip>:[<port>] */ server_address: &str,
|
address: &str,
|
||||||
prefer_ipv6: bool,
|
prefer_ipv6: bool,
|
||||||
) -> Result<Self, std::io::Error> {
|
) -> Result<Vec<SocketAddr>, std::io::Error> {
|
||||||
// `lookup_host` will internally try to parse it as a SocketAddr
|
// `lookup_host` will internally try to parse it as a SocketAddr
|
||||||
// 1. Assume it's a hostname + port
|
// 1. Assume it's a hostname + port
|
||||||
match lookup_host(server_address).await {
|
match lookup_host(address).await {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
trace!("Host lookup succeeded");
|
trace!("Host lookup succeeded");
|
||||||
Ok(Self::sort_ipv6(s, prefer_ipv6))
|
Ok(sort_ipv6(s, prefer_ipv6))
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// 2. Assume its a hostname without port
|
// 2. Assume its a hostname without port
|
||||||
match lookup_host((server_address, Self::DEFAULT_PORT)).await {
|
match lookup_host((address, ConnectionArgs::DEFAULT_PORT)).await {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
trace!("Host lookup without ports succeeded");
|
trace!("Host lookup without ports succeeded");
|
||||||
Ok(Self::sort_ipv6(s, prefer_ipv6))
|
Ok(sort_ipv6(s, prefer_ipv6))
|
||||||
},
|
},
|
||||||
Err(_) => Err(e), // Todo: evaluate returning both errors
|
Err(_) => Err(e), // Todo: evaluate returning both errors
|
||||||
}
|
}
|
||||||
@ -38,13 +48,36 @@ impl ConnectionArgs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sort_ipv6(s: impl Iterator<Item = SocketAddr>, prefer_ipv6: bool) -> Self {
|
pub(crate) async fn try_connect<F>(
|
||||||
|
network: &network::Network,
|
||||||
|
address: &str,
|
||||||
|
prefer_ipv6: bool,
|
||||||
|
f: F,
|
||||||
|
) -> Result<network::Participant, crate::error::Error>
|
||||||
|
where
|
||||||
|
F: Fn(std::net::SocketAddr) -> network::ConnectAddr,
|
||||||
|
{
|
||||||
|
use crate::error::Error;
|
||||||
|
let mut participant = None;
|
||||||
|
for addr in resolve(&address, prefer_ipv6)
|
||||||
|
.await
|
||||||
|
.map_err(Error::HostnameLookupFailed)?
|
||||||
|
{
|
||||||
|
match network.connect(f(addr)).await {
|
||||||
|
Ok(p) => {
|
||||||
|
participant = Some(Ok(p));
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
Err(e) => participant = Some(Err(Error::NetworkErr(e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
participant.unwrap_or_else(|| Err(Error::Other("No Ip Addr provided".to_string())))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sort_ipv6(s: impl Iterator<Item = SocketAddr>, prefer_ipv6: bool) -> Vec<SocketAddr> {
|
||||||
let (mut first_addrs, mut second_addrs) =
|
let (mut first_addrs, mut second_addrs) =
|
||||||
s.partition::<Vec<_>, _>(|a| a.is_ipv6() == prefer_ipv6);
|
s.partition::<Vec<_>, _>(|a| a.is_ipv6() == prefer_ipv6);
|
||||||
let addr = std::iter::Iterator::chain(first_addrs.drain(..), second_addrs.drain(..))
|
std::iter::Iterator::chain(first_addrs.drain(..), second_addrs.drain(..)).collect::<Vec<_>>()
|
||||||
.collect::<Vec<_>>();
|
|
||||||
ConnectionArgs::IpAndPort(addr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -54,85 +87,47 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn resolve_localhost() {
|
async fn resolve_localhost() {
|
||||||
let args = ConnectionArgs::resolve("localhost", false)
|
let args = resolve("localhost", false).await.expect("resolve failed");
|
||||||
.await
|
|
||||||
.expect("resolve failed");
|
|
||||||
if let ConnectionArgs::IpAndPort(args) = args {
|
|
||||||
assert!(args.len() == 1 || args.len() == 2);
|
assert!(args.len() == 1 || args.len() == 2);
|
||||||
assert_eq!(args[0].ip(), IpAddr::V4(Ipv4Addr::LOCALHOST));
|
assert_eq!(args[0].ip(), IpAddr::V4(Ipv4Addr::LOCALHOST));
|
||||||
assert_eq!(args[0].port(), 14004);
|
assert_eq!(args[0].port(), 14004);
|
||||||
} else {
|
|
||||||
panic!("wrong resolution");
|
|
||||||
}
|
|
||||||
|
|
||||||
let args = ConnectionArgs::resolve("localhost:666", false)
|
let args = resolve("localhost:666", false)
|
||||||
.await
|
.await
|
||||||
.expect("resolve failed");
|
.expect("resolve failed");
|
||||||
if let ConnectionArgs::IpAndPort(args) = args {
|
|
||||||
assert!(args.len() == 1 || args.len() == 2);
|
assert!(args.len() == 1 || args.len() == 2);
|
||||||
assert_eq!(args[0].port(), 666);
|
assert_eq!(args[0].port(), 666);
|
||||||
} else {
|
|
||||||
panic!("wrong resolution");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn resolve_ipv6() {
|
async fn resolve_ipv6() {
|
||||||
let args = ConnectionArgs::resolve("localhost", true)
|
let args = resolve("localhost", true).await.expect("resolve failed");
|
||||||
.await
|
|
||||||
.expect("resolve failed");
|
|
||||||
if let ConnectionArgs::IpAndPort(args) = args {
|
|
||||||
assert!(args.len() == 1 || args.len() == 2);
|
assert!(args.len() == 1 || args.len() == 2);
|
||||||
assert_eq!(args[0].ip(), Ipv6Addr::LOCALHOST);
|
assert_eq!(args[0].ip(), Ipv6Addr::LOCALHOST);
|
||||||
assert_eq!(args[0].port(), 14004);
|
assert_eq!(args[0].port(), 14004);
|
||||||
} else {
|
|
||||||
panic!("wrong resolution");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn resolve() {
|
async fn tresolve() {
|
||||||
let args = ConnectionArgs::resolve("google.com", false)
|
let args = resolve("google.com", false).await.expect("resolve failed");
|
||||||
.await
|
|
||||||
.expect("resolve failed");
|
|
||||||
if let ConnectionArgs::IpAndPort(args) = args {
|
|
||||||
assert!(args.len() == 1 || args.len() == 2);
|
assert!(args.len() == 1 || args.len() == 2);
|
||||||
assert_eq!(args[0].port(), 14004);
|
assert_eq!(args[0].port(), 14004);
|
||||||
} else {
|
|
||||||
panic!("wrong resolution");
|
|
||||||
}
|
|
||||||
|
|
||||||
let args = ConnectionArgs::resolve("127.0.0.1", false)
|
let args = resolve("127.0.0.1", false).await.expect("resolve failed");
|
||||||
.await
|
|
||||||
.expect("resolve failed");
|
|
||||||
if let ConnectionArgs::IpAndPort(args) = args {
|
|
||||||
assert_eq!(args.len(), 1);
|
assert_eq!(args.len(), 1);
|
||||||
assert_eq!(args[0].port(), 14004);
|
assert_eq!(args[0].port(), 14004);
|
||||||
assert_eq!(args[0].ip(), IpAddr::V4(Ipv4Addr::LOCALHOST));
|
assert_eq!(args[0].ip(), IpAddr::V4(Ipv4Addr::LOCALHOST));
|
||||||
} else {
|
|
||||||
panic!("wrong resolution");
|
|
||||||
}
|
|
||||||
|
|
||||||
let args = ConnectionArgs::resolve("55.66.77.88", false)
|
let args = resolve("55.66.77.88", false).await.expect("resolve failed");
|
||||||
.await
|
|
||||||
.expect("resolve failed");
|
|
||||||
if let ConnectionArgs::IpAndPort(args) = args {
|
|
||||||
assert_eq!(args.len(), 1);
|
assert_eq!(args.len(), 1);
|
||||||
assert_eq!(args[0].port(), 14004);
|
assert_eq!(args[0].port(), 14004);
|
||||||
assert_eq!(args[0].ip(), IpAddr::V4(Ipv4Addr::new(55, 66, 77, 88)));
|
assert_eq!(args[0].ip(), IpAddr::V4(Ipv4Addr::new(55, 66, 77, 88)));
|
||||||
} else {
|
|
||||||
panic!("wrong resolution");
|
|
||||||
}
|
|
||||||
|
|
||||||
let args = ConnectionArgs::resolve("127.0.0.1:776", false)
|
let args = resolve("127.0.0.1:776", false)
|
||||||
.await
|
.await
|
||||||
.expect("resolve failed");
|
.expect("resolve failed");
|
||||||
if let ConnectionArgs::IpAndPort(args) = args {
|
|
||||||
assert_eq!(args.len(), 1);
|
assert_eq!(args.len(), 1);
|
||||||
assert_eq!(args[0].port(), 776);
|
assert_eq!(args[0].port(), 776);
|
||||||
assert_eq!(args[0].ip(), IpAddr::V4(Ipv4Addr::LOCALHOST));
|
assert_eq!(args[0].ip(), IpAddr::V4(Ipv4Addr::LOCALHOST));
|
||||||
} else {
|
|
||||||
panic!("wrong resolution");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ pub enum Error {
|
|||||||
NetworkErr(NetworkError),
|
NetworkErr(NetworkError),
|
||||||
ParticipantErr(ParticipantError),
|
ParticipantErr(ParticipantError),
|
||||||
StreamErr(StreamError),
|
StreamErr(StreamError),
|
||||||
ServerWentMad,
|
|
||||||
ServerTimeout,
|
ServerTimeout,
|
||||||
ServerShutdown,
|
ServerShutdown,
|
||||||
TooManyPlayers,
|
TooManyPlayers,
|
||||||
@ -18,6 +17,7 @@ pub enum Error {
|
|||||||
AuthClientError(AuthClientError),
|
AuthClientError(AuthClientError),
|
||||||
AuthServerUrlInvalid(String),
|
AuthServerUrlInvalid(String),
|
||||||
AuthServerNotTrusted,
|
AuthServerNotTrusted,
|
||||||
|
HostnameLookupFailed(std::io::Error),
|
||||||
Banned(String),
|
Banned(String),
|
||||||
/// Persisted character data is invalid or missing
|
/// Persisted character data is invalid or missing
|
||||||
InvalidCharacter,
|
InvalidCharacter,
|
||||||
|
@ -203,10 +203,8 @@ pub struct CharacterList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
/// Create a new `Client`.
|
|
||||||
pub async fn new(
|
pub async fn new(
|
||||||
addr: ConnectionArgs,
|
addr: ConnectionArgs,
|
||||||
view_distance: Option<u32>,
|
|
||||||
runtime: Arc<Runtime>,
|
runtime: Arc<Runtime>,
|
||||||
// TODO: refactor to avoid needing to use this out parameter
|
// TODO: refactor to avoid needing to use this out parameter
|
||||||
mismatched_server_info: &mut Option<ServerInfo>,
|
mismatched_server_info: &mut Option<ServerInfo>,
|
||||||
@ -214,20 +212,21 @@ impl Client {
|
|||||||
let network = Network::new(Pid::new(), &runtime);
|
let network = Network::new(Pid::new(), &runtime);
|
||||||
|
|
||||||
let participant = match addr {
|
let participant = match addr {
|
||||||
ConnectionArgs::IpAndPort(addrs) => {
|
ConnectionArgs::Tcp {
|
||||||
// Try to connect to all IP's and return the first that works
|
hostname,
|
||||||
let mut participant = None;
|
prefer_ipv6,
|
||||||
for addr in addrs {
|
} => addr::try_connect(&network, &hostname, prefer_ipv6, ConnectAddr::Tcp).await?,
|
||||||
match network.connect(ConnectAddr::Tcp(addr)).await {
|
ConnectionArgs::Quic {
|
||||||
Ok(p) => {
|
hostname,
|
||||||
participant = Some(Ok(p));
|
prefer_ipv6,
|
||||||
break;
|
} => {
|
||||||
},
|
let mut config = quinn::ClientConfigBuilder::default();
|
||||||
Err(e) => participant = Some(Err(Error::NetworkErr(e))),
|
config.protocols(&[b"VELOREN"]);
|
||||||
}
|
let config = config.build();
|
||||||
}
|
addr::try_connect(&network, &hostname, prefer_ipv6, |a| {
|
||||||
participant
|
ConnectAddr::Quic(a, config.clone(), hostname.clone())
|
||||||
.unwrap_or_else(|| Err(Error::Other("No Ip Addr provided".to_string())))?
|
})
|
||||||
|
.await?
|
||||||
},
|
},
|
||||||
ConnectionArgs::Mpsc(id) => network.connect(ConnectAddr::Mpsc(id)).await?,
|
ConnectionArgs::Mpsc(id) => network.connect(ConnectAddr::Mpsc(id)).await?,
|
||||||
};
|
};
|
||||||
@ -694,7 +693,7 @@ impl Client {
|
|||||||
|
|
||||||
tick: 0,
|
tick: 0,
|
||||||
state,
|
state,
|
||||||
view_distance,
|
view_distance: None,
|
||||||
loaded_distance: 0.0,
|
loaded_distance: 0.0,
|
||||||
|
|
||||||
pending_chunks: HashMap::new(),
|
pending_chunks: HashMap::new(),
|
||||||
@ -2447,7 +2446,6 @@ impl Drop for Client {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
/// THIS TEST VERIFIES THE CONSTANT API.
|
/// THIS TEST VERIFIES THE CONSTANT API.
|
||||||
@ -2457,17 +2455,16 @@ mod tests {
|
|||||||
/// CONTACT @Core Developer BEFORE MERGING CHANGES TO THIS TEST
|
/// CONTACT @Core Developer BEFORE MERGING CHANGES TO THIS TEST
|
||||||
fn constant_api_test() {
|
fn constant_api_test() {
|
||||||
use common::clock::Clock;
|
use common::clock::Clock;
|
||||||
use std::net::{IpAddr, Ipv4Addr};
|
|
||||||
|
|
||||||
const SPT: f64 = 1.0 / 60.0;
|
const SPT: f64 = 1.0 / 60.0;
|
||||||
|
|
||||||
let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 9000);
|
|
||||||
let view_distance: Option<u32> = None;
|
|
||||||
let runtime = Arc::new(Runtime::new().unwrap());
|
let runtime = Arc::new(Runtime::new().unwrap());
|
||||||
let runtime2 = Arc::clone(&runtime);
|
let runtime2 = Arc::clone(&runtime);
|
||||||
let veloren_client: Result<Client, Error> = runtime.block_on(Client::new(
|
let veloren_client: Result<Client, Error> = runtime.block_on(Client::new(
|
||||||
ConnectionArgs::IpAndPort(vec![socket]),
|
ConnectionArgs::Tcp {
|
||||||
view_distance,
|
hostname: "127.0.0.1:9000".to_owned(),
|
||||||
|
prefer_ipv6: false,
|
||||||
|
},
|
||||||
runtime2,
|
runtime2,
|
||||||
&mut None,
|
&mut None,
|
||||||
));
|
));
|
||||||
|
@ -59,6 +59,7 @@ where
|
|||||||
.add_directive("tokio_util=info".parse().unwrap())
|
.add_directive("tokio_util=info".parse().unwrap())
|
||||||
.add_directive("rustls=info".parse().unwrap())
|
.add_directive("rustls=info".parse().unwrap())
|
||||||
.add_directive("veloren_network_protocol=info".parse().unwrap())
|
.add_directive("veloren_network_protocol=info".parse().unwrap())
|
||||||
|
.add_directive("quinn_proto::connection=info".parse().unwrap())
|
||||||
.add_directive(
|
.add_directive(
|
||||||
"veloren_server::persistence::character=info"
|
"veloren_server::persistence::character=info"
|
||||||
.parse()
|
.parse()
|
||||||
|
@ -20,7 +20,7 @@ common-state = { package = "veloren-common-state", path = "../common/state" }
|
|||||||
common-systems = { package = "veloren-common-systems", path = "../common/systems" }
|
common-systems = { package = "veloren-common-systems", path = "../common/systems" }
|
||||||
common-net = { package = "veloren-common-net", path = "../common/net" }
|
common-net = { package = "veloren-common-net", path = "../common/net" }
|
||||||
world = { package = "veloren-world", path = "../world" }
|
world = { package = "veloren-world", path = "../world" }
|
||||||
network = { package = "veloren-network", path = "../network", features = ["metrics", "compression"], default-features = false }
|
network = { package = "veloren-network", path = "../network", features = ["metrics", "compression", "quic"], default-features = false }
|
||||||
|
|
||||||
# inline_tweak = "1.0.8"
|
# inline_tweak = "1.0.8"
|
||||||
|
|
||||||
@ -33,6 +33,7 @@ vek = { version = "0.14.1", features = ["serde"] }
|
|||||||
futures-util = "0.3.7"
|
futures-util = "0.3.7"
|
||||||
tokio = { version = "1", default-features = false, features = ["rt"] }
|
tokio = { version = "1", default-features = false, features = ["rt"] }
|
||||||
prometheus-hyper = "0.1.2"
|
prometheus-hyper = "0.1.2"
|
||||||
|
quinn = "0.7.2"
|
||||||
atomicwrites = "0.3.0"
|
atomicwrites = "0.3.0"
|
||||||
chrono = { version = "0.4.9", features = ["serde"] }
|
chrono = { version = "0.4.9", features = ["serde"] }
|
||||||
humantime = "2.1.0"
|
humantime = "2.1.0"
|
||||||
|
@ -398,6 +398,38 @@ impl Server {
|
|||||||
});
|
});
|
||||||
runtime.block_on(network.listen(ListenAddr::Tcp(settings.gameserver_address)))?;
|
runtime.block_on(network.listen(ListenAddr::Tcp(settings.gameserver_address)))?;
|
||||||
runtime.block_on(network.listen(ListenAddr::Mpsc(14004)))?;
|
runtime.block_on(network.listen(ListenAddr::Mpsc(14004)))?;
|
||||||
|
if let Some(quic) = &settings.quic_files {
|
||||||
|
use std::fs;
|
||||||
|
match || -> Result<_, Box<dyn std::error::Error>> {
|
||||||
|
let mut server_config =
|
||||||
|
quinn::ServerConfigBuilder::new(quinn::ServerConfig::default());
|
||||||
|
server_config.protocols(&[b"VELOREN"]);
|
||||||
|
let key = fs::read(&quic.key)?;
|
||||||
|
let key = if quic.key.extension().map_or(false, |x| x == "der") {
|
||||||
|
quinn::PrivateKey::from_der(&key)?
|
||||||
|
} else {
|
||||||
|
quinn::PrivateKey::from_pem(&key)?
|
||||||
|
};
|
||||||
|
let cert_chain = fs::read(&quic.cert)?;
|
||||||
|
let cert_chain = if quic.cert.extension().map_or(false, |x| x == "der") {
|
||||||
|
quinn::CertificateChain::from_certs(Some(
|
||||||
|
quinn::Certificate::from_der(&cert_chain).unwrap(),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
quinn::CertificateChain::from_pem(&cert_chain)?
|
||||||
|
};
|
||||||
|
server_config.certificate(cert_chain, key)?;
|
||||||
|
Ok(server_config.build())
|
||||||
|
}() {
|
||||||
|
Ok(server_config) => {
|
||||||
|
runtime.block_on(
|
||||||
|
network
|
||||||
|
.listen(ListenAddr::Quic(settings.gameserver_address, server_config)),
|
||||||
|
)?;
|
||||||
|
},
|
||||||
|
Err(e) => error!(?e, "Failed to load Quic Certificate, run without Quic"),
|
||||||
|
}
|
||||||
|
}
|
||||||
let connection_handler = ConnectionHandler::new(network, &runtime);
|
let connection_handler = ConnectionHandler::new(network, &runtime);
|
||||||
|
|
||||||
// Initiate real-time world simulation
|
// Initiate real-time world simulation
|
||||||
|
@ -33,12 +33,19 @@ const BANLIST_FILENAME: &str = "banlist.ron";
|
|||||||
const SERVER_DESCRIPTION_FILENAME: &str = "description.ron";
|
const SERVER_DESCRIPTION_FILENAME: &str = "description.ron";
|
||||||
const ADMINS_FILENAME: &str = "admins.ron";
|
const ADMINS_FILENAME: &str = "admins.ron";
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct X509FilePair {
|
||||||
|
pub cert: PathBuf,
|
||||||
|
pub key: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pub gameserver_address: SocketAddr,
|
pub gameserver_address: SocketAddr,
|
||||||
pub metrics_address: SocketAddr,
|
pub metrics_address: SocketAddr,
|
||||||
pub auth_server_address: Option<String>,
|
pub auth_server_address: Option<String>,
|
||||||
|
pub quic_files: Option<X509FilePair>,
|
||||||
pub max_players: usize,
|
pub max_players: usize,
|
||||||
pub world_seed: u32,
|
pub world_seed: u32,
|
||||||
//pub pvp_enabled: bool,
|
//pub pvp_enabled: bool,
|
||||||
@ -62,6 +69,7 @@ impl Default for Settings {
|
|||||||
gameserver_address: SocketAddr::from(([0; 4], 14004)),
|
gameserver_address: SocketAddr::from(([0; 4], 14004)),
|
||||||
metrics_address: SocketAddr::from(([0; 4], 14005)),
|
metrics_address: SocketAddr::from(([0; 4], 14005)),
|
||||||
auth_server_address: Some("https://auth.veloren.net".into()),
|
auth_server_address: Some("https://auth.veloren.net".into()),
|
||||||
|
quic_files: None,
|
||||||
world_seed: DEFAULT_WORLD_SEED,
|
world_seed: DEFAULT_WORLD_SEED,
|
||||||
server_name: "Veloren Alpha".into(),
|
server_name: "Veloren Alpha".into(),
|
||||||
max_players: 100,
|
max_players: 100,
|
||||||
@ -140,6 +148,7 @@ impl Settings {
|
|||||||
pick_unused_port().expect("Failed to find unused port!"),
|
pick_unused_port().expect("Failed to find unused port!"),
|
||||||
)),
|
)),
|
||||||
auth_server_address: None,
|
auth_server_address: None,
|
||||||
|
quic_files: None,
|
||||||
// If loading the default map file, make sure the seed is also default.
|
// If loading the default map file, make sure the seed is also default.
|
||||||
world_seed: if load.map_file.is_some() {
|
world_seed: if load.map_file.is_some() {
|
||||||
load.world_seed
|
load.world_seed
|
||||||
|
@ -116,6 +116,10 @@ impl PlayState for CharSelectionState {
|
|||||||
},
|
},
|
||||||
ui::Event::Play(character_id) => {
|
ui::Event::Play(character_id) => {
|
||||||
self.client.borrow_mut().request_character(character_id);
|
self.client.borrow_mut().request_character(character_id);
|
||||||
|
//Send our ViewDistance
|
||||||
|
self.client
|
||||||
|
.borrow_mut()
|
||||||
|
.set_view_distance(global_state.settings.graphics.view_distance);
|
||||||
|
|
||||||
return PlayStateResult::Switch(Box::new(SessionState::new(
|
return PlayStateResult::Switch(Box::new(SessionState::new(
|
||||||
global_state,
|
global_state,
|
||||||
|
@ -17,7 +17,6 @@ use tracing::{trace, warn};
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
NoAddress,
|
|
||||||
ClientError {
|
ClientError {
|
||||||
error: ClientError,
|
error: ClientError,
|
||||||
mismatched_server_info: Option<ServerInfo>,
|
mismatched_server_info: Option<ServerInfo>,
|
||||||
@ -31,12 +30,6 @@ pub enum Msg {
|
|||||||
Done(Result<Client, Error>),
|
Done(Result<Client, Error>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ClientConnArgs {
|
|
||||||
Host(String),
|
|
||||||
#[allow(dead_code)] //singleplayer
|
|
||||||
Resolved(ConnectionArgs),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AuthTrust(String, bool);
|
pub struct AuthTrust(String, bool);
|
||||||
|
|
||||||
// Used to asynchronously parse the server address, resolve host names,
|
// Used to asynchronously parse the server address, resolve host names,
|
||||||
@ -51,9 +44,8 @@ impl ClientInit {
|
|||||||
#[allow(clippy::op_ref)] // TODO: Pending review in #587
|
#[allow(clippy::op_ref)] // TODO: Pending review in #587
|
||||||
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
||||||
pub fn new(
|
pub fn new(
|
||||||
connection_args: ClientConnArgs,
|
connection_args: ConnectionArgs,
|
||||||
username: String,
|
username: String,
|
||||||
view_distance: Option<u32>,
|
|
||||||
password: String,
|
password: String,
|
||||||
runtime: Option<Arc<runtime::Runtime>>,
|
runtime: Option<Arc<runtime::Runtime>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -89,18 +81,6 @@ impl ClientInit {
|
|||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
};
|
};
|
||||||
|
|
||||||
let connection_args = match connection_args {
|
|
||||||
ClientConnArgs::Host(host) => match ConnectionArgs::resolve(&host, false).await {
|
|
||||||
Ok(r) => r,
|
|
||||||
Err(_) => {
|
|
||||||
let _ = tx.send(Msg::Done(Err(Error::NoAddress)));
|
|
||||||
tokio::task::block_in_place(move || drop(runtime2));
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ClientConnArgs::Resolved(r) => r,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut last_err = None;
|
let mut last_err = None;
|
||||||
|
|
||||||
const FOUR_MINUTES_RETRIES: u64 = 48;
|
const FOUR_MINUTES_RETRIES: u64 = 48;
|
||||||
@ -111,7 +91,6 @@ impl ClientInit {
|
|||||||
let mut mismatched_server_info = None;
|
let mut mismatched_server_info = None;
|
||||||
match Client::new(
|
match Client::new(
|
||||||
connection_args.clone(),
|
connection_args.clone(),
|
||||||
view_distance,
|
|
||||||
Arc::clone(&runtime2),
|
Arc::clone(&runtime2),
|
||||||
&mut mismatched_server_info,
|
&mut mismatched_server_info,
|
||||||
)
|
)
|
||||||
@ -146,8 +125,11 @@ impl ClientInit {
|
|||||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parsing/host name resolution successful but no connection succeeded.
|
// Only possibility for no last_err is aborting
|
||||||
let _ = tx.send(Msg::Done(Err(last_err.unwrap_or(Error::NoAddress))));
|
let _ = tx.send(Msg::Done(Err(last_err.unwrap_or(Error::ClientError {
|
||||||
|
error: ClientError::Other("Connection attempt aborted by user".to_owned()),
|
||||||
|
mismatched_server_info: None,
|
||||||
|
}))));
|
||||||
|
|
||||||
// Safe drop runtime
|
// Safe drop runtime
|
||||||
tokio::task::block_in_place(move || drop(runtime2));
|
tokio::task::block_in_place(move || drop(runtime2));
|
||||||
|
@ -5,22 +5,18 @@ use super::char_selection::CharSelectionState;
|
|||||||
#[cfg(feature = "singleplayer")]
|
#[cfg(feature = "singleplayer")]
|
||||||
use crate::singleplayer::Singleplayer;
|
use crate::singleplayer::Singleplayer;
|
||||||
use crate::{
|
use crate::{
|
||||||
i18n::{Localization, LocalizationHandle},
|
i18n::LocalizationHandle, render::Renderer, settings::Settings, window::Event, Direction,
|
||||||
render::Renderer,
|
GlobalState, PlayState, PlayStateResult,
|
||||||
settings::Settings,
|
|
||||||
window::Event,
|
|
||||||
Direction, GlobalState, PlayState, PlayStateResult,
|
|
||||||
};
|
};
|
||||||
#[cfg(feature = "singleplayer")]
|
|
||||||
use client::addr::ConnectionArgs;
|
|
||||||
use client::{
|
use client::{
|
||||||
|
addr::ConnectionArgs,
|
||||||
error::{InitProtocolError, NetworkConnectError, NetworkError},
|
error::{InitProtocolError, NetworkConnectError, NetworkError},
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
};
|
};
|
||||||
use client_init::{ClientConnArgs, ClientInit, Error as InitError, Msg as InitMsg};
|
use client_init::{ClientInit, Error as InitError, Msg as InitMsg};
|
||||||
use common::comp;
|
use common::comp;
|
||||||
use common_base::span;
|
use common_base::span;
|
||||||
use std::{fmt::Debug, sync::Arc};
|
use std::sync::Arc;
|
||||||
use tokio::runtime;
|
use tokio::runtime;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
use ui::{Event as MainMenuEvent, MainMenuUi};
|
use ui::{Event as MainMenuEvent, MainMenuUi};
|
||||||
@ -74,11 +70,10 @@ impl PlayState for MainMenuState {
|
|||||||
Ok(Ok(runtime)) => {
|
Ok(Ok(runtime)) => {
|
||||||
// Attempt login after the server is finished initializing
|
// Attempt login after the server is finished initializing
|
||||||
attempt_login(
|
attempt_login(
|
||||||
&mut global_state.settings,
|
|
||||||
&mut global_state.info_message,
|
&mut global_state.info_message,
|
||||||
"singleplayer".to_owned(),
|
"singleplayer".to_owned(),
|
||||||
"".to_owned(),
|
"".to_owned(),
|
||||||
ClientConnArgs::Resolved(ConnectionArgs::Mpsc(14004)),
|
ConnectionArgs::Mpsc(14004),
|
||||||
&mut self.client_init,
|
&mut self.client_init,
|
||||||
Some(runtime),
|
Some(runtime),
|
||||||
);
|
);
|
||||||
@ -120,117 +115,14 @@ impl PlayState for MainMenuState {
|
|||||||
std::rc::Rc::new(std::cell::RefCell::new(client)),
|
std::rc::Rc::new(std::cell::RefCell::new(client)),
|
||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
Some(InitMsg::Done(Err(err))) => {
|
Some(InitMsg::Done(Err(e))) => {
|
||||||
let localized_strings = global_state.i18n.read();
|
|
||||||
self.client_init = None;
|
self.client_init = None;
|
||||||
global_state.info_message = Some({
|
tracing::trace!(?e, "raw Client Init error");
|
||||||
let err = match err {
|
let e = get_client_msg_error(e, &global_state.i18n);
|
||||||
InitError::NoAddress => {
|
|
||||||
localized_strings.get("main.login.server_not_found").into()
|
|
||||||
},
|
|
||||||
InitError::ClientError {
|
|
||||||
error,
|
|
||||||
mismatched_server_info,
|
|
||||||
} => match error {
|
|
||||||
client::Error::SpecsErr(e) => format!(
|
|
||||||
"{}: {}",
|
|
||||||
localized_strings.get("main.login.internal_error"),
|
|
||||||
e
|
|
||||||
),
|
|
||||||
client::Error::AuthErr(e) => format!(
|
|
||||||
"{}: {}",
|
|
||||||
localized_strings.get("main.login.authentication_error"),
|
|
||||||
e
|
|
||||||
),
|
|
||||||
client::Error::Kicked(e) => e,
|
|
||||||
client::Error::TooManyPlayers => {
|
|
||||||
localized_strings.get("main.login.server_full").into()
|
|
||||||
},
|
|
||||||
client::Error::AuthServerNotTrusted => localized_strings
|
|
||||||
.get("main.login.untrusted_auth_server")
|
|
||||||
.into(),
|
|
||||||
client::Error::ServerWentMad => localized_strings
|
|
||||||
.get("main.login.outdated_client_or_server")
|
|
||||||
.into(),
|
|
||||||
client::Error::ServerTimeout => {
|
|
||||||
localized_strings.get("main.login.timeout").into()
|
|
||||||
},
|
|
||||||
client::Error::ServerShutdown => {
|
|
||||||
localized_strings.get("main.login.server_shut_down").into()
|
|
||||||
},
|
|
||||||
client::Error::NotOnWhitelist => {
|
|
||||||
localized_strings.get("main.login.not_on_whitelist").into()
|
|
||||||
},
|
|
||||||
client::Error::Banned(reason) => format!(
|
|
||||||
"{}: {}",
|
|
||||||
localized_strings.get("main.login.banned"),
|
|
||||||
reason
|
|
||||||
),
|
|
||||||
client::Error::InvalidCharacter => {
|
|
||||||
localized_strings.get("main.login.invalid_character").into()
|
|
||||||
},
|
|
||||||
client::Error::NetworkErr(NetworkError::ConnectFailed(
|
|
||||||
NetworkConnectError::Handshake(InitProtocolError::WrongVersion(_)),
|
|
||||||
)) => get_network_error_text(
|
|
||||||
&localized_strings,
|
|
||||||
localized_strings.get("main.login.network_wrong_version"),
|
|
||||||
mismatched_server_info,
|
|
||||||
),
|
|
||||||
client::Error::NetworkErr(e) => get_network_error_text(
|
|
||||||
&localized_strings,
|
|
||||||
e,
|
|
||||||
mismatched_server_info,
|
|
||||||
),
|
|
||||||
client::Error::ParticipantErr(e) => get_network_error_text(
|
|
||||||
&localized_strings,
|
|
||||||
e,
|
|
||||||
mismatched_server_info,
|
|
||||||
),
|
|
||||||
client::Error::StreamErr(e) => get_network_error_text(
|
|
||||||
&localized_strings,
|
|
||||||
e,
|
|
||||||
mismatched_server_info,
|
|
||||||
),
|
|
||||||
client::Error::Other(e) => {
|
|
||||||
format!("{}: {}", localized_strings.get("common.error"), e)
|
|
||||||
},
|
|
||||||
client::Error::AuthClientError(e) => match e {
|
|
||||||
// TODO: remove parentheses
|
|
||||||
client::AuthClientError::RequestError(e) => format!(
|
|
||||||
"{}: {}",
|
|
||||||
localized_strings.get("main.login.failed_sending_request"),
|
|
||||||
e
|
|
||||||
),
|
|
||||||
client::AuthClientError::JsonError(e) => format!(
|
|
||||||
"{}: {}",
|
|
||||||
localized_strings.get("main.login.failed_sending_request"),
|
|
||||||
e
|
|
||||||
),
|
|
||||||
client::AuthClientError::InsecureSchema => localized_strings
|
|
||||||
.get("main.login.insecure_auth_scheme")
|
|
||||||
.into(),
|
|
||||||
client::AuthClientError::ServerError(_, e) => {
|
|
||||||
String::from_utf8_lossy(&e).to_string()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
client::Error::AuthServerUrlInvalid(e) => {
|
|
||||||
format!(
|
|
||||||
"{}: https://{}",
|
|
||||||
localized_strings
|
|
||||||
.get("main.login.failed_auth_server_url_invalid"),
|
|
||||||
e
|
|
||||||
)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
InitError::ClientCrashed => {
|
|
||||||
localized_strings.get("main.login.client_crashed").into()
|
|
||||||
},
|
|
||||||
};
|
|
||||||
// Log error for possible additional use later or incase that the error
|
// Log error for possible additional use later or incase that the error
|
||||||
// displayed is cut of.
|
// displayed is cut of.
|
||||||
error!("{}", err);
|
error!(?e, "Client Init failed");
|
||||||
err
|
global_state.info_message = Some(e);
|
||||||
});
|
|
||||||
},
|
},
|
||||||
Some(InitMsg::IsAuthTrusted(auth_server)) => {
|
Some(InitMsg::IsAuthTrusted(auth_server)) => {
|
||||||
if global_state
|
if global_state
|
||||||
@ -264,6 +156,7 @@ impl PlayState for MainMenuState {
|
|||||||
server_address,
|
server_address,
|
||||||
} => {
|
} => {
|
||||||
let mut net_settings = &mut global_state.settings.networking;
|
let mut net_settings = &mut global_state.settings.networking;
|
||||||
|
let use_quic = net_settings.use_quic;
|
||||||
net_settings.username = username.clone();
|
net_settings.username = username.clone();
|
||||||
net_settings.default_server = server_address.clone();
|
net_settings.default_server = server_address.clone();
|
||||||
if !net_settings.servers.contains(&server_address) {
|
if !net_settings.servers.contains(&server_address) {
|
||||||
@ -271,12 +164,22 @@ impl PlayState for MainMenuState {
|
|||||||
}
|
}
|
||||||
global_state.settings.save_to_file_warn();
|
global_state.settings.save_to_file_warn();
|
||||||
|
|
||||||
|
let connection_args = if use_quic {
|
||||||
|
ConnectionArgs::Quic {
|
||||||
|
hostname: server_address,
|
||||||
|
prefer_ipv6: false,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ConnectionArgs::Tcp {
|
||||||
|
hostname: server_address,
|
||||||
|
prefer_ipv6: false,
|
||||||
|
}
|
||||||
|
};
|
||||||
attempt_login(
|
attempt_login(
|
||||||
&mut global_state.settings,
|
|
||||||
&mut global_state.info_message,
|
&mut global_state.info_message,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
ClientConnArgs::Host(server_address),
|
connection_args,
|
||||||
&mut self.client_init,
|
&mut self.client_init,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
@ -347,14 +250,13 @@ impl PlayState for MainMenuState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When a network error is received and there is a mismatch between the client
|
fn get_client_msg_error(e: client_init::Error, localized_strings: &LocalizationHandle) -> String {
|
||||||
/// and server version it is almost definitely due to this mismatch rather than
|
let localization = localized_strings.read();
|
||||||
/// a true networking error.
|
|
||||||
fn get_network_error_text(
|
// When a network error is received and there is a mismatch between the client
|
||||||
localization: &Localization,
|
// and server version it is almost definitely due to this mismatch rather than
|
||||||
error: impl Debug,
|
// a true networking error.
|
||||||
mismatched_server_info: Option<ServerInfo>,
|
let net_e = |error: String, mismatched_server_info: Option<ServerInfo>| -> String {
|
||||||
) -> String {
|
|
||||||
if let Some(server_info) = mismatched_server_info {
|
if let Some(server_info) = mismatched_server_info {
|
||||||
format!(
|
format!(
|
||||||
"{} {}: {} {}: {}",
|
"{} {}: {} {}: {}",
|
||||||
@ -366,18 +268,92 @@ fn get_network_error_text(
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
"{}: {:?}",
|
"{}: {}",
|
||||||
localization.get("main.login.network_error"),
|
localization.get("main.login.network_error"),
|
||||||
error
|
error
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
use client::Error;
|
||||||
|
match e {
|
||||||
|
InitError::ClientError {
|
||||||
|
error,
|
||||||
|
mismatched_server_info,
|
||||||
|
} => match error {
|
||||||
|
Error::SpecsErr(e) => {
|
||||||
|
format!("{}: {}", localization.get("main.login.internal_error"), e)
|
||||||
|
},
|
||||||
|
Error::AuthErr(e) => format!(
|
||||||
|
"{}: {}",
|
||||||
|
localization.get("main.login.authentication_error"),
|
||||||
|
e
|
||||||
|
),
|
||||||
|
Error::Kicked(e) => e,
|
||||||
|
Error::TooManyPlayers => localization.get("main.login.server_full").into(),
|
||||||
|
Error::AuthServerNotTrusted => {
|
||||||
|
localization.get("main.login.untrusted_auth_server").into()
|
||||||
|
},
|
||||||
|
Error::ServerTimeout => localization.get("main.login.timeout").into(),
|
||||||
|
Error::ServerShutdown => localization.get("main.login.server_shut_down").into(),
|
||||||
|
Error::NotOnWhitelist => localization.get("main.login.not_on_whitelist").into(),
|
||||||
|
Error::Banned(reason) => {
|
||||||
|
format!("{}: {}", localization.get("main.login.banned"), reason)
|
||||||
|
},
|
||||||
|
Error::InvalidCharacter => localization.get("main.login.invalid_character").into(),
|
||||||
|
Error::NetworkErr(NetworkError::ConnectFailed(NetworkConnectError::Handshake(
|
||||||
|
InitProtocolError::WrongVersion(_),
|
||||||
|
))) => net_e(
|
||||||
|
localization
|
||||||
|
.get("main.login.network_wrong_version")
|
||||||
|
.to_owned(),
|
||||||
|
mismatched_server_info,
|
||||||
|
),
|
||||||
|
Error::NetworkErr(e) => net_e(e.to_string(), mismatched_server_info),
|
||||||
|
Error::ParticipantErr(e) => net_e(e.to_string(), mismatched_server_info),
|
||||||
|
Error::StreamErr(e) => net_e(e.to_string(), mismatched_server_info),
|
||||||
|
Error::HostnameLookupFailed(e) => {
|
||||||
|
format!("{}: {}", localization.get("main.login.server_not_found"), e)
|
||||||
|
},
|
||||||
|
Error::Other(e) => {
|
||||||
|
format!("{}: {}", localization.get("common.error"), e)
|
||||||
|
},
|
||||||
|
Error::AuthClientError(e) => match e {
|
||||||
|
// TODO: remove parentheses
|
||||||
|
client::AuthClientError::RequestError(e) => format!(
|
||||||
|
"{}: {}",
|
||||||
|
localization.get("main.login.failed_sending_request"),
|
||||||
|
e
|
||||||
|
),
|
||||||
|
client::AuthClientError::JsonError(e) => format!(
|
||||||
|
"{}: {}",
|
||||||
|
localization.get("main.login.failed_sending_request"),
|
||||||
|
e
|
||||||
|
),
|
||||||
|
client::AuthClientError::InsecureSchema => {
|
||||||
|
localization.get("main.login.insecure_auth_scheme").into()
|
||||||
|
},
|
||||||
|
client::AuthClientError::ServerError(_, e) => {
|
||||||
|
String::from_utf8_lossy(&e).to_string()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Error::AuthServerUrlInvalid(e) => {
|
||||||
|
format!(
|
||||||
|
"{}: https://{}",
|
||||||
|
localization.get("main.login.failed_auth_server_url_invalid"),
|
||||||
|
e
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
InitError::ClientCrashed => localization.get("main.login.client_crashed").into(),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn attempt_login(
|
fn attempt_login(
|
||||||
settings: &mut Settings,
|
|
||||||
info_message: &mut Option<String>,
|
info_message: &mut Option<String>,
|
||||||
username: String,
|
username: String,
|
||||||
password: String,
|
password: String,
|
||||||
connection_args: ClientConnArgs,
|
connection_args: ConnectionArgs,
|
||||||
client_init: &mut Option<ClientInit>,
|
client_init: &mut Option<ClientInit>,
|
||||||
runtime: Option<Arc<runtime::Runtime>>,
|
runtime: Option<Arc<runtime::Runtime>>,
|
||||||
) {
|
) {
|
||||||
@ -391,7 +367,6 @@ fn attempt_login(
|
|||||||
*client_init = Some(ClientInit::new(
|
*client_init = Some(ClientInit::new(
|
||||||
connection_args,
|
connection_args,
|
||||||
username,
|
username,
|
||||||
Some(settings.graphics.view_distance),
|
|
||||||
password,
|
password,
|
||||||
runtime,
|
runtime,
|
||||||
));
|
));
|
||||||
|
@ -9,6 +9,7 @@ pub struct NetworkingSettings {
|
|||||||
pub servers: Vec<String>,
|
pub servers: Vec<String>,
|
||||||
pub default_server: String,
|
pub default_server: String,
|
||||||
pub trusted_auth_servers: HashSet<String>,
|
pub trusted_auth_servers: HashSet<String>,
|
||||||
|
pub use_quic: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for NetworkingSettings {
|
impl Default for NetworkingSettings {
|
||||||
@ -21,6 +22,7 @@ impl Default for NetworkingSettings {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect(),
|
.collect(),
|
||||||
|
use_quic: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user