From c3e4a6ef5bbb4dadce5477e00b8b169a5c5edd24 Mon Sep 17 00:00:00 2001
From: Outfluencer <git@outfluencer.dev>
Date: Sat, 8 Feb 2025 15:50:43 +1100
Subject: [PATCH] #3779: Improve eventloop consistency and isClosing code

---
 .../bungee/connection/InitialHandler.java     | 78 +++++++++----------
 1 file changed, 36 insertions(+), 42 deletions(-)

diff --git a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
index 472714b3..b8542177 100644
--- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
+++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java
@@ -2,6 +2,7 @@ package net.md_5.bungee.connection;
 
 import com.google.common.base.Preconditions;
 import com.google.gson.Gson;
+import io.netty.channel.EventLoop;
 import java.math.BigInteger;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
@@ -228,11 +229,6 @@ public class InitialHandler extends PacketHandler implements PendingConnection
                     @Override
                     public void done(ProxyPingEvent result, Throwable error)
                     {
-                        if ( ch.isClosing() )
-                        {
-                            return;
-                        }
-
                         ServerPing legacy = result.getResponse();
                         String kickMessage;
 
@@ -256,7 +252,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
                     }
                 };
 
-                bungee.getPluginManager().callEvent( new ProxyPingEvent( InitialHandler.this, result, callback ) );
+                bungee.getPluginManager().callEvent( new ProxyPingEvent( InitialHandler.this, result, eventLoopCallback( callback ) ) );
             }
         };
 
@@ -318,7 +314,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
                     }
                 };
 
-                bungee.getPluginManager().callEvent( new ProxyPingEvent( InitialHandler.this, result, callback ) );
+                bungee.getPluginManager().callEvent( new ProxyPingEvent( InitialHandler.this, result, eventLoopCallback( callback ) ) );
             }
         };
 
@@ -484,10 +480,6 @@ public class InitialHandler extends PacketHandler implements PendingConnection
                     disconnect( ( reason != null ) ? reason : TextComponent.fromLegacy( bungee.getTranslation( "kick_message" ) ) );
                     return;
                 }
-                if ( ch.isClosing() )
-                {
-                    return;
-                }
                 if ( onlineMode )
                 {
                     thisState = State.ENCRYPT;
@@ -501,7 +493,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
         };
 
         // fire pre login event
-        bungee.getPluginManager().callEvent( new PreLoginEvent( InitialHandler.this, callback ) );
+        bungee.getPluginManager().callEvent( new PreLoginEvent( InitialHandler.this, eventLoopCallback( callback ) ) );
     }
 
     @Override
@@ -621,35 +613,21 @@ public class InitialHandler extends PacketHandler implements PendingConnection
                     disconnect( ( reason != null ) ? reason : TextComponent.fromLegacy( bungee.getTranslation( "kick_message" ) ) );
                     return;
                 }
-                if ( ch.isClosing() )
+
+                userCon = new UserConnection( bungee, ch, getName(), InitialHandler.this );
+                userCon.setCompressionThreshold( BungeeCord.getInstance().config.getCompressionThreshold() );
+
+                if ( getVersion() < ProtocolConstants.MINECRAFT_1_20_2 )
                 {
-                    return;
+                    unsafe.sendPacket( new LoginSuccess( getRewriteId(), getName(), ( loginProfile == null ) ? null : loginProfile.getProperties() ) );
+                    ch.setProtocol( Protocol.GAME );
                 }
-
-                ch.getHandle().eventLoop().execute( new Runnable()
-                {
-                    @Override
-                    public void run()
-                    {
-                        if ( !ch.isClosing() )
-                        {
-                            userCon = new UserConnection( bungee, ch, getName(), InitialHandler.this );
-                            userCon.setCompressionThreshold( BungeeCord.getInstance().config.getCompressionThreshold() );
-
-                            if ( getVersion() < ProtocolConstants.MINECRAFT_1_20_2 )
-                            {
-                                unsafe.sendPacket( new LoginSuccess( getRewriteId(), getName(), ( loginProfile == null ) ? null : loginProfile.getProperties() ) );
-                                ch.setProtocol( Protocol.GAME );
-                            }
-                            finish2();
-                        }
-                    }
-                } );
+                finish2();
             }
         };
 
         // fire login event
-        bungee.getPluginManager().callEvent( new LoginEvent( InitialHandler.this, complete ) );
+        bungee.getPluginManager().callEvent( new LoginEvent( InitialHandler.this, eventLoopCallback( complete ) ) );
     }
 
     private void finish2()
@@ -680,18 +658,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
             @Override
             public void done(PostLoginEvent result, Throwable error)
             {
-                // #3612: Don't progress further if disconnected during event
-                if ( ch.isClosing() )
-                {
-                    return;
-                }
-
                 userCon.connect( result.getTarget(), null, true, ServerConnectEvent.Reason.JOIN_PROXY );
             }
         };
 
         // fire post-login event
-        bungee.getPluginManager().callEvent( new PostLoginEvent( userCon, initialServer, complete ) );
+        bungee.getPluginManager().callEvent( new PostLoginEvent( userCon, initialServer, eventLoopCallback( complete ) ) );
     }
 
     @Override
@@ -920,4 +892,26 @@ public class InitialHandler extends PacketHandler implements PendingConnection
         unsafe.sendPacket( new LoginPayloadRequest( id, channel, data ) );
         return future;
     }
+
+    // this method is used for event execution
+    // if this connection is disconnected during an event-call, the original callback is not called
+    // if the event was executed async, we execute the callback on the eventloop again
+    // otherwise netty will schedule any pipeline related call by itself, this decreases performance
+    private <T> Callback<T> eventLoopCallback(Callback<T> callback)
+    {
+        EventLoop eventLoop = ch.getHandle().eventLoop();
+        return eventLoop.inEventLoop() ? (result, error) ->
+        {
+            if ( !ch.isClosing() )
+            {
+                callback.done( result, error );
+            }
+        } : (result, error) -> eventLoop.execute( () ->
+        {
+            if ( !ch.isClosing() )
+            {
+                callback.done( result, error );
+            }
+        } );
+    }
 }