From 3bbde30ab05712d838c7eff7cbf76a28a09053b7 Mon Sep 17 00:00:00 2001
From: md_5 <md_5@live.com.au>
Date: Wed, 13 Feb 2013 12:22:25 +1100
Subject: [PATCH] Remove locking in favour of a volatile state variable.

---
 CraftBukkit-Patches/0026-Netty.patch | 103 ++++++++++++---------------
 1 file changed, 44 insertions(+), 59 deletions(-)

diff --git a/CraftBukkit-Patches/0026-Netty.patch b/CraftBukkit-Patches/0026-Netty.patch
index cb4b9327a..021f88549 100644
--- a/CraftBukkit-Patches/0026-Netty.patch
+++ b/CraftBukkit-Patches/0026-Netty.patch
@@ -1,4 +1,4 @@
-From 840a6fa0c4febdcdb5b9e0a7af30a7d04d7e3172 Mon Sep 17 00:00:00 2001
+From d5543f1ee66f0f7e7ad7dad7220887d6014feb5f Mon Sep 17 00:00:00 2001
 From: md_5 <md_5@live.com.au>
 Date: Sun, 3 Feb 2013 10:24:33 +1100
 Subject: [PATCH] Netty
@@ -17,14 +17,14 @@ This commit is licensed under the Creative Commons Attribution-ShareAlike 3.0 Un
  .../net/minecraft/server/PendingConnection.java    |  15 +-
  .../net/minecraft/server/PlayerConnection.java     |   2 +-
  src/main/java/org/spigotmc/netty/CipherCodec.java  |  65 ++++++
- .../org/spigotmc/netty/NettyNetworkManager.java    | 221 ++++++++++++++++++
+ .../org/spigotmc/netty/NettyNetworkManager.java    | 206 +++++++++++++++++
  .../org/spigotmc/netty/NettyServerConnection.java  | 105 +++++++++
  .../org/spigotmc/netty/NettySocketAdaptor.java     | 248 +++++++++++++++++++++
  .../java/org/spigotmc/netty/PacketDecoder.java     |  63 ++++++
  .../java/org/spigotmc/netty/PacketEncoder.java     |  43 ++++
  .../java/org/spigotmc/netty/PacketListener.java    | 100 +++++++++
  src/main/java/org/spigotmc/netty/ReadState.java    |  16 ++
- 12 files changed, 883 insertions(+), 7 deletions(-)
+ 12 files changed, 868 insertions(+), 7 deletions(-)
  create mode 100644 src/main/java/org/spigotmc/netty/CipherCodec.java
  create mode 100644 src/main/java/org/spigotmc/netty/NettyNetworkManager.java
  create mode 100644 src/main/java/org/spigotmc/netty/NettyServerConnection.java
@@ -210,10 +210,10 @@ index 0000000..cfc0535
 +}
 diff --git a/src/main/java/org/spigotmc/netty/NettyNetworkManager.java b/src/main/java/org/spigotmc/netty/NettyNetworkManager.java
 new file mode 100644
-index 0000000..81164a4
+index 0000000..90c63e1
 --- /dev/null
 +++ b/src/main/java/org/spigotmc/netty/NettyNetworkManager.java
-@@ -0,0 +1,221 @@
+@@ -0,0 +1,206 @@
 +package org.spigotmc.netty;
 +
 +import io.netty.channel.Channel;
@@ -249,8 +249,8 @@ index 0000000..81164a4
 +    private static final PrivateKey key = server.F().getPrivate();
 +    private static final NettyServerConnection serverConnection = (NettyServerConnection) server.ae();
 +    /*========================================================================*/
-+    private final Object mutex = new Object();
 +    private final Queue<Packet> syncPackets = new ConcurrentLinkedQueue<Packet>();
++    private volatile boolean connected;
 +    private Channel channel;
 +    private SocketAddress address;
 +    private Connection handler;
@@ -261,41 +261,31 @@ index 0000000..81164a4
 +
 +    @Override
 +    public void channelActive(ChannelHandlerContext ctx) throws Exception {
-+        synchronized (mutex) {
-+            // Channel and address groundwork first
-+            channel = ctx.channel();
-+            address = channel.remoteAddress();
-+            // Then the socket adaptor
-+            socketAdaptor = NettySocketAdaptor.adapt((SocketChannel) channel);
-+            // Followed by their first handler
-+            handler = new PendingConnection(server, this);
-+            // Finally register the connection
-+            serverConnection.pendingConnections.add((PendingConnection) handler);
-+        }
++        // Channel and address groundwork first
++        channel = ctx.channel();
++        address = channel.remoteAddress();
++        // Then the socket adaptor
++        socketAdaptor = NettySocketAdaptor.adapt((SocketChannel) channel);
++        // Followed by their first handler
++        handler = new PendingConnection(server, this);
++        // Finally register the connection
++        connected = true;
++        serverConnection.pendingConnections.add((PendingConnection) handler);
 +    }
 +
 +    @Override
 +    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
