From c841430c32d435edb7406443771cba7dddf29216 Mon Sep 17 00:00:00 2001 From: Obique Date: Wed, 11 Feb 2015 08:28:56 -0600 Subject: [PATCH] Fixed ConnectionService bugs and improved the disconnect system --- src/services/galaxy/ConnectionService.java | 73 ++++++++++++++++++---- src/services/player/PlayerManager.java | 2 - 2 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/services/galaxy/ConnectionService.java b/src/services/galaxy/ConnectionService.java index 206003e93..32bcd388f 100644 --- a/src/services/galaxy/ConnectionService.java +++ b/src/services/galaxy/ConnectionService.java @@ -1,12 +1,17 @@ package services.galaxy; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Queue; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import network.packets.soe.Disconnect; +import network.packets.soe.Disconnect.DisconnectReason; import network.packets.swg.zone.HeartBeatMessage; +import intents.CloseConnectionIntent; import intents.GalacticPacketIntent; import intents.PlayerEventIntent; import resources.control.Intent; @@ -17,33 +22,40 @@ import resources.player.PlayerState; public class ConnectionService extends Service { - private static final double LD_THRESHOLD = TimeUnit.SECONDS.toMillis(30); - private static final double DISAPPEAR_THRESHOLD = TimeUnit.MINUTES.toMillis(3); + private static final double LD_THRESHOLD = TimeUnit.MINUTES.toMillis(3); // Time since last packet + private static final double DISAPPEAR_THRESHOLD = TimeUnit.MINUTES.toMillis(2); // Time after the LD private final ScheduledExecutorService updateService; private final Runnable updateRunnable; + private final Runnable disappearRunnable; + private final Queue disappearPlayers; private final List zonedInPlayers; public ConnectionService() { updateService = Executors.newSingleThreadScheduledExecutor(); zonedInPlayers = new LinkedList(); + disappearPlayers = new LinkedList(); updateRunnable = new Runnable() { public void run() { synchronized (zonedInPlayers) { for (Player p : zonedInPlayers) { - if (p.getTimeSinceLastPacket() > DISAPPEAR_THRESHOLD) { - p.setPlayerState(PlayerState.DISCONNECTED); - System.out.println("[" + p.getUsername() +"] " + p.getCharacterName() + " disappeared"); - new PlayerEventIntent(p, PlayerEvent.PE_DISAPPEAR).broadcast(); - } else if (p.getTimeSinceLastPacket() > LD_THRESHOLD) { - if (p.getPlayerState() != PlayerState.LOGGED_OUT) - System.out.println("[" + p.getUsername() +"] Logged out " + p.getCharacterName()); - p.setPlayerState(PlayerState.LOGGED_OUT); + if (p.getTimeSinceLastPacket() > LD_THRESHOLD) { + logOut(p); + disconnect(p, DisconnectReason.TIMEOUT); } } } } }; + disappearRunnable = new Runnable() { + public void run() { + Player p = disappearPlayers.poll(); + synchronized (zonedInPlayers) { + if (p != null && zonedInPlayers.contains(p)) + disappear(p); + } + } + }; } @Override @@ -77,8 +89,7 @@ public class ConnectionService extends Service { if (((PlayerEventIntent)i).getEvent() == PlayerEvent.PE_ZONE_IN) { Player p = ((PlayerEventIntent)i).getPlayer(); synchronized (zonedInPlayers) { - if (zonedInPlayers.contains(p)) - zonedInPlayers.remove(p); + removeOld(p); zonedInPlayers.add(p); } } else if (((PlayerEventIntent)i).getEvent() == PlayerEvent.PE_DISAPPEAR) { @@ -92,8 +103,46 @@ public class ConnectionService extends Service { Player p = gpi.getPlayerManager().getPlayerFromNetworkId(gpi.getNetworkId()); if (p != null) p.sendPacket(gpi.getPacket()); + } else if (((GalacticPacketIntent)i).getPacket() instanceof Disconnect) { + GalacticPacketIntent gpi = (GalacticPacketIntent) i; + Player p = gpi.getPlayerManager().getPlayerFromNetworkId(gpi.getNetworkId()); + if (p != null) { + logOut(p); + disconnect(p, DisconnectReason.OTHER_SIDE_TERMINATED); + } } } } + private void removeOld(Player nPlayer) { + synchronized (zonedInPlayers) { + Iterator zonedIterator = zonedInPlayers.iterator(); + while (zonedIterator.hasNext()) { + Player old = zonedIterator.next(); + if (old.equals(nPlayer)) { + zonedIterator.remove(); + disconnect(old, DisconnectReason.NEW_CONNECTION_ATTEMPT); + } + } + } + } + + private void logOut(Player p) { + if (p.getPlayerState() != PlayerState.LOGGED_OUT) + System.out.println("[" + p.getUsername() +"] Logged out " + p.getCharacterName()); + p.setPlayerState(PlayerState.LOGGED_OUT); + disappearPlayers.add(p); + updateService.schedule(disappearRunnable, (long) DISAPPEAR_THRESHOLD, TimeUnit.MILLISECONDS); + } + + private void disappear(Player p) { + p.setPlayerState(PlayerState.DISCONNECTED); + System.out.println("[" + p.getUsername() +"] " + p.getCharacterName() + " disappeared"); + new PlayerEventIntent(p, PlayerEvent.PE_DISAPPEAR).broadcast(); + } + + private void disconnect(Player player, DisconnectReason reason) { + new CloseConnectionIntent(player.getConnectionId(), player.getNetworkId(), reason).broadcast(); + } + } diff --git a/src/services/player/PlayerManager.java b/src/services/player/PlayerManager.java index 00460f143..e87338406 100644 --- a/src/services/player/PlayerManager.java +++ b/src/services/player/PlayerManager.java @@ -9,7 +9,6 @@ import java.util.Map; import network.packets.Packet; import network.packets.swg.login.ClientIdMsg; import network.packets.swg.zone.insertion.SelectCharacter; -import intents.CloseConnectionIntent; import intents.GalacticPacketIntent; import intents.NotifyPlayersPacketIntent; import intents.InboundPacketIntent; @@ -87,7 +86,6 @@ public class PlayerManager extends Manager { Player p = pei.getPlayer(); if (p.getPlayerState() == PlayerState.DISCONNECTED) { players.remove(p.getNetworkId()); - new CloseConnectionIntent(p.getNetworkId()).broadcast(); } } } else if (i instanceof NotifyPlayersPacketIntent) {