Log in through AccountService

This commit is contained in:
P0nk
2024-09-28 18:30:41 +02:00
parent 1be775394e
commit 5595f5763b
6 changed files with 62 additions and 72 deletions

View File

@@ -119,7 +119,6 @@ public class Client extends ChannelInboundHandlerAdapter {
private boolean disconnecting = false; private boolean disconnecting = false;
private final Semaphore actionsSemaphore = new Semaphore(7); private final Semaphore actionsSemaphore = new Semaphore(7);
private final Lock lock = new ReentrantLock(true); private final Lock lock = new ReentrantLock(true);
private final Lock encoderLock = new ReentrantLock(true);
private final Lock announcerLock = new ReentrantLock(true); private final Lock announcerLock = new ReentrantLock(true);
// thanks Masterrulax & try2hack for pointing out a bottleneck issue with shared locks, shavit for noticing an opportunity for improvement // thanks Masterrulax & try2hack for pointing out a bottleneck issue with shared locks, shavit for noticing an opportunity for improvement
private Calendar tempBanCalendar; private Calendar tempBanCalendar;
@@ -453,21 +452,6 @@ public class Client extends ChannelInboundHandlerAdapter {
} }
} }
public boolean finishLogin() {
encoderLock.lock();
try {
if (getLoginState() > LoginState.NOT_LOGGED_IN) { // 0 = LOGIN_NOTLOGGEDIN, 1= LOGIN_SERVER_TRANSITION, 2 = LOGIN_LOGGEDIN
loggedIn = false;
return false;
}
updateLoginState(LoginState.LOGGED_IN);
} finally {
encoderLock.unlock();
}
return true;
}
public void setPin(String pin) { public void setPin(String pin) {
this.pin = pin; this.pin = pin;
} }
@@ -755,6 +739,8 @@ public class Client extends ChannelInboundHandlerAdapter {
} }
} }
// TODO: move to postgres. Called from all CharSelect handlers (6 in total).
//
public void setCharacterOnSessionTransitionState(int cid) { public void setCharacterOnSessionTransitionState(int cid) {
this.updateLoginState(LoginState.SERVER_TRANSITION); this.updateLoginState(LoginState.SERVER_TRANSITION);
this.inTransition = true; this.inTransition = true;
@@ -832,7 +818,6 @@ public class Client extends ChannelInboundHandlerAdapter {
if (lastPong < pingedAt) { if (lastPong < pingedAt) {
if (ioChannel.isActive()) { if (ioChannel.isActive()) {
log.info("Disconnected {} due to idling. Reason: {}", remoteAddress, event.state()); log.info("Disconnected {} due to idling. Reason: {}", remoteAddress, event.state());
updateLoginState(LoginState.NOT_LOGGED_IN);
disconnectSession(); disconnectSession();
} }
} }

View File

@@ -318,7 +318,7 @@ public final class PacketProcessor {
registerHandler(RecvOpcode.ITEM_MOVE, new ItemMoveHandler()); registerHandler(RecvOpcode.ITEM_MOVE, new ItemMoveHandler());
registerHandler(RecvOpcode.MESO_DROP, new MesoDropHandler()); registerHandler(RecvOpcode.MESO_DROP, new MesoDropHandler());
registerHandler(RecvOpcode.PLAYER_LOGGEDIN, new PlayerLoggedinHandler(channelDeps.characterLoader(), registerHandler(RecvOpcode.PLAYER_LOGGEDIN, new PlayerLoggedinHandler(channelDeps.characterLoader(),
channelDeps.noteService())); channelDeps.accountService(), channelDeps.noteService()));
registerHandler(RecvOpcode.CHANGE_MAP, new ChangeMapHandler()); registerHandler(RecvOpcode.CHANGE_MAP, new ChangeMapHandler());
registerHandler(RecvOpcode.MOVE_LIFE, new MoveLifeHandler()); registerHandler(RecvOpcode.MOVE_LIFE, new MoveLifeHandler());
registerHandler(RecvOpcode.CLOSE_RANGE_ATTACK, new CloseRangeDamageHandler(channelDeps.dropProvider(), channelDeps.banService())); registerHandler(RecvOpcode.CLOSE_RANGE_ATTACK, new CloseRangeDamageHandler(channelDeps.dropProvider(), channelDeps.banService()));

View File

@@ -39,6 +39,7 @@ import client.inventory.Pet;
import client.keybind.KeyBinding; import client.keybind.KeyBinding;
import config.YamlConfig; import config.YamlConfig;
import constants.game.GameConstants; import constants.game.GameConstants;
import database.account.Account;
import database.character.CharacterLoader; import database.character.CharacterLoader;
import model.CharacterIdentity; import model.CharacterIdentity;
import net.AbstractPacketHandler; import net.AbstractPacketHandler;
@@ -61,6 +62,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import scripting.event.EventInstanceManager; import scripting.event.EventInstanceManager;
import server.life.MobSkill; import server.life.MobSkill;
import service.AccountService;
import service.NoteService; import service.NoteService;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import tools.PacketCreator; import tools.PacketCreator;
@@ -86,10 +88,12 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
private static final Set<Integer> attemptingLoginAccounts = new HashSet<>(); private static final Set<Integer> attemptingLoginAccounts = new HashSet<>();
private final CharacterLoader chrLoader; private final CharacterLoader chrLoader;
private final AccountService accountService;
private final NoteService noteService; private final NoteService noteService;
public PlayerLoggedinHandler(CharacterLoader chrLoader, NoteService noteService) { public PlayerLoggedinHandler(CharacterLoader chrLoader, AccountService accountService, NoteService noteService) {
this.chrLoader = chrLoader; this.chrLoader = chrLoader;
this.accountService = accountService;
this.noteService = noteService; this.noteService = noteService;
} }
@@ -159,65 +163,54 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
throw new GameViolationException("Attempt to enter game without chr id in transition"); throw new GameViolationException("Attempt to enter game without chr id in transition");
} }
boolean newcomer = false; boolean newlyLoggedIn = false;
if (player == null) { if (player == null) {
Optional<Character> loadedChr = chrLoader.loadForChannel(chrId, c); Optional<Character> loadedChr = chrLoader.loadForChannel(chrId, c);
if (loadedChr.isPresent()) { if (loadedChr.isPresent()) {
player = loadedChr.get(); player = loadedChr.get();
newcomer = true; newlyLoggedIn = true;
} else { } else {
throw new GameViolationException("Unable to load chr"); throw new GameViolationException("Unable to load chr");
} }
} }
c.setPlayer(player); c.setPlayer(player);
c.setAccID(player.getAccountID());
boolean allowLogin = true; Optional<Account> foundAccount = accountService.getAccount(player.getAccountID());
if (foundAccount.isEmpty()) {
c.sendPacket(PacketCreator.getAfterLoginError(5));
return;
}
Account account = foundAccount.get();
c.setAccount(account);
/* is this check really necessary? int accId = account.id();
if (state == LoginState.SERVER_TRANSITION || state == LoginState.NOT_LOGGED_IN) { if (!tryAcquireAccount(accId)) { // Sync this to prevent wrong login state for double loggedin handling
List<String> charNames = c.loadCharacterNames(c.getWorld());
if(!newcomer) {
charNames.remove(player.getName());
}
for (String charName : charNames) {
if(wserv.getPlayerStorage().getCharacterByName(charName) != null) {
allowLogin = false;
break;
}
}
}
*/
int accId = c.getAccID();
if (tryAcquireAccount(accId)) { // Sync this to prevent wrong login state for double loggedin handling
try {
int state = c.getLoginState();
if (state != LoginState.SERVER_TRANSITION || !allowLogin) {
c.setPlayer(null);
c.setAccID(0);
if (state == LoginState.LOGGED_IN) {
throw new GameViolationException("Attempt to log in when already logged in");
} else {
c.sendPacket(PacketCreator.getAfterLoginError(7));
}
return;
}
c.updateLoginState(LoginState.LOGGED_IN);
} finally {
releaseAccount(accId);
}
} else {
c.setPlayer(null); c.setPlayer(null);
c.setAccID(0); c.setAccID(0);
c.sendPacket(PacketCreator.getAfterLoginError(10)); c.sendPacket(PacketCreator.getAfterLoginError(10));
return; return;
} }
if (!newcomer) { try {
int state = c.getLoginState(account);
if (state != LoginState.SERVER_TRANSITION) {
c.setPlayer(null);
c.setAccID(0);
if (state == LoginState.LOGGED_IN) {
throw new GameViolationException("Attempt to log in when already logged in");
} else {
c.sendPacket(PacketCreator.getAfterLoginError(7));
}
return;
}
c.updateLoginState(LoginState.LOGGED_IN);
} finally {
releaseAccount(accId);
}
if (!newlyLoggedIn) {
c.setCharacterSlots((byte) player.getClient().getCharacterSlots()); c.setCharacterSlots((byte) player.getClient().getCharacterSlots());
player.newClient(c); player.newClient(c);
} }
@@ -315,7 +308,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
c.sendPacket(GuildPackets.updateAllianceInfo(newAlliance, c.getWorld())); c.sendPacket(GuildPackets.updateAllianceInfo(newAlliance, c.getWorld()));
c.sendPacket(GuildPackets.allianceNotice(newAlliance.getId(), newAlliance.getNotice())); c.sendPacket(GuildPackets.allianceNotice(newAlliance.getId(), newAlliance.getNotice()));
if (newcomer) { if (newlyLoggedIn) {
server.allianceMessage(allianceId, GuildPackets.allianceMemberOnline(player, true), player.getId(), -1); server.allianceMessage(allianceId, GuildPackets.allianceMemberOnline(player, true), player.getId(), -1);
} }
} }
@@ -361,7 +354,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
player.changeSkillLevel(SkillFactory.getSkill(10000000 * player.getJobType() + 12), (byte) (player.getLinkedLevel() / 10), 20, -1); player.changeSkillLevel(SkillFactory.getSkill(10000000 * player.getJobType() + 12), (byte) (player.getLinkedLevel() / 10), 20, -1);
player.checkBerserk(player.isHidden()); player.checkBerserk(player.isHidden());
if (newcomer) { if (newlyLoggedIn) {
for (Pet pet : player.getPets()) { for (Pet pet : player.getPets()) {
if (pet != null) { if (pet != null) {
wserv.registerPetHunger(player, player.getPetIndex(pet)); wserv.registerPetHunger(player, player.getPetIndex(pet));
@@ -423,7 +416,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
} }
} }
if (newcomer) { if (newlyLoggedIn) {
EventInstanceManager eim = EventRecallCoordinator.getInstance().recallEventInstance(chrId); EventInstanceManager eim = EventRecallCoordinator.getInstance().recallEventInstance(chrId);
if (eim != null) { if (eim != null) {
eim.registerPlayer(player); eim.registerPlayer(player);
@@ -443,7 +436,7 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler {
c.sendPacket(PacketCreator.setNPCScriptable(npcsIds)); c.sendPacket(PacketCreator.setNPCScriptable(npcsIds));
} }
if (newcomer) { if (newlyLoggedIn) {
player.setLoginTime(System.currentTimeMillis()); player.setLoginTime(System.currentTimeMillis());
} }
} catch (Exception e) { } catch (Exception e) {

View File

@@ -29,10 +29,10 @@ public final class AcceptToSHandler extends AbstractPacketHandler {
throw new GameViolationException("ToS not accepted"); throw new GameViolationException("ToS not accepted");
} }
if (c.finishLogin()) { if (!accountService.logIn(c)) {
c.sendPacket(PacketCreator.getAuthSuccess(c)); c.sendPacket(PacketCreator.getLoginFailed(7));
} else {
c.sendPacket(PacketCreator.getLoginFailed(9));//shouldn't happen XD
} }
c.sendPacket(PacketCreator.getAuthSuccess(c));
} }
} }

