|
@ -1,5 +1,6 @@ |
|
|
// TODO: rename this module to auth
|
|
|
// TODO: rename this module to auth
|
|
|
|
|
|
|
|
|
|
|
|
use std::collections::HashMap;
|
|
|
use std::net;
|
|
|
use std::net;
|
|
|
|
|
|
|
|
|
use rand::Rng;
|
|
|
use rand::Rng;
|
|
@ -21,6 +22,7 @@ pub const COMMUNICATION_PORT: u16 = 12123; |
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
#[derive(Debug)]
|
|
|
pub enum LoginError {
|
|
|
pub enum LoginError {
|
|
|
|
|
|
DbError
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -61,6 +63,10 @@ pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) |
|
|
let username = array_to_utf8(pkt.username).map_err(|_err| AccountStatus::Error)?;
|
|
|
let username = array_to_utf8(pkt.username).map_err(|_err| AccountStatus::Error)?;
|
|
|
let password = array_to_utf8(pkt.password).map_err(|_err| AccountStatus::Error)?;
|
|
|
let password = array_to_utf8(pkt.password).map_err(|_err| AccountStatus::Error)?;
|
|
|
let user = entity_gateway.get_user_by_name(username).await.map_err(|_| AccountStatus::InvalidUser)?;
|
|
|
let user = entity_gateway.get_user_by_name(username).await.map_err(|_| AccountStatus::InvalidUser)?;
|
|
|
|
|
|
if user.is_currently_online() {
|
|
|
|
|
|
return Err(AccountStatus::AlreadyOnline)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
if !user.activated {
|
|
|
if !user.activated {
|
|
|
return Err(AccountStatus::PayUp)
|
|
|
return Err(AccountStatus::PayUp)
|
|
|
}
|
|
|
}
|
|
@ -77,10 +83,19 @@ pub async fn get_login_status(entity_gateway: &impl EntityGateway, pkt: &Login) |
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn check_if_already_online(user: UserAccountEntity) -> Result<UserAccountEntity, AccountStatus> {
|
|
|
|
|
|
if user.is_currently_online() {
|
|
|
|
|
|
Err(AccountStatus::PayUp)
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
Ok(user)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
pub struct LoginServerState<EG: EntityGateway> {
|
|
|
pub struct LoginServerState<EG: EntityGateway> {
|
|
|
character_server_ip: net::Ipv4Addr,
|
|
|
character_server_ip: net::Ipv4Addr,
|
|
|
entity_gateway: EG,
|
|
|
entity_gateway: EG,
|
|
|
|
|
|
clients: HashMap<ClientId, String>,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
impl<EG: EntityGateway> LoginServerState<EG> {
|
|
|
impl<EG: EntityGateway> LoginServerState<EG> {
|
|
@ -88,20 +103,24 @@ impl<EG: EntityGateway> LoginServerState<EG> { |
|
|
LoginServerState {
|
|
|
LoginServerState {
|
|
|
entity_gateway: entity_gateway,
|
|
|
entity_gateway: entity_gateway,
|
|
|
character_server_ip: character_server_ip.into(),
|
|
|
character_server_ip: character_server_ip.into(),
|
|
|
|
|
|
clients: HashMap::new(),
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
async fn validate_login(&mut self, pkt: &Login) -> Vec<SendLoginPacket> {
|
|
|
|
|
|
match get_login_status(&self.entity_gateway, pkt).await {
|
|
|
|
|
|
Ok(_user) => {
|
|
|
|
|
|
|
|
|
async fn validate_login(&mut self, id: ClientId, pkt: &Login) -> Result<Vec<SendLoginPacket>, LoginError> {
|
|
|
|
|
|
match get_login_status(&self.entity_gateway, pkt).await.and_then(check_if_already_online) {
|
|
|
|
|
|
Ok(mut user) => {
|
|
|
|
|
|
user.at_login = true;
|
|
|
|
|
|
self.entity_gateway.save_user(&user).await.map_err(|_| LoginError::DbError)?;
|
|
|
|
|
|
self.clients.insert(id, user.username.clone());
|
|
|
|
|
|
|
|
|
let response = SendLoginPacket::LoginResponse(LoginResponse::by_status(AccountStatus::Ok, pkt.session));
|
|
|
let response = SendLoginPacket::LoginResponse(LoginResponse::by_status(AccountStatus::Ok, pkt.session));
|
|
|
//let ip = net::Ipv4Addr::new(127,0,0,1);
|
|
|
|
|
|
let ip = u32::from_ne_bytes(self.character_server_ip.octets());
|
|
|
let ip = u32::from_ne_bytes(self.character_server_ip.octets());
|
|
|
vec![response,
|
|
|
|
|
|
SendLoginPacket::RedirectClient(RedirectClient::new(ip, crate::login::character::CHARACTER_PORT))]
|
|
|
|
|
|
|
|
|
Ok(vec![response,
|
|
|
|
|
|
SendLoginPacket::RedirectClient(RedirectClient::new(ip, crate::login::character::CHARACTER_PORT))])
|
|
|
},
|
|
|
},
|
|
|
Err(err) => {
|
|
|
Err(err) => {
|
|
|
vec![SendLoginPacket::LoginResponse(LoginResponse::by_status(err, pkt.session))]
|
|
|
|
|
|
|
|
|
Ok(vec![SendLoginPacket::LoginResponse(LoginResponse::by_status(err, pkt.session))])
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -131,7 +150,7 @@ impl<EG: EntityGateway> ServerState for LoginServerState<EG> { |
|
|
-> Result<Box<dyn Iterator<Item = (ClientId, Self::SendPacket)> + Send>, LoginError> {
|
|
|
-> Result<Box<dyn Iterator<Item = (ClientId, Self::SendPacket)> + Send>, LoginError> {
|
|
|
Ok(match pkt {
|
|
|
Ok(match pkt {
|
|
|
RecvLoginPacket::Login(login) => {
|
|
|
RecvLoginPacket::Login(login) => {
|
|
|
Box::new(self.validate_login(login).await
|
|
|
|
|
|
|
|
|
Box::new(self.validate_login(id, login).await?
|
|
|
.into_iter()
|
|
|
.into_iter()
|
|
|
.map(move |pkt| {
|
|
|
.map(move |pkt| {
|
|
|
(id, pkt)
|
|
|
(id, pkt)
|
|
@ -140,7 +159,13 @@ impl<EG: EntityGateway> ServerState for LoginServerState<EG> { |
|
|
})
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
async fn on_disconnect(&mut self, _id: ClientId) -> Vec<(ClientId, SendLoginPacket)> {
|
|
|
|
|
|
|
|
|
async fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, SendLoginPacket)> {
|
|
|
|
|
|
if let Some(username) = self.clients.remove(&id) {
|
|
|
|
|
|
if let Ok(mut user) = self.entity_gateway.get_user_by_name(username).await {
|
|
|
|
|
|
user.at_login = false;
|
|
|
|
|
|
self.entity_gateway.save_user(&user).await;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
Vec::new()
|
|
|
Vec::new()
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -197,6 +222,9 @@ mod test { |
|
|
created_at: chrono::Utc::now(),
|
|
|
created_at: chrono::Utc::now(),
|
|
|
flags: 0,
|
|
|
flags: 0,
|
|
|
activated: true,
|
|
|
activated: true,
|
|
|
|
|
|
at_login: false,
|
|
|
|
|
|
at_character: false,
|
|
|
|
|
|
at_ship: false,
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
};
|
|
@ -282,6 +310,9 @@ mod test { |
|
|
created_at: chrono::Utc::now(),
|
|
|
created_at: chrono::Utc::now(),
|
|
|
flags: 0,
|
|
|
flags: 0,
|
|
|
activated: true,
|
|
|
activated: true,
|
|
|
|
|
|
at_login: false,
|
|
|
|
|
|
at_character: false,
|
|
|
|
|
|
at_ship: false,
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@ -328,6 +359,9 @@ mod test { |
|
|
created_at: chrono::Utc::now(),
|
|
|
created_at: chrono::Utc::now(),
|
|
|
flags: 0,
|
|
|
flags: 0,
|
|
|
activated: true,
|
|
|
activated: true,
|
|
|
|
|
|
at_login: false,
|
|
|
|
|
|
at_character: false,
|
|
|
|
|
|
at_ship: false,
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|