2011-03-27 22:12:39 +02:00
|
|
|
package net.minecraft.server;
|
|
|
|
|
|
|
|
import java.net.SocketAddress;
|
2013-07-09 01:43:37 +02:00
|
|
|
import java.util.Queue;
|
2012-07-29 09:33:13 +02:00
|
|
|
import javax.crypto.SecretKey;
|
2011-06-07 07:29:55 +02:00
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
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;
|
2014-04-16 04:45:03 +02:00
|
|
|
import net.minecraft.util.io.netty.handler.timeout.TimeoutException;
|
2013-11-04 14:07:38 +01:00
|
|
|
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 {
|
|
|
|
|
2014-03-21 05:26:30 +01:00
|
|
|
private static final Logger i = LogManager.getLogger();
|
2013-11-04 14:07:38 +01:00
|
|
|
public static final Marker a = MarkerManager.getMarker("NETWORK");
|
|
|
|
public static final Marker b = MarkerManager.getMarker("NETWORK_PACKETS", a);
|
2014-03-21 05:26:30 +01:00
|
|
|
public static final Marker c = MarkerManager.getMarker("NETWORK_STAT", a);
|
|
|
|
public static final AttributeKey d = new AttributeKey("protocol");
|
|
|
|
public static final AttributeKey e = new AttributeKey("receivable_packets");
|
|
|
|
public static final AttributeKey f = new AttributeKey("sendable_packets");
|
|
|
|
public static final NioEventLoopGroup g = new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Client IO #%d").setDaemon(true).build());
|
|
|
|
public static final NetworkStatistics h = new NetworkStatistics();
|
|
|
|
private final boolean j;
|
|
|
|
private final Queue k = Queues.newConcurrentLinkedQueue();
|
|
|
|
private final Queue l = Queues.newConcurrentLinkedQueue();
|
|
|
|
private Channel m;
|
|
|
|
private SocketAddress n;
|
|
|
|
private PacketListener o;
|
|
|
|
private EnumProtocol p;
|
|
|
|
private IChatBaseComponent q;
|
2014-04-11 03:04:38 +02:00
|
|
|
private boolean r;
|
2013-11-04 14:07:38 +01:00
|
|
|
|
|
|
|
public NetworkManager(boolean flag) {
|
2014-03-21 05:26:30 +01:00
|
|
|
this.j = flag;
|
2013-11-04 14:07:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void channelActive(ChannelHandlerContext channelhandlercontext) throws Exception { // CraftBukkit - throws Exception
|
|
|
|
super.channelActive(channelhandlercontext);
|
2014-03-21 05:26:30 +01:00
|
|
|
this.m = channelhandlercontext.channel();
|
|
|
|
this.n = this.m.remoteAddress();
|
2013-11-04 14:07:38 +01:00
|
|
|
this.a(EnumProtocol.HANDSHAKING);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void a(EnumProtocol enumprotocol) {
|
2014-03-21 05:26:30 +01:00
|
|
|
this.p = (EnumProtocol) this.m.attr(d).getAndSet(enumprotocol);
|
|
|
|
this.m.attr(e).set(enumprotocol.a(this.j));
|
|
|
|
this.m.attr(f).set(enumprotocol.b(this.j));
|
|
|
|
this.m.config().setAutoRead(true);
|
|
|
|
i.debug("Enabled auto read");
|
2013-11-04 14:07:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void channelInactive(ChannelHandlerContext channelhandlercontext) {
|
2014-03-21 05:26:30 +01:00
|
|
|
this.close(new ChatMessage("disconnect.endOfStream", new Object[0]));
|
2013-11-04 14:07:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) {
|
2014-04-16 04:45:03 +02:00
|
|
|
ChatMessage chatmessage;
|
|
|
|
|
|
|
|
if (throwable instanceof TimeoutException) {
|
|
|
|
chatmessage = new ChatMessage("disconnect.timeout", new Object[0]);
|
|
|
|
} else {
|
|
|
|
chatmessage = new ChatMessage("disconnect.genericReason", new Object[] { "Internal Exception: " + throwable});
|
|
|
|
}
|
|
|
|
|
|
|
|
this.close(chatmessage);
|
2013-11-04 14:07:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void a(ChannelHandlerContext channelhandlercontext, Packet packet) {
|
2014-03-21 05:26:30 +01:00
|
|
|
if (this.m.isOpen()) {
|
2013-11-04 14:07:38 +01:00
|
|
|
if (packet.a()) {
|
2014-03-21 05:26:30 +01:00
|
|
|
packet.handle(this.o);
|
2013-11-04 14:07:38 +01:00
|
|
|
} else {
|
2014-03-21 05:26:30 +01:00
|
|
|
this.k.add(packet);
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
2011-05-28 22:50:08 +02:00
|
|
|
}
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public void a(PacketListener packetlistener) {
|
|
|
|
Validate.notNull(packetlistener, "packetListener", new Object[0]);
|
2014-03-21 05:26:30 +01:00
|
|
|
i.debug("Set listener of {} to {}", new Object[] { this, packetlistener});
|
|
|
|
this.o = packetlistener;
|
2012-07-29 09:33:13 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public void handle(Packet packet, GenericFutureListener... agenericfuturelistener) {
|
2014-03-21 05:26:30 +01:00
|
|
|
if (this.m != null && this.m.isOpen()) {
|
2014-04-11 03:04:38 +02:00
|
|
|
this.i();
|
2013-11-04 14:07:38 +01:00
|
|
|
this.b(packet, agenericfuturelistener);
|
2012-07-29 09:33:13 +02:00
|
|
|
} else {
|
2014-03-21 05:26:30 +01:00
|
|
|
this.l.add(new QueuedPacket(packet, agenericfuturelistener));
|
2012-07-29 09:33:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
private void b(Packet packet, GenericFutureListener[] agenericfuturelistener) {
|
|
|
|
EnumProtocol enumprotocol = EnumProtocol.a(packet);
|
2014-03-21 05:26:30 +01:00
|
|
|
EnumProtocol enumprotocol1 = (EnumProtocol) this.m.attr(d).get();
|
2012-07-29 09:33:13 +02:00
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
if (enumprotocol1 != enumprotocol) {
|
2014-03-21 05:26:30 +01:00
|
|
|
i.debug("Disabled auto read");
|
|
|
|
this.m.config().setAutoRead(false);
|
2012-07-29 09:33:13 +02:00
|
|
|
}
|
|
|
|
|
2014-03-21 05:26:30 +01:00
|
|
|
if (this.m.eventLoop().inEventLoop()) {
|
2013-11-04 14:07:38 +01:00
|
|
|
if (enumprotocol != enumprotocol1) {
|
|
|
|
this.a(enumprotocol);
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
2011-05-28 22:50:08 +02:00
|
|
|
|
2014-03-21 05:26:30 +01:00
|
|
|
this.m.writeAndFlush(packet).addListeners(agenericfuturelistener).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
2013-11-04 14:07:38 +01:00
|
|
|
} else {
|
2014-03-21 05:26:30 +01:00
|
|
|
this.m.eventLoop().execute(new QueuedProtocolSwitch(this, enumprotocol, enumprotocol1, packet, agenericfuturelistener));
|
2011-05-28 22:50:08 +02:00
|
|
|
}
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2014-04-11 03:04:38 +02:00
|
|
|
private void i() {
|
2014-03-21 05:26:30 +01:00
|
|
|
if (this.m != null && this.m.isOpen()) {
|
|
|
|
while (!this.l.isEmpty()) {
|
|
|
|
QueuedPacket queuedpacket = (QueuedPacket) this.l.poll();
|
2011-03-27 22:12:39 +02:00
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
this.b(QueuedPacket.a(queuedpacket), QueuedPacket.b(queuedpacket));
|
2012-11-06 13:05:28 +01:00
|
|
|
}
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public void a() {
|
2014-04-11 03:04:38 +02:00
|
|
|
this.i();
|
2014-03-21 05:26:30 +01:00
|
|
|
EnumProtocol enumprotocol = (EnumProtocol) this.m.attr(d).get();
|
2011-03-27 22:12:39 +02:00
|
|
|
|
2014-03-21 05:26:30 +01:00
|
|
|
if (this.p != enumprotocol) {
|
|
|
|
if (this.p != null) {
|
|
|
|
this.o.a(this.p, enumprotocol);
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
2013-11-04 14:07:38 +01:00
|
|
|
|
2014-03-21 05:26:30 +01:00
|
|
|
this.p = enumprotocol;
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2014-03-21 05:26:30 +01:00
|
|
|
if (this.o != null) {
|
|
|
|
for (int i = 1000; !this.k.isEmpty() && i >= 0; --i) {
|
|
|
|
Packet packet = (Packet) this.k.poll();
|
2011-03-27 22:12:39 +02:00
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
// CraftBukkit start
|
2014-03-21 05:26:30 +01:00
|
|
|
if (!this.isConnected() || !this.m.config().isAutoRead()) {
|
2013-11-04 14:07:38 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// CraftBukkit end
|
2014-03-21 05:26:30 +01:00
|
|
|
packet.handle(this.o);
|
2012-09-10 06:19:28 +02:00
|
|
|
}
|
|
|
|
|
2014-03-21 05:26:30 +01:00
|
|
|
this.o.a();
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2014-03-21 05:26:30 +01:00
|
|
|
this.m.flush();
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2011-04-20 19:05:14 +02:00
|
|
|
public SocketAddress getSocketAddress() {
|
2014-03-21 05:26:30 +01:00
|
|
|
return this.n;
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2014-03-21 05:26:30 +01:00
|
|
|
public void close(IChatBaseComponent ichatbasecomponent) {
|
|
|
|
if (this.m.isOpen()) {
|
|
|
|
this.m.close();
|
|
|
|
this.q = ichatbasecomponent;
|
2012-01-12 23:10:13 +01:00
|
|
|
}
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public boolean c() {
|
2014-03-21 05:26:30 +01:00
|
|
|
return this.m instanceof LocalChannel || this.m instanceof LocalServerChannel;
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public void a(SecretKey secretkey) {
|
2014-03-21 05:26:30 +01:00
|
|
|
this.m.pipeline().addBefore("splitter", "decrypt", new PacketDecrypter(MinecraftEncryption.a(2, secretkey)));
|
|
|
|
this.m.pipeline().addBefore("prepender", "encrypt", new PacketEncrypter(MinecraftEncryption.a(1, secretkey)));
|
2014-04-11 03:04:38 +02:00
|
|
|
this.r = true;
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2014-03-21 05:26:30 +01:00
|
|
|
public boolean isConnected() {
|
|
|
|
return this.m != null && this.m.isOpen();
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public PacketListener getPacketListener() {
|
2014-03-21 05:26:30 +01:00
|
|
|
return this.o;
|
2011-05-26 14:48:22 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public IChatBaseComponent f() {
|
2014-03-21 05:26:30 +01:00
|
|
|
return this.q;
|
2011-05-26 14:48:22 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public void g() {
|
2014-03-21 05:26:30 +01:00
|
|
|
this.m.config().setAutoRead(false);
|
2011-05-26 14:48:22 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
protected void channelRead0(ChannelHandlerContext channelhandlercontext, Object object) {
|
|
|
|
this.a(channelhandlercontext, (Packet) object);
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
static Channel a(NetworkManager networkmanager) {
|
2014-03-21 05:26:30 +01:00
|
|
|
return networkmanager.m;
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
}
|