-+        synchronized (mutex) {
-+            if (dcReason == null || dcArgs == null) {
-+                a("disconnect.endOfStream", new Object[0]);
-+            }
-+            // Remove channel reference to indicate we are done
-+            channel = null;
-+        }
++        a("disconnect.endOfStream", new Object[0]);
 +    }
 +
 +    @Override
 +    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-+        synchronized (mutex) {
-+            // TODO: Remove this once we are more stable
-+            // Bukkit.getServer().getLogger().severe("======================= Start Netty Debug Log =======================");
-+            // Bukkit.getServer().getLogger().log(Level.SEVERE, "Error caught whilst handling " + channel, cause);
-+            // Bukkit.getServer().getLogger().severe("======================= End Netty Debug Log =======================");
-+
-+            // Disconnect with generic reason + exception
-+            a("disconnect.genericReason", new Object[]{"Internal exception: " + cause});
-+        }
++        // TODO: Remove this once we are more stable
++        // Bukkit.getServer().getLogger().severe("======================= Start Netty Debug Log =======================");
++        // Bukkit.getServer().getLogger().log(Level.SEVERE, "Error caught whilst handling " + channel, cause);
++        // Bukkit.getServer().getLogger().severe("======================= End Netty Debug Log =======================");
++        // Disconnect with generic reason + exception
++        a("disconnect.genericReason", new Object[]{"Internal exception: " + cause});
 +    }
 +
 +    @Override
@@ -338,22 +328,20 @@ index 0000000..81164a4
 +     * @param packet the packet to queue
 +     */
 +    public void queue(Packet packet) {
-+        synchronized (mutex) {
-+            // Only send if channel is still connected
-+            if (channel != null) {
-+                // Process packet via handler
-+                packet = PacketListener.callQueued(this, handler, packet);
-+                // If handler indicates packet send
-+                if (packet != null) {
-+                    channel.write(packet);
++        // Only send if channel is still connected
++        if (connected) {
++            // Process packet via handler
++            packet = PacketListener.callQueued(this, handler, packet);
++            // If handler indicates packet send
++            if (packet != null) {
++                channel.write(packet);
 +
-+                    // If needed, check and prepare encryption phase
-+                    if (packet instanceof Packet252KeyResponse) {
-+                        BufferedBlockCipher encrypt = NettyServerConnection.getCipher(true, secret);
-+                        BufferedBlockCipher decrypt = NettyServerConnection.getCipher(false, secret);
-+                        CipherCodec codec = new CipherCodec(encrypt, decrypt);
-+                        channel.pipeline().addBefore("decoder", "cipher", codec);
-+                    }
++                // If needed, check and prepare encryption phase
++                if (packet instanceof Packet252KeyResponse) {
++                    BufferedBlockCipher encrypt = NettyServerConnection.getCipher(true, secret);
++                    BufferedBlockCipher decrypt = NettyServerConnection.getCipher(false, secret);
++                    CipherCodec codec = new CipherCodec(encrypt, decrypt);
++                    channel.pipeline().addBefore("decoder", "cipher", codec);
 +                }
 +            }
 +        }
@@ -381,7 +369,7 @@ index 0000000..81164a4
 +        }
 +
 +        // Disconnect via the handler - this performs all plugin related cleanup + logging
-+        if ((dcReason != null || dcArgs != null) && syncPackets.isEmpty()) {
++        if (!connected) {
 +            handler.a(dcReason, dcArgs);
 +        }
 +    }
@@ -400,10 +388,9 @@ index 0000000..81164a4
 +     * close. Close and release all resources associated with this connection.
 +     */
 +    public void d() {
-+        synchronized (mutex) {
-+            if (channel != null) {
-+                channel.close();
-+            }
++        if (connected) {
++            connected = false;
++            channel.close();
 +        }
 +    }
 +
@@ -426,12 +413,10 @@ index 0000000..81164a4
 +     * exception which triggered the disconnect.
 +     */
 +    public void a(String reason, Object... arguments) {
-+        synchronized (mutex) {
-+            if (channel != null) {
-+                dcReason = reason;
-+                dcArgs = arguments;
-+                channel.close();
-+            }
++        if (connected) {
++            dcReason = reason;
++            dcArgs = arguments;
++            d();
 +        }
 +    }
 +}