Paper/src/main/java/net/minecraft/server/NetworkManager.java
2014-04-17 13:44:03 -05:00

211 Zeilen
7.4 KiB
Java

package net.minecraft.server;
import java.net.SocketAddress;
import java.util.Queue;
import javax.crypto.SecretKey;
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.handler.timeout.TimeoutException;
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 i = LogManager.getLogger();
public static final Marker a = MarkerManager.getMarker("NETWORK");
public static final Marker b = MarkerManager.getMarker("NETWORK_PACKETS", a);
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;
private boolean r;
public NetworkManager(boolean flag) {
this.j = flag;
}
public void channelActive(ChannelHandlerContext channelhandlercontext) throws Exception { // CraftBukkit - throws Exception
super.channelActive(channelhandlercontext);
this.m = channelhandlercontext.channel();
this.n = this.m.remoteAddress();
this.a(EnumProtocol.HANDSHAKING);
}
public void a(EnumProtocol enumprotocol) {
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");
}
public void channelInactive(ChannelHandlerContext channelhandlercontext) {
this.close(new ChatMessage("disconnect.endOfStream", new Object[0]));
}
public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) {
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);
}
protected void a(ChannelHandlerContext channelhandlercontext, Packet packet) {
if (this.m.isOpen()) {
if (packet.a()) {
packet.handle(this.o);
} else {
this.k.add(packet);
}
}
}
public void a(PacketListener packetlistener) {
Validate.notNull(packetlistener, "packetListener", new Object[0]);
i.debug("Set listener of {} to {}", new Object[] { this, packetlistener});
this.o = packetlistener;
}
public void handle(Packet packet, GenericFutureListener... agenericfuturelistener) {
if (this.m != null && this.m.isOpen()) {
this.i();
this.b(packet, agenericfuturelistener);
} else {
this.l.add(new QueuedPacket(packet, agenericfuturelistener));
}
}
private void b(Packet packet, GenericFutureListener[] agenericfuturelistener) {
EnumProtocol enumprotocol = EnumProtocol.a(packet);
EnumProtocol enumprotocol1 = (EnumProtocol) this.m.attr(d).get();
if (enumprotocol1 != enumprotocol) {
i.debug("Disabled auto read");
this.m.config().setAutoRead(false);
}
if (this.m.eventLoop().inEventLoop()) {
if (enumprotocol != enumprotocol1) {
this.a(enumprotocol);
}
this.m.writeAndFlush(packet).addListeners(agenericfuturelistener).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
} else {
this.m.eventLoop().execute(new QueuedProtocolSwitch(this, enumprotocol, enumprotocol1, packet, agenericfuturelistener));
}
}
private void i() {
if (this.m != null && this.m.isOpen()) {
while (!this.l.isEmpty()) {
QueuedPacket queuedpacket = (QueuedPacket) this.l.poll();
this.b(QueuedPacket.a(queuedpacket), QueuedPacket.b(queuedpacket));
}
}
}
public void a() {
this.i();
EnumProtocol enumprotocol = (EnumProtocol) this.m.attr(d).get();
if (this.p != enumprotocol) {
if (this.p != null) {
this.o.a(this.p, enumprotocol);
}
this.p = enumprotocol;
}
if (this.o != null) {
for (int i = 1000; !this.k.isEmpty() && i >= 0; --i) {
Packet packet = (Packet) this.k.poll();
// CraftBukkit start
if (!this.isConnected() || !this.m.config().isAutoRead()) {
continue;
}
// CraftBukkit end
packet.handle(this.o);
}
this.o.a();
}
this.m.flush();
}
public SocketAddress getSocketAddress() {
return this.n;
}
public void close(IChatBaseComponent ichatbasecomponent) {
if (this.m.isOpen()) {
this.m.close();
this.q = ichatbasecomponent;
}
}
public boolean c() {
return this.m instanceof LocalChannel || this.m instanceof LocalServerChannel;
}
public void a(SecretKey secretkey) {
this.m.pipeline().addBefore("splitter", "decrypt", new PacketDecrypter(MinecraftEncryption.a(2, secretkey)));
this.m.pipeline().addBefore("prepender", "encrypt", new PacketEncrypter(MinecraftEncryption.a(1, secretkey)));
this.r = true;
}
public boolean isConnected() {
return this.m != null && this.m.isOpen();
}
public PacketListener getPacketListener() {
return this.o;
}
public IChatBaseComponent f() {
return this.q;
}
public void g() {
this.m.config().setAutoRead(false);
}
protected void channelRead0(ChannelHandlerContext channelhandlercontext, Object object) {
this.a(channelhandlercontext, (Packet) object);
}
static Channel a(NetworkManager networkmanager) {
return networkmanager.m;
}
}