diff --git a/src/main/java/fr/quatrevieux/araknemu/game/GameModule.java b/src/main/java/fr/quatrevieux/araknemu/game/GameModule.java index b4f93110c..6981de3cb 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/GameModule.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/GameModule.java @@ -363,8 +363,8 @@ public void configure(ContainerConfigurator configurator) { container -> new SessionConfigurator<>(GameSession::new) .add(new BanIpCheck<>(container.get(BanIpService.class))) .add(new RateLimiter.Configurator<>(container.get(GameConfiguration.class).packetRateLimit())) - .add(new SessionLogger.Configurator<>(container.get(Logger.class))) .add(new GameExceptionConfigurator(container.get(Logger.class))) + .add(new SessionLogger.Configurator<>(container.get(Logger.class))) .add(new GamePacketConfigurator( container.get(Dispatcher.class), container.get(PacketParser.class) diff --git a/src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java b/src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java index 61c04053d..4c1129a64 100644 --- a/src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java +++ b/src/main/java/fr/quatrevieux/araknemu/game/fight/Fight.java @@ -412,7 +412,7 @@ public void run() { executorLock.lock(); if (!alive) { - logger.warn("Cannot run task " + action.getClass().toString() + " on dead fight"); + logger.warn("Cannot run task " + action.toString() + " on dead fight"); return; } diff --git a/src/main/java/fr/quatrevieux/araknemu/network/game/GameExceptionConfigurator.java b/src/main/java/fr/quatrevieux/araknemu/network/game/GameExceptionConfigurator.java index 253923780..04462f4c0 100644 --- a/src/main/java/fr/quatrevieux/araknemu/network/game/GameExceptionConfigurator.java +++ b/src/main/java/fr/quatrevieux/araknemu/network/game/GameExceptionConfigurator.java @@ -30,6 +30,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.util.NullnessUtil; +import java.io.IOException; + /** * Configure base exception for a game session */ @@ -57,7 +59,7 @@ public void configure(ConfigurableSession inner, GameSession session) { }); inner.addExceptionHandler(CloseImmediately.class, (cause, packet) -> { - logger.error(MarkerManager.getMarker("CLOSE_IMMEDIATELY"), "[{}] Session closed : {}", context(session, packet), cause.getMessage() == null ? cause.toString() : cause.getMessage()); + logger.warn(MarkerManager.getMarker("CLOSE_IMMEDIATELY"), "[{}] Session closed : {}", context(session, packet), cause.getMessage() == null ? cause.toString() : cause.getMessage()); return true; }); @@ -69,11 +71,23 @@ public void configure(ConfigurableSession inner, GameSession session) { }); inner.addExceptionHandler(RateLimitException.class, cause -> { - logger.error(MarkerManager.getMarker("RATE_LIMIT"), "[{}] RateLimit : close session", session); + logger.warn(MarkerManager.getMarker("RATE_LIMIT"), "[{}] RateLimit : close session", session); session.close(); return true; }); + + inner.addExceptionHandler(IOException.class, cause -> { + // Ignore connection reset errors + if ( + !"Connection reset by peer".equals(cause.getMessage()) + && !"Connexion ré-initialisée par le correspondant".equals(cause.getMessage()) + ) { + logger.error("[{}] IOException : {}", session, cause.getMessage() == null ? cause.toString() : cause.getMessage()); + } + + return false; + }); } /** diff --git a/src/main/java/fr/quatrevieux/araknemu/network/realm/RealmSessionConfigurator.java b/src/main/java/fr/quatrevieux/araknemu/network/realm/RealmSessionConfigurator.java index e9b1a99cd..9f01cb032 100644 --- a/src/main/java/fr/quatrevieux/araknemu/network/realm/RealmSessionConfigurator.java +++ b/src/main/java/fr/quatrevieux/araknemu/network/realm/RealmSessionConfigurator.java @@ -28,6 +28,8 @@ import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.MarkerManager; +import java.io.IOException; + /** * Configure session for realm */ @@ -63,6 +65,18 @@ public void configure(ConfigurableSession inner, RealmSession session) { return true; }); + inner.addExceptionHandler(IOException.class, cause -> { + // Ignore connection reset errors + if ( + !"Connection reset by peer".equals(cause.getMessage()) + && !"Connexion ré-initialisée par le correspondant".equals(cause.getMessage()) + ) { + logger.error("[{}] IOException : {}", session, cause.getMessage() == null ? cause.toString() : cause.getMessage()); + } + + return false; + }); + inner.addReceiveMiddleware(new RealmPacketParserMiddleware(loginPackets, baseParser)); inner.addReceiveMiddleware((packet, next) -> dispatcher.dispatch(session, (Packet) packet)); } diff --git a/src/main/java/fr/quatrevieux/araknemu/realm/RealmModule.java b/src/main/java/fr/quatrevieux/araknemu/realm/RealmModule.java index a12f968b5..1af61a173 100644 --- a/src/main/java/fr/quatrevieux/araknemu/realm/RealmModule.java +++ b/src/main/java/fr/quatrevieux/araknemu/realm/RealmModule.java @@ -128,13 +128,13 @@ public void configure(ContainerConfigurator configurator) { container -> new SessionConfigurator<>(RealmSession::new) .add(new BanIpCheck<>(container.get(BanIpService.class))) .add(new RateLimiter.Configurator<>(container.get(RealmConfiguration.class).packetRateLimit())) - .add(new SessionLogger.Configurator<>(container.get(Logger.class))) .add(new RealmSessionConfigurator( container.get(Dispatcher.class), new PacketParser[] {DofusVersion.parser(), Credentials.parser()}, container.get(PacketParser.class), container.get(Logger.class) )) + .add(new SessionLogger.Configurator<>(container.get(Logger.class))) ); configurator.factory( diff --git a/src/test/java/fr/quatrevieux/araknemu/network/game/GameExceptionConfiguratorTest.java b/src/test/java/fr/quatrevieux/araknemu/network/game/GameExceptionConfiguratorTest.java index 351704ff6..13e81fded 100644 --- a/src/test/java/fr/quatrevieux/araknemu/network/game/GameExceptionConfiguratorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/network/game/GameExceptionConfiguratorTest.java @@ -32,7 +32,10 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import java.io.IOException; + import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; class GameExceptionConfiguratorTest extends GameBaseCase { private GameExceptionConfigurator configurator; @@ -56,7 +59,7 @@ void exceptionCaughtCloseSession() { gameSession.exception(new CloseImmediately("my error")); assertFalse(session.isLogged()); - Mockito.verify(logger).error(MarkerManager.getMarker("CLOSE_IMMEDIATELY"), "[{}] Session closed : {}", gameSession, "my error"); + Mockito.verify(logger).warn(MarkerManager.getMarker("CLOSE_IMMEDIATELY"), "[{}] Session closed : {}", gameSession, "my error"); } @Test @@ -64,7 +67,7 @@ void exceptionCaughtCloseSessionWithPacket() { gameSession.exception(new CloseImmediately("my error"), "my packet"); assertFalse(session.isLogged()); - Mockito.verify(logger).error(MarkerManager.getMarker("CLOSE_IMMEDIATELY"), "[{}] Session closed : {}", gameSession + "; packet=my packet", "my error"); + Mockito.verify(logger).warn(MarkerManager.getMarker("CLOSE_IMMEDIATELY"), "[{}] Session closed : {}", gameSession + "; packet=my packet", "my error"); } @Test @@ -103,6 +106,23 @@ void exceptionCaughtRateLimit() { gameSession.exception(new RateLimitException()); assertFalse(session.isAlive()); - Mockito.verify(logger).error(MarkerManager.getMarker("RATE_LIMIT"), "[{}] RateLimit : close session", gameSession); + Mockito.verify(logger).warn(MarkerManager.getMarker("RATE_LIMIT"), "[{}] RateLimit : close session", gameSession); + } + + @Test + void exceptionShouldIgnoreConnectionReset() { + gameSession.exception(new IOException("Connection reset by peer")); + gameSession.exception(new IOException("Connexion ré-initialisée par le correspondant")); + + assertTrue(session.isAlive()); + Mockito.verifyNoInteractions(logger); + } + + @Test + void exceptionShouldLogIOException() { + gameSession.exception(new IOException("My error")); + + assertTrue(session.isAlive()); + Mockito.verify(logger).error("[{}] IOException : {}", gameSession, "My error"); } } diff --git a/src/test/java/fr/quatrevieux/araknemu/network/realm/RealmSessionConfiguratorTest.java b/src/test/java/fr/quatrevieux/araknemu/network/realm/RealmSessionConfiguratorTest.java index 7e556a06f..89a9e4d3d 100644 --- a/src/test/java/fr/quatrevieux/araknemu/network/realm/RealmSessionConfiguratorTest.java +++ b/src/test/java/fr/quatrevieux/araknemu/network/realm/RealmSessionConfiguratorTest.java @@ -40,7 +40,10 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import java.io.IOException; + import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; class RealmSessionConfiguratorTest extends RealmBaseCase { private RealmSessionConfigurator configurator; @@ -109,4 +112,31 @@ void exceptionCaughtRateLimit() { assertFalse(session.isAlive()); Mockito.verify(logger).error(MarkerManager.getMarker("RATE_LIMIT"), "[{}] RateLimit : close session", realmSession); } + + @Test + void exceptionShouldIgnoreConnectionReset() { + ConfigurableSession session = new ConfigurableSession(channel); + RealmSession realmSession = new RealmSession(session); + + configurator.configure(session, realmSession); + + realmSession.exception(new IOException("Connection reset by peer")); + realmSession.exception(new IOException("Connexion ré-initialisée par le correspondant")); + + assertFalse(session.isAlive()); + Mockito.verifyNoInteractions(logger); + } + + @Test + void exceptionShouldLogIOException() { + ConfigurableSession session = new ConfigurableSession(channel); + RealmSession realmSession = new RealmSession(session); + + configurator.configure(session, realmSession); + + realmSession.exception(new IOException("My error")); + + assertFalse(session.isAlive()); + Mockito.verify(logger).error("[{}] IOException : {}", realmSession, "My error"); + } }