summaryrefslogtreecommitdiffstats
path: root/src/main/java/net/minecraft/server/NetworkManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/net/minecraft/server/NetworkManager.java')
-rw-r--r--src/main/java/net/minecraft/server/NetworkManager.java449
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;
}
}