View File

@@ -149,10 +149,10 @@ public final class LoginPasswordHandler implements PacketHandler {
return; return;
} }
if (!c.finishLogin()) { if (!accountService.logIn(c)) {
c.sendPacket(PacketCreator.getLoginFailed(7)); c.sendPacket(PacketCreator.getLoginFailed(7));
} }
checkChar(c); removeOnlineAccountChrs(c);
c.sendPacket(PacketCreator.getAuthSuccess(c)); c.sendPacket(PacketCreator.getAuthSuccess(c));
Server.getInstance().registerLoginState(c); Server.getInstance().registerLoginState(c);
@@ -200,7 +200,7 @@ public final class LoginPasswordHandler implements PacketHandler {
}; };
} }
private void checkChar(Client c) { // issue with multiple chars from same account login found by shavit, resinate private void removeOnlineAccountChrs(Client c) { // issue with multiple chars from same account login found by shavit, resinate
if (!YamlConfig.config.server.USE_CHARACTER_ACCOUNT_CHECK) { if (!YamlConfig.config.server.USE_CHARACTER_ACCOUNT_CHECK) {
return; return;
} }

View File

@@ -213,6 +213,18 @@ public class AccountService {
return accountRepository.setChrSlots(accountId, chrSlots); return accountRepository.setChrSlots(accountId, chrSlots);
} }
public boolean logIn(Client c) {
byte newState = LoginState.LOGGED_IN;
if (c.getLoginState() != LoginState.NOT_LOGGED_IN) {
return false;
}
setLoginStateMysql(c.getAccID(), newState);
setLoginStatePostgres(c.getAccID(), newState);
c.setLoginState(newState);
return true;
}
public void logOut(Client c) { public void logOut(Client c) {
SessionCoordinator.getInstance().closeSession(c, false); SessionCoordinator.getInstance().closeSession(c, false);
byte newState = LoginState.NOT_LOGGED_IN; byte newState = LoginState.NOT_LOGGED_IN;