Reduce login state updates, fix multi-login on same acc

This commit is contained in:
P0nk
2024-09-29 15:55:14 +02:00
parent fa666c98e6
commit 5450c29178
4 changed files with 21 additions and 73 deletions

View File

@@ -63,7 +63,6 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
@@ -502,12 +501,7 @@ public class Client extends ChannelInboundHandlerAdapter {
}
public boolean attemptLogin() {
if (++failedLoginAttempts >= MAX_FAILED_LOGIN_ATTEMPTS) {
SessionCoordinator.getInstance().closeSession(this, false);
return false;
}
return true;
return ++failedLoginAttempts < MAX_FAILED_LOGIN_ATTEMPTS;
}
// TODO: check tempban directly on loaded account
@@ -588,32 +582,6 @@ public class Client extends ChannelInboundHandlerAdapter {
return accId;
}
public void updateLoginState(int newState) {
try (Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE accounts SET loggedin = ?, lastlogin = ? WHERE id = ?")) {
// using sql currenttime here could potentially break the login, thanks Arnah for pointing this out
ps.setInt(1, newState);
ps.setTimestamp(2, new java.sql.Timestamp(Server.getInstance().getCurrentTime()));
ps.setInt(3, getAccID());
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
if (newState == LoginState.LOGGED_OUT) {
loggedIn = false;
inServerTransition = false;
setAccID(0);
} else if (newState == LoginState.SERVER_TRANSITION) {
loggedIn = false;
inServerTransition = true;
} else {
loggedIn = true;
inServerTransition = false;
}
}
public void setLoginState(int newState) {
if (newState == LoginState.LOGGED_OUT) {
loggedIn = false;
@@ -630,35 +598,6 @@ public class Client extends ChannelInboundHandlerAdapter {
}
}
public byte getLoginState(Account account) {
byte loginState = account.loginState();
if (loginState == LoginState.SERVER_TRANSITION && lastLoginOverThirtySecondsAgo(account)) {
loginState = LoginState.LOGGED_OUT;
updateLoginState(LoginState.LOGGED_OUT);
}
if (loginState == LoginState.LOGGED_IN) {
loggedIn = true;
} else if (loginState == LoginState.SERVER_TRANSITION) {
try (Connection con = DatabaseConnection.getConnection();
PreparedStatement ps2 = con.prepareStatement("UPDATE accounts SET loggedin = 0 WHERE id = ?")) {
ps2.setInt(1, getAccID());
ps2.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
return loginState;
}
private static boolean lastLoginOverThirtySecondsAgo(Account account) {
if (account.lastLogin() == null) {
return true;
}
return account.lastLogin().isBefore(LocalDateTime.now().minusSeconds(30));
}
public boolean checkBirthDate(Calendar date) {
return date.get(Calendar.YEAR) == birthday.get(Calendar.YEAR) && date.get(Calendar.MONTH) == birthday.get(Calendar.MONTH) && date.get(Calendar.DAY_OF_MONTH) == birthday.get(Calendar.DAY_OF_MONTH);
}

View File

@@ -192,7 +192,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
}
try {
int state = c.getLoginState(account);
int state = account.loginState();
if (state != LoginState.SERVER_TRANSITION) {
c.setPlayer(null);
c.setAccID(0);

View File

@@ -83,8 +83,11 @@ public final class LoginPasswordHandler implements PacketHandler {
c.setHwid(new Hwid(HexTool.toCompactHexString(hwidNibbles)));
if (!c.attemptLogin()) {
c.sendPacket(PacketCreator.getLoginFailed(10));
SessionCoordinator.getInstance().closeSession(c, false);
return;
}
Optional<Account> foundAccount = accountService.getAccount(login);
if (foundAccount.isEmpty()) {
if (YamlConfig.config.server.AUTOMATIC_REGISTER) {
@@ -97,6 +100,12 @@ public final class LoginPasswordHandler implements PacketHandler {
}
Account account = foundAccount.get();
if (!correctPassword(pwd, account)) {
c.sendPacket(PacketCreator.getLoginFailed(4));
return;
}
if (account.banned()) {
c.sendPacket(PacketCreator.getLoginFailed(3));
// TODO: send ban reason instead of login failed, something like this:
@@ -104,18 +113,13 @@ public final class LoginPasswordHandler implements PacketHandler {
return;
}
if (!correctPassword(pwd, account)) {
c.sendPacket(PacketCreator.getLoginFailed(4));
if (account.loginState() > LoginState.LOGGED_OUT) {
c.sendPacket(PacketCreator.getLoginFailed(7));
return;
}
c.setAccount(account);
if (c.getLoginState(account) > LoginState.LOGGED_OUT) {
c.sendPacket(PacketCreator.getLoginFailed(7));
return;
}
if (!account.acceptedTos()) {
c.sendPacket(PacketCreator.getLoginFailed(23));
return;

View File

@@ -214,13 +214,17 @@ public class AccountService {
}
public boolean setLoggedIn(Client c) {
byte newState = LoginState.LOGGED_IN;
int currentState = c.getLoginState();
Account account = c.getAccount();
if (account == null) {
throw new IllegalStateException("Unable to set logged in - no account");
}
int currentState = account.loginState();
if (currentState != LoginState.LOGGED_OUT && currentState != LoginState.SERVER_TRANSITION) {
return false;
}
setLoginState(c, newState);
setLoginState(c, LoginState.LOGGED_IN);
return true;
}
@@ -229,6 +233,7 @@ public class AccountService {
setLoggedOut(c);
}
// TODO: check "stuck" accounts periodically and log them out.
public void setLoggedOut(Client c) {
setLoginState(c, LoginState.LOGGED_OUT);
}