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;
|
|
|
|
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);
|
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]);
|
|
|
|
g.debug("Set listener of {} to {}", new Object[] { this, packetlistener});
|
|
|
|
this.m = packetlistener;
|
2012-07-29 09:33:13 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public void handle(Packet packet, GenericFutureListener... agenericfuturelistener) {
|
|
|
|
if (this.k != null && this.k.isOpen()) {
|
|
|
|
this.h();
|
|
|
|
this.b(packet, agenericfuturelistener);
|
2012-07-29 09:33:13 +02:00
|
|
|
} else {
|
2013-11-04 14:07:38 +01:00
|
|
|
this.j.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);
|
|
|
|
EnumProtocol enumprotocol1 = (EnumProtocol) this.k.attr(c).get();
|
2012-07-29 09:33:13 +02:00
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
if (enumprotocol1 != enumprotocol) {
|
|
|
|
g.debug("Disabled auto read");
|
|
|
|
this.k.config().setAutoRead(false);
|
2012-07-29 09:33:13 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
if (this.k.eventLoop().inEventLoop()) {
|
|
|
|
if (enumprotocol != enumprotocol1) {
|
|
|
|
this.a(enumprotocol);
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
2011-05-28 22:50:08 +02:00
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
this.k.writeAndFlush(packet).addListeners(agenericfuturelistener).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
|
|
|
} else {
|
|
|
|
this.k.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
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
private void h() {
|
|
|
|
if (this.k != null && this.k.isOpen()) {
|
|
|
|
while (!this.j.isEmpty()) {
|
|
|
|
QueuedPacket queuedpacket = (QueuedPacket) this.j.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() {
|
|
|
|
this.h();
|
|
|
|
EnumProtocol enumprotocol = (EnumProtocol) this.k.attr(c).get();
|
2011-03-27 22:12:39 +02:00
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
if (this.n != enumprotocol) {
|
|
|
|
if (this.n != null) {
|
|
|
|
this.m.a(this.n, enumprotocol);
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
2013-11-04 14:07:38 +01:00
|
|
|
|
|
|
|
this.n = enumprotocol;
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
if (this.m != null) {
|
|
|
|
for (int i = 1000; !this.i.isEmpty() && i >= 0; --i) {
|
|
|
|
Packet packet = (Packet) this.i.poll();
|
2011-03-27 22:12:39 +02:00
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
// CraftBukkit start
|
|
|
|
if (!this.d() || !this.k.config().isAutoRead()) { // Should be isConnected
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// CraftBukkit end
|
2011-03-27 22:12:39 +02:00
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
packet.handle(this.m);
|
2012-09-10 06:19:28 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
this.m.a();
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
this.k.flush();
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2011-04-20 19:05:14 +02:00
|
|
|
public SocketAddress getSocketAddress() {
|
2013-11-04 14:07:38 +01:00
|
|
|
return this.l;
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public void a(IChatBaseComponent ichatbasecomponent) {
|
|
|
|
if (this.k.isOpen()) {
|
|
|
|
this.k.close();
|
|
|
|
this.o = 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() {
|
|
|
|
return this.k instanceof LocalChannel || this.k instanceof LocalServerChannel;
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
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)));
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public boolean d() {
|
|
|
|
return this.k != null && this.k.isOpen();
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public PacketListener getPacketListener() {
|
|
|
|
return this.m;
|
2011-05-26 14:48:22 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public IChatBaseComponent f() {
|
|
|
|
return this.o;
|
2011-05-26 14:48:22 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 14:07:38 +01:00
|
|
|
public void g() {
|
|
|
|
this.k.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) {
|
|
|
|
return networkmanager.k;
|
2011-03-27 22:12:39 +02:00
|
|
|
}
|
|
|
|
}
|