diff options
Diffstat (limited to 'src/main/java/net/minecraft/server/NetworkManager.java')
-rw-r--r-- | src/main/java/net/minecraft/server/NetworkManager.java | 449 |
1 files changed, 135 insertions, 314 deletions
diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java index a2bdfa32..8f829bb9 100644 --- a/src/main/java/net/minecraft/server/NetworkManager.java +++ b/src/main/java/net/minecraft/server/NetworkManager.java @@ -1,377 +1,198 @@ package net.minecraft.server; -import java.io.BufferedOutputStream; -import java.io.DataInputStream; -import java.io.DataOutput; -import java.io.DataOutputStream; -import java.io.InputStream; -import java.net.Socket; import java.net.SocketAddress; -import java.net.SocketException; -import java.security.PrivateKey; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicInteger; import javax.crypto.SecretKey; -import java.io.IOException; // CraftBukkit - -public class NetworkManager implements INetworkManager { - - public static AtomicInteger a = new AtomicInteger(); - public static AtomicInteger b = new AtomicInteger(); - private final Object h = new Object(); - private final IConsoleLogManager i; - public Socket socket; // CraftBukkit - private -> public - private final SocketAddress k; - private volatile DataInputStream input; - private volatile DataOutputStream output; - private volatile boolean n = true; - private volatile boolean o; - private Queue inboundQueue = new ConcurrentLinkedQueue(); - private List highPriorityQueue = Collections.synchronizedList(new ArrayList()); - private List lowPriorityQueue = Collections.synchronizedList(new ArrayList()); - private Connection connection; - private boolean t; - private Thread u; - private Thread v; - private String w = ""; - private Object[] x; - private int y; - private int z; - public static int[] c = new int[256]; - public static int[] d = new int[256]; - public int e; - boolean f; - boolean g; - private SecretKey A; - private PrivateKey B; - private int lowPriorityQueueDelay = 50; - - public NetworkManager(IConsoleLogManager iconsolelogmanager, Socket socket, String s, Connection connection, PrivateKey privatekey) throws IOException { // CraftBukkit - throws IOException - this.B = privatekey; - this.socket = socket; - this.i = iconsolelogmanager; - this.k = socket.getRemoteSocketAddress(); - this.connection = connection; - - try { - socket.setSoTimeout(30000); - socket.setTrafficClass(24); - } catch (SocketException socketexception) { - System.err.println(socketexception.getMessage()); - } - - this.input = new DataInputStream(socket.getInputStream()); - this.output = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream(), 5120)); - this.v = new NetworkReaderThread(this, s + " read thread"); - this.u = new NetworkWriterThread(this, s + " write thread"); - this.v.start(); - this.u.start(); - } - - public void a(Connection connection) { - this.connection = connection; - } - - public void queue(Packet packet) { - if (!this.t) { - Object object = this.h; - - synchronized (this.h) { - this.z += packet.a() + 1; - this.highPriorityQueue.add(packet); - } - } - } - - private boolean h() { - boolean flag = false; - - try { - Packet packet; - int i; - int[] aint; - - if (this.e == 0 || !this.highPriorityQueue.isEmpty() && MinecraftServer.aq() - ((Packet) this.highPriorityQueue.get(0)).timestamp >= (long) this.e) { - packet = this.a(false); - if (packet != null) { - Packet.a(packet, (DataOutput) this.output); - if (packet instanceof Packet252KeyResponse && !this.g) { - if (!this.connection.a()) { - this.A = ((Packet252KeyResponse) packet).d(); - } - - this.k(); - } - - aint = d; - i = packet.n(); - aint[i] += packet.a() + 1; - flag = true; - } - } - - // CraftBukkit - don't allow low priority packet to be sent unless it was placed in the queue before the first packet on the high priority queue TODO: is this still right? - if ((flag || this.lowPriorityQueueDelay-- <= 0) && !this.lowPriorityQueue.isEmpty() && (this.highPriorityQueue.isEmpty() || ((Packet) this.highPriorityQueue.get(0)).timestamp > ((Packet) this.lowPriorityQueue.get(0)).timestamp)) { - packet = this.a(true); - if (packet != null) { - Packet.a(packet, (DataOutput) this.output); - aint = d; - i = packet.n(); - aint[i] += packet.a() + 1; - this.lowPriorityQueueDelay = 0; - flag = true; - } - } - - return flag; - } catch (Exception exception) { - if (!this.o) { - this.a(exception); +import net.minecraft.util.com.google.common.collect.Queues; +import net.minecraft.util.com.google.common.util.concurrent.ThreadFactoryBuilder; +import net.minecraft.util.io.netty.channel.Channel; +import net.minecraft.util.io.netty.channel.ChannelFutureListener; +import net.minecraft.util.io.netty.channel.ChannelHandlerContext; +import net.minecraft.util.io.netty.channel.SimpleChannelInboundHandler; +import net.minecraft.util.io.netty.channel.local.LocalChannel; +import net.minecraft.util.io.netty.channel.local.LocalServerChannel; +import net.minecraft.util.io.netty.channel.nio.NioEventLoopGroup; +import net.minecraft.util.io.netty.util.AttributeKey; +import net.minecraft.util.io.netty.util.concurrent.GenericFutureListener; +import net.minecraft.util.org.apache.commons.lang3.Validate; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.MarkerManager; + +public class NetworkManager extends SimpleChannelInboundHandler { + + private static final Logger g = LogManager.getLogger(); + public static final Marker a = MarkerManager.getMarker("NETWORK"); + public static final Marker b = MarkerManager.getMarker("NETWORK_PACKETS", a); + public static final AttributeKey c = new AttributeKey("protocol"); + public static final AttributeKey d = new AttributeKey("receivable_packets"); + public static final AttributeKey e = new AttributeKey("sendable_packets"); + public static final NioEventLoopGroup f = new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Client IO #%d").setDaemon(true).build()); + private final boolean h; + private final Queue i = Queues.newConcurrentLinkedQueue(); + private final Queue j = Queues.newConcurrentLinkedQueue(); + private Channel k; + private SocketAddress l; + private PacketListener m; + private EnumProtocol n; + private IChatBaseComponent o; + + public NetworkManager(boolean flag) { + this.h = flag; + } + + public void channelActive(ChannelHandlerContext channelhandlercontext) throws Exception { // CraftBukkit - throws Exception + super.channelActive(channelhandlercontext); + this.k = channelhandlercontext.channel(); + this.l = this.k.remoteAddress(); + this.a(EnumProtocol.HANDSHAKING); + } + + public void a(EnumProtocol enumprotocol) { + this.n = (EnumProtocol) this.k.attr(c).getAndSet(enumprotocol); + this.k.attr(d).set(enumprotocol.a(this.h)); + this.k.attr(e).set(enumprotocol.b(this.h)); + this.k.config().setAutoRead(true); + g.debug("Enabled auto read"); + } + + public void channelInactive(ChannelHandlerContext channelhandlercontext) { + this.a((IChatBaseComponent) (new ChatMessage("disconnect.endOfStream", new Object[0]))); + } + + public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) { + this.a((IChatBaseComponent) (new ChatMessage("disconnect.genericReason", new Object[] { "Internal Exception: " + throwable}))); + } + + protected void a(ChannelHandlerContext channelhandlercontext, Packet packet) { + if (this.k.isOpen()) { + if (packet.a()) { + packet.handle(this.m); + } else { + this.i.add(packet); } - - return false; } } - private Packet a(boolean flag) { - Packet packet = null; - List list = flag ? this.lowPriorityQueue : this.highPriorityQueue; - Object object = this.h; - - synchronized (this.h) { - while (!list.isEmpty() && packet == null) { - packet = (Packet) list.remove(0); - this.z -= packet.a() + 1; - if (this.a(packet, flag)) { - packet = null; - } - } - - return packet; - } + public void a(PacketListener packetlistener) { + Validate.notNull(packetlistener, "packetListener", new Object[0]); + g.debug("Set listener of {} to {}", new Object[] { this, packetlistener}); + this.m = packetlistener; } - private boolean a(Packet packet, boolean flag) { - if (!packet.e()) { - return false; + public void handle(Packet packet, GenericFutureListener... agenericfuturelistener) { + if (this.k != null && this.k.isOpen()) { + this.h(); + this.b(packet, agenericfuturelistener); } else { - List list = flag ? this.lowPriorityQueue : this.highPriorityQueue; - Iterator iterator = list.iterator(); - - Packet packet1; - - do { - if (!iterator.hasNext()) { - return false; - } - - packet1 = (Packet) iterator.next(); - } while (packet1.n() != packet.n()); - - return packet.a(packet1); + this.j.add(new QueuedPacket(packet, agenericfuturelistener)); } } - public void a() { - if (this.v != null) { - this.v.interrupt(); - } + private void b(Packet packet, GenericFutureListener[] agenericfuturelistener) { + EnumProtocol enumprotocol = EnumProtocol.a(packet); + EnumProtocol enumprotocol1 = (EnumProtocol) this.k.attr(c).get(); - if (this.u != null) { - this.u.interrupt(); + if (enumprotocol1 != enumprotocol) { + g.debug("Disabled auto read"); + this.k.config().setAutoRead(false); } - } - - private boolean i() { - boolean flag = false; - - try { - Packet packet = Packet.a(this.i, this.input, this.connection.a(), this.socket); - - if (packet != null) { - if (packet instanceof Packet252KeyResponse && !this.f) { - if (this.connection.a()) { - this.A = ((Packet252KeyResponse) packet).a(this.B); - } - this.j(); - } - - int[] aint = c; - int i = packet.n(); - - aint[i] += packet.a() + 1; - if (!this.t) { - if (packet.a_() && this.connection.b()) { - this.y = 0; - packet.handle(this.connection); - } else { - this.inboundQueue.add(packet); - } - } - - flag = true; - } else { - this.a("disconnect.endOfStream", new Object[0]); + if (this.k.eventLoop().inEventLoop()) { + if (enumprotocol != enumprotocol1) { + this.a(enumprotocol); } - return flag; - } catch (Exception exception) { - if (!this.o) { - this.a(exception); - } - - return false; + this.k.writeAndFlush(packet).addListeners(agenericfuturelistener).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); + } else { + this.k.eventLoop().execute(new QueuedProtocolSwitch(this, enumprotocol, enumprotocol1, packet, agenericfuturelistener)); } } - private void a(Exception exception) { - // exception.printStackTrace(); // CraftBukkit - Remove console spam - this.a("disconnect.genericReason", new Object[] { "Internal exception: " + exception.toString()}); - } + private void h() { + if (this.k != null && this.k.isOpen()) { + while (!this.j.isEmpty()) { + QueuedPacket queuedpacket = (QueuedPacket) this.j.poll(); - public void a(String s, Object... aobject) { - if (this.n) { - this.o = true; - this.w = s; - this.x = aobject; - this.n = false; - (new NetworkMasterThread(this)).start(); - - try { - this.input.close(); - } catch (Throwable throwable) { - ; + this.b(QueuedPacket.a(queuedpacket), QueuedPacket.b(queuedpacket)); } - - try { - this.output.close(); - } catch (Throwable throwable1) { - ; - } - - try { - this.socket.close(); - } catch (Throwable throwable2) { - ; - } - - this.input = null; - this.output = null; - this.socket = null; } } - public void b() { - if (this.z > 2097152) { - this.a("disconnect.overflow", new Object[0]); - } + public void a() { + this.h(); + EnumProtocol enumprotocol = (EnumProtocol) this.k.attr(c).get(); - if (this.inboundQueue.isEmpty()) { - if (this.y++ == 1200) { - this.a("disconnect.timeout", new Object[0]); + if (this.n != enumprotocol) { + if (this.n != null) { + this.m.a(this.n, enumprotocol); } - } else { - this.y = 0; + + this.n = enumprotocol; } - int i = 1000; + if (this.m != null) { + for (int i = 1000; !this.i.isEmpty() && i >= 0; --i) { + Packet packet = (Packet) this.i.poll(); - while (!this.inboundQueue.isEmpty() && i-- >= 0) { - Packet packet = (Packet) this.inboundQueue.poll(); + // CraftBukkit start + if (!this.d() || !this.k.config().isAutoRead()) { // Should be isConnected + continue; + } + // CraftBukkit end - // CraftBukkit start - if (this.connection instanceof PendingConnection ? ((PendingConnection) this.connection).b : ((PlayerConnection) this.connection).disconnected) { - continue; + packet.handle(this.m); } - // CraftBukkit end - if (packet != null && !this.connection.c()) { - packet.handle(this.connection); - } + this.m.a(); } - this.a(); - if (this.o && this.inboundQueue.isEmpty()) { - this.connection.a(this.w, this.x); - } + this.k.flush(); } public SocketAddress getSocketAddress() { - return this.k; + return this.l; } - public void d() { - if (!this.t) { - this.a(); - this.t = true; - this.v.interrupt(); - (new NetworkMonitorThread(this)).start(); + public void a(IChatBaseComponent ichatbasecomponent) { + if (this.k.isOpen()) { + this.k.close(); + this.o = ichatbasecomponent; } } - private void j() throws IOException { // CraftBukkit - throws IOException - this.f = true; - InputStream inputstream = this.socket.getInputStream(); - - this.input = new DataInputStream(MinecraftEncryption.a(this.A, inputstream)); - } - - private void k() throws IOException { // CraftBukkit - throws IOException - this.output.flush(); - this.g = true; - BufferedOutputStream bufferedoutputstream = new BufferedOutputStream(MinecraftEncryption.a(this.A, this.socket.getOutputStream()), 5120); - - this.output = new DataOutputStream(bufferedoutputstream); - } - - public int e() { - return this.lowPriorityQueue.size(); - } - - public Socket getSocket() { - return this.socket; - } - - static boolean a(NetworkManager networkmanager) { - return networkmanager.n; - } - - static boolean b(NetworkManager networkmanager) { - return networkmanager.t; + public boolean c() { + return this.k instanceof LocalChannel || this.k instanceof LocalServerChannel; } - static boolean c(NetworkManager networkmanager) { - return networkmanager.i(); + public void a(SecretKey secretkey) { + this.k.pipeline().addBefore("splitter", "decrypt", new PacketDecrypter(MinecraftEncryption.a(2, secretkey))); + this.k.pipeline().addBefore("prepender", "encrypt", new PacketEncrypter(MinecraftEncryption.a(1, secretkey))); } - static boolean d(NetworkManager networkmanager) { - return networkmanager.h(); + public boolean d() { + return this.k != null && this.k.isOpen(); } - static DataOutputStream e(NetworkManager networkmanager) { - return networkmanager.output; + public PacketListener getPacketListener() { + return this.m; } - static boolean f(NetworkManager networkmanager) { - return networkmanager.o; + public IChatBaseComponent f() { + return this.o; } - static void a(NetworkManager networkmanager, Exception exception) { - networkmanager.a(exception); + public void g() { + this.k.config().setAutoRead(false); } - static Thread g(NetworkManager networkmanager) { - return networkmanager.v; + protected void channelRead0(ChannelHandlerContext channelhandlercontext, Object object) { + this.a(channelhandlercontext, (Packet) object); } - static Thread h(NetworkManager networkmanager) { - return networkmanager.u; + static Channel a(NetworkManager networkmanager) { + return networkmanager.k; } } |