You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-19 15:06:19 +00:00
fix(session): separate forced disconnects from resume parking
Add a forced dispose path for bans, RCON disconnects, logout/account endpoints, plugin-cancelled login, duplicate login replacement, and late MAC-ban enforcement. Soft channel closes still park a session for reconnect, while security-driven closes now bypass session resume. Also null-guard client/channel disposal and cover the contract with focused tests.
This commit is contained in:
@@ -149,6 +149,10 @@ public class GameClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
|
this.dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose(boolean allowSessionResume) {
|
||||||
try {
|
try {
|
||||||
this.channel.close();
|
this.channel.close();
|
||||||
|
|
||||||
@@ -161,7 +165,7 @@ public class GameClient {
|
|||||||
// appena ripristinata (era la causa del "Bye"/kick al 2° reconnect).
|
// appena ripristinata (era la causa del "Bye"/kick al 2° reconnect).
|
||||||
if (this.habbo.getClient() == this && this.habbo.isOnline()) {
|
if (this.habbo.getClient() == this && this.habbo.isOnline()) {
|
||||||
// Try to park the habbo in the grace period instead of immediate disconnect
|
// Try to park the habbo in the grace period instead of immediate disconnect
|
||||||
boolean parked = SessionResumeManager.getInstance().parkHabbo(this.habbo, this.ssoTicket);
|
boolean parked = allowSessionResume && SessionResumeManager.getInstance().parkHabbo(this.habbo, this.ssoTicket);
|
||||||
|
|
||||||
if (!parked) {
|
if (!parked) {
|
||||||
// No grace period configured — immediate disconnect as before
|
// No grace period configured — immediate disconnect as before
|
||||||
@@ -177,4 +181,4 @@ public class GameClient {
|
|||||||
LOGGER.error("Caught exception", e);
|
LOGGER.error("Caught exception", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,14 +43,34 @@ public class GameClientManager {
|
|||||||
|
|
||||||
|
|
||||||
public void disposeClient(GameClient client) {
|
public void disposeClient(GameClient client) {
|
||||||
this.disposeClient(client.getChannel());
|
if (client == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.disposeClient(client.getChannel(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forceDisposeClient(GameClient client) {
|
||||||
|
if (client == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.disposeClient(client.getChannel(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void disposeClient(Channel channel) {
|
private void disposeClient(Channel channel) {
|
||||||
|
this.disposeClient(channel, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disposeClient(Channel channel, boolean allowSessionResume) {
|
||||||
|
if (channel == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GameClient client = channel.attr(GameServerAttributes.CLIENT).get();
|
GameClient client = channel.attr(GameServerAttributes.CLIENT).get();
|
||||||
|
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
client.dispose();
|
client.dispose(allowSessionResume);
|
||||||
}
|
}
|
||||||
channel.deregister();
|
channel.deregister();
|
||||||
channel.attr(GameServerAttributes.CLIENT).set(null);
|
channel.attr(GameServerAttributes.CLIENT).set(null);
|
||||||
@@ -190,4 +210,4 @@ public class GameClientManager {
|
|||||||
CFKeepAlive();
|
CFKeepAlive();
|
||||||
}, 30000);
|
}, 30000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ public class HabboManager {
|
|||||||
habbo = this.cloneCheck(userId);
|
habbo = this.cloneCheck(userId);
|
||||||
if (habbo != null) {
|
if (habbo != null) {
|
||||||
habbo.alert(Emulator.getTexts().getValue("loggedin.elsewhere"));
|
habbo.alert(Emulator.getTexts().getValue("loggedin.elsewhere"));
|
||||||
Emulator.getGameServer().getGameClientManager().disposeClient(habbo.getClient());
|
Emulator.getGameServer().getGameClientManager().forceDisposeClient(habbo.getClient());
|
||||||
habbo = null;
|
habbo = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ public class MachineIDEvent extends MessageHandler {
|
|||||||
// SSO ticket), so Habbo.connect() may have skipped the MAC-ban check for
|
// SSO ticket), so Habbo.connect() may have skipped the MAC-ban check for
|
||||||
// lack of a machineId. Enforce it now that the fingerprint is known.
|
// lack of a machineId. Enforce it now that the fingerprint is known.
|
||||||
if (Emulator.getGameEnvironment().getModToolManager().hasMACBan(this.client)) {
|
if (Emulator.getGameEnvironment().getModToolManager().hasMACBan(this.client)) {
|
||||||
Emulator.getGameServer().getGameClientManager().disposeClient(this.client);
|
Emulator.getGameServer().getGameClientManager().forceDisposeClient(this.client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.debug("Setting client MachineId to {}", storedMachineId);
|
LOGGER.debug("Setting client MachineId to {}", storedMachineId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -306,7 +306,7 @@ public class SecureLoginEvent extends MessageHandler {
|
|||||||
Emulator.getPluginManager().fireEvent(userLoginEvent);
|
Emulator.getPluginManager().fireEvent(userLoginEvent);
|
||||||
|
|
||||||
if(userLoginEvent.isCancelled()) {
|
if(userLoginEvent.isCancelled()) {
|
||||||
Emulator.getGameServer().getGameClientManager().disposeClient(this.client);
|
Emulator.getGameServer().getGameClientManager().forceDisposeClient(this.client);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public class DisconnectUser extends RCONMessage<DisconnectUser.DisconnectUserJSO
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Emulator.getGameServer().getGameClientManager().disposeClient(target.getClient());
|
Emulator.getGameServer().getGameClientManager().forceDisposeClient(target.getClient());
|
||||||
this.message = Emulator.getTexts().getValue("commands.succes.cmd_disconnect.disconnected").replace("%user%", target.getHabboInfo().getUsername());
|
this.message = Emulator.getTexts().getValue("commands.succes.cmd_disconnect.disconnected").replace("%user%", target.getHabboInfo().getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,4 +40,4 @@ public class DisconnectUser extends RCONMessage<DisconnectUser.DisconnectUserJSO
|
|||||||
|
|
||||||
public String username;
|
public String username;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -467,7 +467,7 @@ final class AccountChangeEndpoints {
|
|||||||
com.eu.habbo.habbohotel.users.Habbo habbo =
|
com.eu.habbo.habbohotel.users.Habbo habbo =
|
||||||
Emulator.getGameServer().getGameClientManager().getHabbo(userId);
|
Emulator.getGameServer().getGameClientManager().getHabbo(userId);
|
||||||
if (habbo != null && habbo.getClient() != null) {
|
if (habbo != null && habbo.getClient() != null) {
|
||||||
Emulator.getGameServer().getGameClientManager().disposeClient(habbo.getClient());
|
Emulator.getGameServer().getGameClientManager().forceDisposeClient(habbo.getClient());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -69,7 +69,7 @@ final class SessionEndpoints {
|
|||||||
com.eu.habbo.habbohotel.users.Habbo habbo =
|
com.eu.habbo.habbohotel.users.Habbo habbo =
|
||||||
Emulator.getGameServer().getGameClientManager().getHabbo(userId);
|
Emulator.getGameServer().getGameClientManager().getHabbo(userId);
|
||||||
if (habbo != null && habbo.getClient() != null) {
|
if (habbo != null && habbo.getClient() != null) {
|
||||||
Emulator.getGameServer().getGameClientManager().disposeClient(habbo.getClient());
|
Emulator.getGameServer().getGameClientManager().forceDisposeClient(habbo.getClient());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
package com.eu.habbo.habbohotel.gameclients;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
|
||||||
|
class GameClientManagerContractTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void exposesExplicitForcedDisposePath() {
|
||||||
|
assertDoesNotThrow(() -> GameClient.class.getDeclaredMethod("dispose", boolean.class));
|
||||||
|
assertDoesNotThrow(() -> GameClientManager.class.getDeclaredMethod("forceDisposeClient", GameClient.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void disposeMethodsIgnoreNullClient() {
|
||||||
|
GameClientManager manager = new GameClientManager();
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> manager.disposeClient(null));
|
||||||
|
assertDoesNotThrow(() -> manager.forceDisposeClient(null));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user