Paper/src/main/java/net/minecraft/server/NetworkManager.java

378 Zeilen
11 KiB
Java

2011-03-27 22:12:39 +02:00
package net.minecraft.server;
2011-04-20 22:47:26 +02:00
import java.io.BufferedOutputStream;
2011-03-27 22:12:39 +02:00
import java.io.DataInputStream;
2013-07-01 13:03:00 +02:00
import java.io.DataOutput;
2011-03-27 22:12:39 +02:00
import java.io.DataOutputStream;
2012-11-06 13:05:28 +01:00
import java.io.InputStream;
2011-03-27 22:12:39 +02:00
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
2012-07-29 09:33:13 +02:00
import java.security.PrivateKey;
2011-03-27 22:12:39 +02:00
import java.util.ArrayList;
import java.util.Collections;
2012-07-29 09:33:13 +02:00
import java.util.Iterator;
2011-03-27 22:12:39 +02:00
import java.util.List;
2013-07-09 01:43:37 +02:00
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
2012-07-29 09:33:13 +02:00
import java.util.concurrent.atomic.AtomicInteger;
import javax.crypto.SecretKey;
2011-06-07 07:29:55 +02:00
2012-07-29 09:33:13 +02:00
import java.io.IOException; // CraftBukkit
2011-03-27 22:12:39 +02:00
2012-07-29 09:33:13 +02:00
public class NetworkManager implements INetworkManager {
public static AtomicInteger a = new AtomicInteger();
public static AtomicInteger b = new AtomicInteger();
2013-03-13 23:33:27 +01:00
private final Object h = new Object();
private final IConsoleLogManager i;
2011-05-14 16:29:42 +02:00
public Socket socket; // CraftBukkit - private -> public
2013-03-13 23:33:27 +01:00
private final SocketAddress k;
2012-07-29 09:33:13 +02:00
private volatile DataInputStream input;
private volatile DataOutputStream output;
2013-03-13 23:33:27 +01:00
private volatile boolean n = true;
2013-07-01 13:03:00 +02:00
private volatile boolean o;
2013-07-09 01:43:37 +02:00
private Queue inboundQueue = new ConcurrentLinkedQueue();
private List highPriorityQueue = Collections.synchronizedList(new ArrayList());
private List lowPriorityQueue = Collections.synchronizedList(new ArrayList());
2012-12-20 05:03:52 +01:00
private Connection connection;
2013-07-01 13:03:00 +02:00
private boolean t;
2012-07-29 09:33:13 +02:00
private Thread u;
2013-03-13 23:33:27 +01:00
private Thread v;
private String w = "";
private Object[] x;
2013-07-01 13:03:00 +02:00
private int y;
private int z;
2012-07-29 09:33:13 +02:00
public static int[] c = new int[256];
2011-05-26 14:48:22 +02:00
public static int[] d = new int[256];
2013-07-01 13:03:00 +02:00
public int e;
boolean f;
boolean g;
private SecretKey A;
private PrivateKey B;
private int lowPriorityQueueDelay = 50;
2011-03-27 22:12:39 +02:00
2013-03-13 23:33:27 +01:00
public NetworkManager(IConsoleLogManager iconsolelogmanager, Socket socket, String s, Connection connection, PrivateKey privatekey) throws IOException { // CraftBukkit - throws IOException
this.B = privatekey;
this.socket = socket;
2013-03-13 23:33:27 +01:00
this.i = iconsolelogmanager;
this.k = socket.getRemoteSocketAddress();
2012-12-20 05:03:52 +01:00
this.connection = connection;
2011-03-27 22:12:39 +02:00
2011-06-07 07:29:55 +02:00
try {
socket.setSoTimeout(30000);
2012-07-29 09:33:13 +02:00
socket.setTrafficClass(24);
} catch (SocketException socketexception) {
2011-03-31 22:40:00 +02:00
System.err.println(socketexception.getMessage());
}
2011-03-27 22:12:39 +02:00
this.input = new DataInputStream(socket.getInputStream());
this.output = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream(), 5120));
2013-03-13 23:33:27 +01:00
this.v = new NetworkReaderThread(this, s + " read thread");
this.u = new NetworkWriterThread(this, s + " write thread");
this.v.start();
2012-07-29 09:33:13 +02:00
this.u.start();
2011-03-27 22:12:39 +02:00
}
2012-12-20 05:03:52 +01:00
public void a(Connection connection) {
this.connection = connection;
2011-03-27 22:12:39 +02:00
}
public void queue(Packet packet) {
2013-03-13 23:33:27 +01:00
if (!this.t) {
2012-07-29 09:33:13 +02:00
Object object = this.h;
2011-03-27 22:12:39 +02:00
2012-07-29 09:33:13 +02:00
synchronized (this.h) {
2013-03-13 23:33:27 +01:00
this.z += packet.a() + 1;
2012-11-06 13:05:28 +01:00
this.highPriorityQueue.add(packet);
2011-03-27 22:12:39 +02:00
}
}
}
2012-07-29 09:33:13 +02:00
private boolean h() {
2011-05-26 16:20:11 +02:00
boolean flag = false;
2011-03-27 22:12:39 +02:00
try {
Packet packet;
2011-05-26 14:48:22 +02:00
int i;
int[] aint;
2013-07-01 13:03:00 +02:00
if (this.e == 0 || !this.highPriorityQueue.isEmpty() && MinecraftServer.aq() - ((Packet) this.highPriorityQueue.get(0)).timestamp >= (long) this.e) {
2012-07-29 09:33:13 +02:00
packet = this.a(false);
if (packet != null) {
2013-07-01 13:03:00 +02:00
Packet.a(packet, (DataOutput) this.output);
2012-07-29 09:33:13 +02:00
if (packet instanceof Packet252KeyResponse && !this.g) {
2012-12-20 05:03:52 +01:00
if (!this.connection.a()) {
2013-03-13 23:33:27 +01:00
this.A = ((Packet252KeyResponse) packet).d();
2012-07-29 09:33:13 +02:00
}
this.k();
}
aint = d;
2013-03-13 23:33:27 +01:00
i = packet.n();
2012-07-29 09:33:13 +02:00
aint[i] += packet.a() + 1;
flag = true;
}
}
2012-07-29 09:33:13 +02:00
// 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)) {
2012-07-29 09:33:13 +02:00
packet = this.a(true);
if (packet != null) {
2013-07-01 13:03:00 +02:00
Packet.a(packet, (DataOutput) this.output);
2012-07-29 09:33:13 +02:00
aint = d;
2013-03-13 23:33:27 +01:00
i = packet.n();
2012-07-29 09:33:13 +02:00
aint[i] += packet.a() + 1;
this.lowPriorityQueueDelay = 0;
flag = true;
2011-03-27 22:12:39 +02:00
}
}
2011-05-28 22:50:08 +02:00
return flag;
2011-03-27 22:12:39 +02:00
} catch (Exception exception) {
2013-03-13 23:33:27 +01:00
if (!this.o) {
2011-03-27 22:12:39 +02:00
this.a(exception);
}
2011-05-26 16:20:11 +02:00
2011-05-28 22:50:08 +02:00
return false;
}
2011-03-27 22:12:39 +02:00
}
2012-07-29 09:33:13 +02:00
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);
2013-03-13 23:33:27 +01:00
this.z -= packet.a() + 1;
2012-07-29 09:33:13 +02:00
if (this.a(packet, flag)) {
packet = null;
}
}
return packet;
}
}
private boolean a(Packet packet, boolean flag) {
if (!packet.e()) {
return false;
} else {
List list = flag ? this.lowPriorityQueue : this.highPriorityQueue;
Iterator iterator = list.iterator();
Packet packet1;
do {
if (!iterator.hasNext()) {
return false;
}
packet1 = (Packet) iterator.next();
2013-03-13 23:33:27 +01:00
} while (packet1.n() != packet.n());
2012-07-29 09:33:13 +02:00
return packet.a(packet1);
}
}
2011-05-26 14:48:22 +02:00
public void a() {
2013-03-13 23:33:27 +01:00
if (this.v != null) {
this.v.interrupt();
2012-07-29 09:33:13 +02:00
}
2013-03-13 23:33:27 +01:00
if (this.u != null) {
this.u.interrupt();
2012-07-29 09:33:13 +02:00
}
2011-05-26 14:48:22 +02:00
}
2012-07-29 09:33:13 +02:00
private boolean i() {
2011-05-26 16:20:11 +02:00
boolean flag = false;
2011-03-27 22:12:39 +02:00
try {
2013-03-13 23:33:27 +01:00
Packet packet = Packet.a(this.i, this.input, this.connection.a(), this.socket);
2011-03-27 22:12:39 +02:00
if (packet != null) {
2012-07-29 09:33:13 +02:00
if (packet instanceof Packet252KeyResponse && !this.f) {
2012-12-20 05:03:52 +01:00
if (this.connection.a()) {
2013-03-13 23:33:27 +01:00
this.A = ((Packet252KeyResponse) packet).a(this.B);
2012-07-29 09:33:13 +02:00
}
this.j();
}
int[] aint = c;
2013-03-13 23:33:27 +01:00
int i = packet.n();
2011-05-26 14:48:22 +02:00
2011-05-28 22:50:08 +02:00
aint[i] += packet.a() + 1;
2013-03-13 23:33:27 +01:00
if (!this.t) {
2012-12-20 05:03:52 +01:00
if (packet.a_() && this.connection.b()) {
2013-03-13 23:33:27 +01:00
this.y = 0;
2012-12-20 05:03:52 +01:00
packet.handle(this.connection);
2012-07-29 09:33:13 +02:00
} else {
this.inboundQueue.add(packet);
}
2012-03-01 11:49:23 +01:00
}
2011-05-26 16:20:11 +02:00
flag = true;
2011-03-27 22:12:39 +02:00
} else {
this.a("disconnect.endOfStream", new Object[0]);
}
2011-05-28 22:50:08 +02:00
return flag;
2011-03-27 22:12:39 +02:00
} catch (Exception exception) {
2013-03-13 23:33:27 +01:00
if (!this.o) {
2011-03-27 22:12:39 +02:00
this.a(exception);
}
2011-05-26 16:20:11 +02:00
2011-05-28 22:50:08 +02:00
return false;
}
2011-03-27 22:12:39 +02:00
}
private void a(Exception exception) {
// exception.printStackTrace(); // CraftBukkit - Remove console spam
2011-03-27 22:12:39 +02:00
this.a("disconnect.genericReason", new Object[] { "Internal exception: " + exception.toString()});
}
public void a(String s, Object... aobject) {
2013-03-13 23:33:27 +01:00
if (this.n) {
this.o = true;
this.w = s;
this.x = aobject;
this.n = false;
2011-03-27 22:12:39 +02:00
(new NetworkMasterThread(this)).start();
try {
this.input.close();
2012-11-06 13:05:28 +01:00
} catch (Throwable throwable) {
;
}
try {
this.output.close();
2012-11-06 13:05:28 +01:00
} catch (Throwable throwable1) {
;
}
try {
this.socket.close();
2012-11-06 13:05:28 +01:00
} catch (Throwable throwable2) {
2011-03-27 22:12:39 +02:00
;
}
2012-11-06 13:05:28 +01:00
this.input = null;
this.output = null;
this.socket = null;
2011-03-27 22:12:39 +02:00
}
}
2011-05-26 14:48:22 +02:00
public void b() {
2013-03-13 23:33:27 +01:00
if (this.z > 2097152) {
2011-03-27 22:12:39 +02:00
this.a("disconnect.overflow", new Object[0]);
}
2012-07-29 09:33:13 +02:00
if (this.inboundQueue.isEmpty()) {
2013-03-13 23:33:27 +01:00
if (this.y++ == 1200) {
2011-03-27 22:12:39 +02:00
this.a("disconnect.timeout", new Object[0]);
}
} else {
2013-03-13 23:33:27 +01:00
this.y = 0;
2011-03-27 22:12:39 +02:00
}
2011-09-15 02:23:52 +02:00
int i = 1000;
2011-03-27 22:12:39 +02:00
2012-07-29 09:33:13 +02:00
while (!this.inboundQueue.isEmpty() && i-- >= 0) {
2013-07-09 01:43:37 +02:00
Packet packet = (Packet) this.inboundQueue.poll();
2011-03-27 22:12:39 +02:00
2012-09-10 06:19:28 +02:00
// CraftBukkit start
2013-03-13 23:33:27 +01:00
if (this.connection instanceof PendingConnection ? ((PendingConnection) this.connection).b : ((PlayerConnection) this.connection).disconnected) {
2012-09-10 06:19:28 +02:00
continue;
}
// CraftBukkit end
2013-07-09 01:43:37 +02:00
if (packet != null && !this.connection.c()) {
packet.handle(this.connection);
}
2011-03-27 22:12:39 +02:00
}
2011-05-28 22:50:08 +02:00
this.a();
2013-03-13 23:33:27 +01:00
if (this.o && this.inboundQueue.isEmpty()) {
this.connection.a(this.w, this.x);
2011-03-27 22:12:39 +02:00
}
}
public SocketAddress getSocketAddress() {
2013-03-13 23:33:27 +01:00
return this.k;
2011-03-27 22:12:39 +02:00
}
2011-05-26 14:48:22 +02:00
public void d() {
2013-03-13 23:33:27 +01:00
if (!this.t) {
2012-01-12 23:10:13 +01:00
this.a();
2013-03-13 23:33:27 +01:00
this.t = true;
this.v.interrupt();
2012-01-12 23:10:13 +01:00
(new NetworkMonitorThread(this)).start();
}
2011-03-27 22:12:39 +02:00
}
2012-07-29 09:33:13 +02:00
private void j() throws IOException { // CraftBukkit - throws IOException
this.f = true;
2012-11-06 13:05:28 +01:00
InputStream inputstream = this.socket.getInputStream();
2013-03-13 23:33:27 +01:00
this.input = new DataInputStream(MinecraftEncryption.a(this.A, inputstream));
2012-07-29 09:33:13 +02:00
}
private void k() throws IOException { // CraftBukkit - throws IOException
this.output.flush();
this.g = true;
2013-03-13 23:33:27 +01:00
BufferedOutputStream bufferedoutputstream = new BufferedOutputStream(MinecraftEncryption.a(this.A, this.socket.getOutputStream()), 5120);
2012-11-06 13:05:28 +01:00
this.output = new DataOutputStream(bufferedoutputstream);
2012-07-29 09:33:13 +02:00
}
2011-05-26 14:48:22 +02:00
public int e() {
return this.lowPriorityQueue.size();
2011-03-27 22:12:39 +02:00
}
public Socket getSocket() {
2011-09-15 02:23:52 +02:00
return this.socket;
}
2011-03-27 22:12:39 +02:00
static boolean a(NetworkManager networkmanager) {
2013-03-13 23:33:27 +01:00
return networkmanager.n;
2011-03-27 22:12:39 +02:00
}
static boolean b(NetworkManager networkmanager) {
2013-03-13 23:33:27 +01:00
return networkmanager.t;
2011-03-27 22:12:39 +02:00
}
2011-05-26 16:20:11 +02:00
static boolean c(NetworkManager networkmanager) {
2012-07-29 09:33:13 +02:00
return networkmanager.i();
2011-03-27 22:12:39 +02:00
}
2011-05-26 16:20:11 +02:00
static boolean d(NetworkManager networkmanager) {
2012-07-29 09:33:13 +02:00
return networkmanager.h();
2011-03-27 22:12:39 +02:00
}
2011-05-28 22:50:08 +02:00
static DataOutputStream e(NetworkManager networkmanager) {
return networkmanager.output;
2011-05-26 14:48:22 +02:00
}
2011-05-28 22:50:08 +02:00
static boolean f(NetworkManager networkmanager) {
2013-03-13 23:33:27 +01:00
return networkmanager.o;
2011-05-26 14:48:22 +02:00
}
2011-05-28 22:50:08 +02:00
static void a(NetworkManager networkmanager, Exception exception) {
networkmanager.a(exception);
2011-05-26 14:48:22 +02:00
}
static Thread g(NetworkManager networkmanager) {
2013-03-13 23:33:27 +01:00
return networkmanager.v;
2011-03-27 22:12:39 +02:00
}
2011-05-26 14:48:22 +02:00
static Thread h(NetworkManager networkmanager) {
2013-03-13 23:33:27 +01:00
return networkmanager.u;
2011-03-27 22:12:39 +02:00
}
}