From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=84=97=E3=84=A0=CB=8B=20=E3=84=91=E3=84=A7=CB=8A?= Date: Sun, 5 Apr 2020 14:59:10 +0800 Subject: [PATCH] Optimizations for network diff --git a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java index a85466bc7e0a8aa54b9eff14077fe6c992ae2902..324af1a12a5780170f8cd6e060ff2f2f9d152c3d 100644 --- a/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java +++ b/src/main/java/com/destroystokyo/paper/network/StandardPaperServerListPingEventImpl.java @@ -106,7 +106,7 @@ public final class StandardPaperServerListPingEventImpl extends PaperServerListP } // Send response - networkManager.sendPacket(new PacketStatusOutServerInfo(ping)); + networkManager.sendPacketAsync(new PacketStatusOutServerInfo(ping)); // Akarin - Async Sending packets } } diff --git a/src/main/java/net/minecraft/server/HandshakeListener.java b/src/main/java/net/minecraft/server/HandshakeListener.java index 0532f975b7af5b3f2916c26141221cd3701765d0..e7be1074b1b8fde3590b1323508965961824e671 100644 --- a/src/main/java/net/minecraft/server/HandshakeListener.java +++ b/src/main/java/net/minecraft/server/HandshakeListener.java @@ -39,7 +39,7 @@ public class HandshakeListener implements PacketHandshakingInListener { if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { throttleTracker.put(address, currentTime); chatmessage = new ChatMessage(com.destroystokyo.paper.PaperConfig.connectionThrottleKickMessage); // Paper - Configurable connection throttle kick message - this.b.sendPacket(new PacketLoginOutDisconnect(chatmessage)); + this.b.sendPacketAsync(new PacketLoginOutDisconnect(chatmessage)); // Akarin - Async Sending packets this.b.close(chatmessage); return; } @@ -66,11 +66,11 @@ public class HandshakeListener implements PacketHandshakingInListener { if (packethandshakinginsetprotocol.c() > SharedConstants.getGameVersion().getProtocolVersion()) { chatmessage = new ChatMessage( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) ); // Spigot - this.b.sendPacket(new PacketLoginOutDisconnect(chatmessage)); + this.b.sendPacketAsync(new PacketLoginOutDisconnect(chatmessage)); this.b.close(chatmessage); } else if (packethandshakinginsetprotocol.c() < SharedConstants.getGameVersion().getProtocolVersion()) { chatmessage = new ChatMessage( java.text.MessageFormat.format( org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getGameVersion().getName() ) ); // Spigot - this.b.sendPacket(new PacketLoginOutDisconnect(chatmessage)); + this.b.sendPacketAsync(new PacketLoginOutDisconnect(chatmessage)); this.b.close(chatmessage); } else { this.b.setPacketListener(new LoginListener(this.a, this.b)); diff --git a/src/main/java/net/minecraft/server/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java index f1222fcb2bd52b8781d0f92c94e1472fa7b1e493..522cfed4cb09bc9ecc48b6313da47f9af7a5e1d8 100644 --- a/src/main/java/net/minecraft/server/LoginListener.java +++ b/src/main/java/net/minecraft/server/LoginListener.java @@ -111,6 +111,19 @@ public class LoginListener implements PacketLoginInListener { } + // Akarin Start - Async Sending packets + public void disconnectAsync(IChatBaseComponent ichatbasecomponent) { + try { + LoginListener.LOGGER.info("Disconnecting {}: {}", this.d(), ichatbasecomponent.getString()); + this.networkManager.sendPacketAsync(new PacketLoginOutDisconnect(ichatbasecomponent)); + this.networkManager.close(ichatbasecomponent); + } catch (Exception exception) { + LoginListener.LOGGER.error("Error whilst disconnecting player", exception); + } + + } + // Akarin End - Async Sending packets + // Paper start - Cache authenticator threads private static final AtomicInteger threadId = new AtomicInteger(0); private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool( @@ -192,7 +205,7 @@ public class LoginListener implements PacketLoginInListener { this.i = packetlogininstart.b(); if (this.server.getOnlineMode() && !this.networkManager.isLocal()) { this.g = LoginListener.EnumProtocolState.KEY; - this.networkManager.sendPacket(new PacketLoginOutEncryptionBegin("", this.server.getKeyPair().getPublic(), this.e)); + this.networkManager.sendPacketAsync(new PacketLoginOutEncryptionBegin("", this.server.getKeyPair().getPublic(), this.e)); // Akarin - Async Sending packets } else { // Paper start - Velocity support if (com.destroystokyo.paper.PaperConfig.velocitySupport) { @@ -254,7 +267,7 @@ public class LoginListener implements PacketLoginInListener { LoginListener.this.i = LoginListener.this.a(gameprofile); LoginListener.this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT; } else { - LoginListener.this.disconnect(new ChatMessage("multiplayer.disconnect.unverified_username", new Object[0])); + LoginListener.this.disconnectAsync(new ChatMessage("multiplayer.disconnect.unverified_username", new Object[0])); // Akarin - Async Sending packets LoginListener.LOGGER.error("Username '{}' tried to join with an invalid session", gameprofile.getName()); } } catch (AuthenticationUnavailableException authenticationunavailableexception) { @@ -267,7 +280,7 @@ public class LoginListener implements PacketLoginInListener { if (com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage != null) { LoginListener.this.disconnect(new ChatComponentText(com.destroystokyo.paper.PaperConfig.authenticationServersDownKickMessage)); } else // Paper end - LoginListener.this.disconnect(new ChatMessage("multiplayer.disconnect.authservers_down", new Object[0])); + LoginListener.this.disconnectAsync(new ChatMessage("multiplayer.disconnect.authservers_down", new Object[0])); // Akarin - Async Sending packets LoginListener.LOGGER.error("Couldn't verify username because servers are unavailable"); } // CraftBukkit start - catch all exceptions @@ -376,7 +389,7 @@ public class LoginListener implements PacketLoginInListener { return; } // Paper end - this.disconnect(new ChatMessage("multiplayer.disconnect.unexpected_query_response", new Object[0])); + this.disconnectAsync(new ChatMessage("multiplayer.disconnect.unexpected_query_response", new Object[0])); // Akarin - Async Sending packets } protected GameProfile a(GameProfile gameprofile) { diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java index 96a785af27e1924b0cc1959254d4ae3cdd0385a1..c5e32e42465aece552f09bc5c73d6e0d51735c91 100644 --- a/src/main/java/net/minecraft/server/NetworkManager.java +++ b/src/main/java/net/minecraft/server/NetworkManager.java @@ -43,6 +43,8 @@ public class NetworkManager extends SimpleChannelInboundHandler> { }); private final EnumProtocolDirection h; private final Queue packetQueue = Queues.newConcurrentLinkedQueue(); private final Queue getPacketQueue() { return this.packetQueue; } // Paper - OBFHELPER + private boolean handled = false; // Akarin - free packet queue + private EnumProtocol protocol; // Akarin - avoid map lookup public Channel channel; public SocketAddress socketAddress; public void setSpoofedRemoteAddress(SocketAddress address) { this.socketAddress = address; } // Paper - OBFHELPER // Spigot Start @@ -88,6 +90,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { public void setProtocol(EnumProtocol enumprotocol) { this.channel.attr(NetworkManager.c).set(enumprotocol); + protocol = enumprotocol; // Akarin - avoid map lookup this.channel.config().setAutoRead(true); NetworkManager.LOGGER.debug("Enabled auto read"); } @@ -175,8 +178,8 @@ public class NetworkManager extends SimpleChannelInboundHandler> { private void dispatchPacket(Packet packet, @Nullable GenericFutureListener> genericFutureListener) { this.b(packet, genericFutureListener); } // Paper - OBFHELPER private void b(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { - EnumProtocol enumprotocol = EnumProtocol.a(packet); - EnumProtocol enumprotocol1 = (EnumProtocol) this.channel.attr(NetworkManager.c).get(); + EnumProtocol enumprotocol = packet.protocol();//EnumProtocol.a(packet); // Akarin - avoid map lookup + EnumProtocol enumprotocol1 = protocol;//(EnumProtocol) this.channel.attr(NetworkManager.c).get(); // Akarin - avoid map lookup ++this.q; if (enumprotocol1 != enumprotocol) { @@ -184,7 +187,7 @@ public class NetworkManager extends SimpleChannelInboundHandler> { this.channel.config().setAutoRead(false); } - if (this.channel.eventLoop().inEventLoop()) { + if (false && this.channel.eventLoop().inEventLoop()) { // Akarin - Async Sending packets if (enumprotocol != enumprotocol1) { this.setProtocol(enumprotocol); } @@ -223,9 +226,51 @@ public class NetworkManager extends SimpleChannelInboundHandler> { } + // Akarin Start - Async Sending packets - multiple packets, copied from above + public void sendPacketAsync(Packet packet) { + EnumProtocol enumprotocol = packet.protocol(); + EnumProtocol enumprotocol1 = protocol; + + ++this.q; + if (enumprotocol1 != enumprotocol) { + NetworkManager.LOGGER.debug("Disabled auto read"); + this.channel.config().setAutoRead(false); + this.setProtocol(enumprotocol); + } + + ChannelFuture channelfuture = this.channel.writeAndFlush(packet); + + channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); + + } + + public void sendPackets(Packet packet, Packet ...packets) { + EnumProtocol enumprotocol = packet.protocol(); + + ++this.q; + if (protocol != enumprotocol) { + NetworkManager.LOGGER.debug("Disabled auto read"); + this.channel.config().setAutoRead(false); + } + + this.channel.eventLoop().execute(() -> { + if (enumprotocol != protocol) { + this.setProtocol(enumprotocol); + } + + this.channel.write(packet).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); + for (Packet pkt : packets) { + this.channel.write(pkt).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); + } + this.channel.flush(); + }); + } + // Akarin End + // Paper start - Async-Anti-Xray - Stop dispatching further packets and return false if the peeked packet is a chunk packet which is not ready private boolean sendPacketQueue() { return this.o(); } // OBFHELPER // void -> boolean private boolean o() { // void -> boolean + if (!handled) { // Akarin - free packet queue if (this.channel != null && this.channel.isOpen()) { Queue queue = this.packetQueue; @@ -245,6 +290,8 @@ public class NetworkManager extends SimpleChannelInboundHandler> { } } + handled = true; // Akarin - free packet queue + } // Akarin - free packet queue return true; // Return true if all packets were dispatched } @@ -260,9 +307,9 @@ public class NetworkManager extends SimpleChannelInboundHandler> { ((PlayerConnection) this.packetListener).tick(); } - if (this.channel != null) { - if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version - } + //if (this.channel != null) { // Akarin - already did + //if (enableExplicitFlush) this.channel.eventLoop().execute(() -> this.channel.flush()); // Paper - we don't need to explicit flush here, but allow opt in incase issues are found to a better version + //} if (this.t++ % 20 == 0) { this.s = this.s * 0.75F + (float) this.q * 0.25F; diff --git a/src/main/java/net/minecraft/server/Packet.java b/src/main/java/net/minecraft/server/Packet.java index 8d0965a0535b16f19eda21b97a44464b85b05460..7e27cd280fa889f6178d46aa9f9d3a613d9702e6 100644 --- a/src/main/java/net/minecraft/server/Packet.java +++ b/src/main/java/net/minecraft/server/Packet.java @@ -20,4 +20,10 @@ public interface Packet { default boolean a() { return false; } + + // Akarin start - add protocol + default EnumProtocol protocol() { + return EnumProtocol.PLAY; + } + // Akarin end } diff --git a/src/main/java/net/minecraft/server/PacketLoginOutCustomPayload.java b/src/main/java/net/minecraft/server/PacketLoginOutCustomPayload.java index 7eb230f1b27eddf48f1b12fc78877a3678d802df..d01cac0bd40a11d82fa0d6874d87ad3f576a4e20 100644 --- a/src/main/java/net/minecraft/server/PacketLoginOutCustomPayload.java +++ b/src/main/java/net/minecraft/server/PacketLoginOutCustomPayload.java @@ -41,4 +41,11 @@ public class PacketLoginOutCustomPayload implements Packet public void a(PacketLoginOutListener packetloginoutlistener) { packetloginoutlistener.a(this); } + + // Akarin start - add protocol + @Override + public EnumProtocol protocol() { + return EnumProtocol.LOGIN; + } + // Akarin end } diff --git a/src/main/java/net/minecraft/server/PacketLoginOutEncryptionBegin.java b/src/main/java/net/minecraft/server/PacketLoginOutEncryptionBegin.java index b0d6342c319a48290fd8bf6aa07a16d108feae18..eeabb54c44d39197f34a7171884cc7e885bce453 100644 --- a/src/main/java/net/minecraft/server/PacketLoginOutEncryptionBegin.java +++ b/src/main/java/net/minecraft/server/PacketLoginOutEncryptionBegin.java @@ -34,4 +34,11 @@ public class PacketLoginOutEncryptionBegin implements Packet { public void a(PacketLoginOutListener packetloginoutlistener) { packetloginoutlistener.a(this); } + + // Akarin start - add protocol + @Override + public EnumProtocol protocol() { + return EnumProtocol.LOGIN; + } + // Akarin end } diff --git a/src/main/java/net/minecraft/server/PacketStatusListener.java b/src/main/java/net/minecraft/server/PacketStatusListener.java index 4bb21c48bd50353370ec3c3546a00a5d20e4b9d8..06af567fc1fb3a2053eb4e8af6d93dbb2391616a 100644 --- a/src/main/java/net/minecraft/server/PacketStatusListener.java +++ b/src/main/java/net/minecraft/server/PacketStatusListener.java @@ -143,7 +143,7 @@ public class PacketStatusListener implements PacketStatusInListener { @Override public void a(PacketStatusInPing packetstatusinping) { - this.networkManager.sendPacket(new PacketStatusOutPong(packetstatusinping.b())); + this.networkManager.sendPacketAsync(new PacketStatusOutPong(packetstatusinping.b())); // Akarin - Async Sending packets this.networkManager.close(PacketStatusListener.a); } } diff --git a/src/main/java/net/minecraft/server/PacketStatusOutPong.java b/src/main/java/net/minecraft/server/PacketStatusOutPong.java index 94a0da87db34ee5131686e4fa813500794ffc30d..577c6ef9cfe26d38783cd38353720b0fe457d7f5 100644 --- a/src/main/java/net/minecraft/server/PacketStatusOutPong.java +++ b/src/main/java/net/minecraft/server/PacketStatusOutPong.java @@ -25,4 +25,11 @@ public class PacketStatusOutPong implements Packet { public void a(PacketStatusOutListener packetstatusoutlistener) { packetstatusoutlistener.a(this); } + + // Akarin start - add protocol + @Override + public EnumProtocol protocol() { + return EnumProtocol.STATUS; + } + // Akarin end } diff --git a/src/main/java/net/minecraft/server/PacketStatusOutServerInfo.java b/src/main/java/net/minecraft/server/PacketStatusOutServerInfo.java index 50d5fb62efa7c89c7a73ccf072a0e7e433bcc650..4da7a2c1a4f84661e1018c7233b7a52449532d5b 100644 --- a/src/main/java/net/minecraft/server/PacketStatusOutServerInfo.java +++ b/src/main/java/net/minecraft/server/PacketStatusOutServerInfo.java @@ -28,4 +28,11 @@ public class PacketStatusOutServerInfo implements Packet