mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
improve(login): more precise error handling during login
This commit is contained in:
parent
d3412d5493
commit
6cc07270ac
@ -8,8 +8,8 @@ pub enum Error {
|
|||||||
ServerTimeout,
|
ServerTimeout,
|
||||||
ServerShutdown,
|
ServerShutdown,
|
||||||
TooManyPlayers,
|
TooManyPlayers,
|
||||||
InvalidAuth,
|
|
||||||
AlreadyLoggedIn,
|
AlreadyLoggedIn,
|
||||||
|
AuthErr(String),
|
||||||
AuthClientError(AuthClientError),
|
AuthClientError(AuthClientError),
|
||||||
AuthServerNotTrusted,
|
AuthServerNotTrusted,
|
||||||
//TODO: InvalidAlias,
|
//TODO: InvalidAlias,
|
||||||
|
@ -18,7 +18,7 @@ use common::{
|
|||||||
event::{EventBus, SfxEvent, SfxEventItem},
|
event::{EventBus, SfxEvent, SfxEventItem},
|
||||||
msg::{
|
msg::{
|
||||||
validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, PlayerListUpdate,
|
validate_chat_msg, ChatMsgValidationError, ClientMsg, ClientState, PlayerListUpdate,
|
||||||
RequestStateError, ServerError, ServerInfo, ServerMsg, MAX_BYTES_CHAT_MSG,
|
RegisterError, RequestStateError, ServerInfo, ServerMsg, MAX_BYTES_CHAT_MSG,
|
||||||
},
|
},
|
||||||
net::PostBox,
|
net::PostBox,
|
||||||
state::State,
|
state::State,
|
||||||
@ -87,13 +87,13 @@ impl Client {
|
|||||||
let mut postbox = PostBox::to(addr)?;
|
let mut postbox = PostBox::to(addr)?;
|
||||||
|
|
||||||
// Wait for initial sync
|
// Wait for initial sync
|
||||||
let (state, entity, server_info, world_map) = match postbox.next_message() {
|
let (state, entity, server_info, world_map) = match postbox.next_message()? {
|
||||||
Some(ServerMsg::InitialSync {
|
ServerMsg::InitialSync {
|
||||||
entity_package,
|
entity_package,
|
||||||
server_info,
|
server_info,
|
||||||
time_of_day,
|
time_of_day,
|
||||||
world_map: (map_size, world_map),
|
world_map: (map_size, world_map),
|
||||||
}) => {
|
} => {
|
||||||
// TODO: Display that versions don't match in Voxygen
|
// TODO: Display that versions don't match in Voxygen
|
||||||
if server_info.git_hash != common::util::GIT_HASH.to_string() {
|
if server_info.git_hash != common::util::GIT_HASH.to_string() {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
@ -132,9 +132,7 @@ impl Client {
|
|||||||
|
|
||||||
(state, entity, server_info, (world_map, map_size))
|
(state, entity, server_info, (world_map, map_size))
|
||||||
},
|
},
|
||||||
Some(ServerMsg::Error(ServerError::TooManyPlayers)) => {
|
ServerMsg::TooManyPlayers => return Err(Error::TooManyPlayers),
|
||||||
return Err(Error::TooManyPlayers);
|
|
||||||
},
|
|
||||||
_ => return Err(Error::ServerWentMad),
|
_ => return Err(Error::ServerWentMad),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -203,11 +201,15 @@ impl Client {
|
|||||||
self.client_state = ClientState::Pending;
|
self.client_state = ClientState::Pending;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match self.postbox.next_message() {
|
match self.postbox.next_message()? {
|
||||||
Some(ServerMsg::StateAnswer(Err((RequestStateError::Denied, _)))) => {
|
ServerMsg::StateAnswer(Err((RequestStateError::RegisterDenied(err), state))) => {
|
||||||
break Err(Error::InvalidAuth);
|
self.client_state = state;
|
||||||
|
break Err(match err {
|
||||||
|
RegisterError::AlreadyLoggedIn => Error::AlreadyLoggedIn,
|
||||||
|
RegisterError::AuthError(err) => Error::AuthErr(err),
|
||||||
|
});
|
||||||
},
|
},
|
||||||
Some(ServerMsg::StateAnswer(Ok(ClientState::Registered))) => break Ok(()),
|
ServerMsg::StateAnswer(Ok(ClientState::Registered)) => break Ok(()),
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -572,12 +574,8 @@ impl Client {
|
|||||||
if new_msgs.len() > 0 {
|
if new_msgs.len() > 0 {
|
||||||
for msg in new_msgs {
|
for msg in new_msgs {
|
||||||
match msg {
|
match msg {
|
||||||
ServerMsg::Error(e) => match e {
|
ServerMsg::TooManyPlayers => {
|
||||||
ServerError::TooManyPlayers => return Err(Error::ServerWentMad),
|
return Err(Error::ServerWentMad);
|
||||||
ServerError::InvalidAuth => return Err(Error::InvalidAuth),
|
|
||||||
ServerError::AlreadyLoggedIn => return Err(Error::AlreadyLoggedIn),
|
|
||||||
ServerError::AuthError(_) => unreachable!(),
|
|
||||||
//TODO: ServerError::InvalidAlias => return Err(Error::InvalidAlias),
|
|
||||||
},
|
},
|
||||||
ServerMsg::Shutdown => return Err(Error::ServerShutdown),
|
ServerMsg::Shutdown => return Err(Error::ServerShutdown),
|
||||||
ServerMsg::InitialSync { .. } => return Err(Error::ServerWentMad),
|
ServerMsg::InitialSync { .. } => return Err(Error::ServerWentMad),
|
||||||
@ -720,10 +718,6 @@ impl Client {
|
|||||||
self.client_state = state;
|
self.client_state = state;
|
||||||
},
|
},
|
||||||
ServerMsg::StateAnswer(Err((error, state))) => {
|
ServerMsg::StateAnswer(Err((error, state))) => {
|
||||||
if error == RequestStateError::Denied {
|
|
||||||
warn!("Connection denied!");
|
|
||||||
return Err(Error::InvalidAuth);
|
|
||||||
}
|
|
||||||
warn!(
|
warn!(
|
||||||
"StateAnswer: {:?}. Server thinks client is in state {:?}.",
|
"StateAnswer: {:?}. Server thinks client is in state {:?}.",
|
||||||
error, state
|
error, state
|
||||||
|
@ -6,7 +6,7 @@ pub mod server;
|
|||||||
pub use self::{
|
pub use self::{
|
||||||
client::ClientMsg,
|
client::ClientMsg,
|
||||||
ecs_packet::EcsCompPacket,
|
ecs_packet::EcsCompPacket,
|
||||||
server::{PlayerListUpdate, RequestStateError, ServerError, ServerInfo, ServerMsg},
|
server::{PlayerListUpdate, RegisterError, RequestStateError, ServerInfo, ServerMsg},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||||
|
@ -8,14 +8,6 @@ use authc::AuthClientError;
|
|||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
||||||
pub enum RequestStateError {
|
|
||||||
Denied,
|
|
||||||
Already,
|
|
||||||
Impossible,
|
|
||||||
WrongMessage,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct ServerInfo {
|
pub struct ServerInfo {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -79,21 +71,28 @@ pub enum ServerMsg {
|
|||||||
chunk: Result<Box<TerrainChunk>, ()>,
|
chunk: Result<Box<TerrainChunk>, ()>,
|
||||||
},
|
},
|
||||||
TerrainBlockUpdates(HashMap<Vec3<i32>, Block>),
|
TerrainBlockUpdates(HashMap<Vec3<i32>, Block>),
|
||||||
Error(ServerError),
|
|
||||||
Disconnect,
|
Disconnect,
|
||||||
Shutdown,
|
Shutdown,
|
||||||
|
TooManyPlayers,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
pub enum ServerError {
|
pub enum RequestStateError {
|
||||||
TooManyPlayers,
|
RegisterDenied(RegisterError),
|
||||||
InvalidAuth,
|
Denied,
|
||||||
|
Already,
|
||||||
|
Impossible,
|
||||||
|
WrongMessage,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
|
pub enum RegisterError {
|
||||||
AlreadyLoggedIn,
|
AlreadyLoggedIn,
|
||||||
AuthError(String),
|
AuthError(String),
|
||||||
//TODO: InvalidAlias,
|
//TODO: InvalidAlias,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<AuthClientError> for ServerError {
|
impl From<AuthClientError> for RegisterError {
|
||||||
fn from(err: AuthClientError) -> Self { Self::AuthError(err.to_string()) }
|
fn from(err: AuthClientError) -> Self { Self::AuthError(err.to_string()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,16 +119,16 @@ impl<S: PostMsg, R: PostMsg> PostBox<S, R> {
|
|||||||
|
|
||||||
pub fn send_message(&mut self, msg: S) { let _ = self.send_tx.send(msg); }
|
pub fn send_message(&mut self, msg: S) { let _ = self.send_tx.send(msg); }
|
||||||
|
|
||||||
pub fn next_message(&mut self) -> Option<R> {
|
pub fn next_message(&mut self) -> Result<R, Error> {
|
||||||
if self.error.is_some() {
|
if let Some(e) = self.error.clone() {
|
||||||
return None;
|
return Err(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.recv_rx.recv().ok()? {
|
match self.recv_rx.recv().map_err(|_| Error::ChannelFailure)? {
|
||||||
Ok(msg) => Some(msg),
|
Ok(msg) => Ok(msg),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.error = Some(e);
|
self.error = Some(e.clone());
|
||||||
None
|
Err(e)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use authc::{AuthClient, AuthToken, Uuid};
|
use authc::{AuthClient, AuthToken, Uuid};
|
||||||
use common::msg::ServerError;
|
use common::msg::RegisterError;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
@ -42,28 +42,26 @@ impl AuthProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn query(&mut self, username_or_token: String) -> Result<bool, ServerError> {
|
pub fn query(&mut self, username_or_token: String) -> Result<(), RegisterError> {
|
||||||
// Based on whether auth server is provided or not we expect an username or
|
// Based on whether auth server is provided or not we expect an username or
|
||||||
// token
|
// token
|
||||||
match &self.auth_server {
|
match &self.auth_server {
|
||||||
// Token from auth server expected
|
// Token from auth server expected
|
||||||
Some(srv) => {
|
Some(srv) => {
|
||||||
log::info!("Validating '{}' token.", &username_or_token);
|
log::info!("Validating '{}' token.", &username_or_token);
|
||||||
if let Ok(token) = AuthToken::from_str(&username_or_token) {
|
// Parse token
|
||||||
match srv.validate(token) {
|
let token = AuthToken::from_str(&username_or_token)
|
||||||
Ok(uuid) => {
|
.map_err(|e| RegisterError::AuthError(e.to_string()))?;
|
||||||
|
// Validate token
|
||||||
|
let uuid = srv.validate(token)?;
|
||||||
|
// Check if already logged in
|
||||||
if self.accounts.contains_key(&uuid) {
|
if self.accounts.contains_key(&uuid) {
|
||||||
return Err(ServerError::AlreadyLoggedIn);
|
return Err(RegisterError::AlreadyLoggedIn);
|
||||||
}
|
}
|
||||||
|
// Log in
|
||||||
let username = srv.uuid_to_username(uuid.clone())?;
|
let username = srv.uuid_to_username(uuid.clone())?;
|
||||||
self.accounts.insert(uuid, username);
|
self.accounts.insert(uuid, username);
|
||||||
Ok(true)
|
Ok(())
|
||||||
},
|
|
||||||
Err(e) => Err(ServerError::from(e)),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// Username is expected
|
// Username is expected
|
||||||
None => {
|
None => {
|
||||||
@ -73,9 +71,9 @@ impl AuthProvider {
|
|||||||
if !self.accounts.contains_key(&uuid) {
|
if !self.accounts.contains_key(&uuid) {
|
||||||
log::info!("New User '{}'", username);
|
log::info!("New User '{}'", username);
|
||||||
self.accounts.insert(uuid, username);
|
self.accounts.insert(uuid, username);
|
||||||
Ok(true)
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(ServerError::AlreadyLoggedIn)
|
Err(RegisterError::AlreadyLoggedIn)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ use common::{
|
|||||||
assets, comp,
|
assets, comp,
|
||||||
effect::Effect,
|
effect::Effect,
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
msg::{ClientMsg, ClientState, ServerError, ServerInfo, ServerMsg},
|
msg::{ClientMsg, ClientState, ServerInfo, ServerMsg},
|
||||||
net::PostOffice,
|
net::PostOffice,
|
||||||
state::{State, TimeOfDay},
|
state::{State, TimeOfDay},
|
||||||
sync::{Uid, WorldSyncExt},
|
sync::{Uid, WorldSyncExt},
|
||||||
@ -505,7 +505,7 @@ impl Server {
|
|||||||
<= self.state.ecs().read_storage::<Client>().join().count()
|
<= self.state.ecs().read_storage::<Client>().join().count()
|
||||||
{
|
{
|
||||||
// Note: in this case the client is dropped
|
// Note: in this case the client is dropped
|
||||||
client.notify(ServerMsg::Error(ServerError::TooManyPlayers));
|
client.notify(ServerMsg::TooManyPlayers);
|
||||||
} else {
|
} else {
|
||||||
let entity = self
|
let entity = self
|
||||||
.state
|
.state
|
||||||
|
@ -127,10 +127,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
player,
|
player,
|
||||||
token_or_username,
|
token_or_username,
|
||||||
} if player.is_valid() => {
|
} if player.is_valid() => {
|
||||||
if !accounts.query(token_or_username.clone()).unwrap_or(false) {
|
match accounts.query(token_or_username.clone()) {
|
||||||
// TO-DO: Set a less generic error here.
|
Err(err) => {
|
||||||
client.error_state(RequestStateError::Denied);
|
client.error_state(RequestStateError::RegisterDenied(err));
|
||||||
break;
|
break;
|
||||||
|
},
|
||||||
|
Ok(()) => {},
|
||||||
}
|
}
|
||||||
match client.client_state {
|
match client.client_state {
|
||||||
ClientState::Connected => {
|
ClientState::Connected => {
|
||||||
|
@ -81,7 +81,7 @@ impl PlayState for MainMenuState {
|
|||||||
"Server not found".into()
|
"Server not found".into()
|
||||||
},
|
},
|
||||||
InitError::ClientError(err) => match err {
|
InitError::ClientError(err) => match err {
|
||||||
client::Error::InvalidAuth => "Invalid credentials".into(),
|
client::Error::AuthErr(e) => format!("Auth error on server: {}", e),
|
||||||
client::Error::TooManyPlayers => "Server is full".into(),
|
client::Error::TooManyPlayers => "Server is full".into(),
|
||||||
client::Error::AuthServerNotTrusted => {
|
client::Error::AuthServerNotTrusted => {
|
||||||
"Auth server not trusted".into()
|
"Auth server not trusted".into()
|
||||||
|
Loading…
Reference in New Issue
Block a user