All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.minecraft.server.NetworkManager Maven / Gradle / Ivy

package net.minecraft.server;

import com.google.common.collect.Queues;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.netty.channel.*;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.local.LocalChannel;
import io.netty.channel.local.LocalEventLoopGroup;
import io.netty.channel.local.LocalServerChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.handler.timeout.TimeoutException;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import org.apache.commons.lang3.ArrayUtils;
import 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;

import javax.crypto.SecretKey;
import java.net.SocketAddress;
import java.util.Queue;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class NetworkManager extends SimpleChannelInboundHandler {
	
	public static final Marker a = MarkerManager.getMarker("NETWORK");
	public static final Marker b = MarkerManager.getMarker("NETWORK_PACKETS", NetworkManager.a);
	public static final AttributeKey c = AttributeKey.valueOf("protocol");
	public static final LazyInitVar d = new LazyInitVar() {
		protected NioEventLoopGroup a() {
			return new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Client IO #%d").setDaemon(true).build());
		}
		
		protected Object init() {
			return this.a();
		}
	};
	public static final LazyInitVar e = new LazyInitVar() {
		protected EpollEventLoopGroup a() {
			return new EpollEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Epoll Client IO #%d").setDaemon(true).build());
		}
		
		protected Object init() {
			return this.a();
		}
	};
	public static final LazyInitVar f = new LazyInitVar() {
		protected LocalEventLoopGroup a() {
			return new LocalEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty Local Client IO #%d").setDaemon(true).build());
		}
		
		protected Object init() {
			return this.a();
		}
	};
	private static final Logger g = LogManager.getLogger();
	private final EnumProtocolDirection h;
	private final Queue i = Queues.newConcurrentLinkedQueue();
	private final ReentrantReadWriteLock j = new ReentrantReadWriteLock();
	public Channel channel;
	// Spigot Start // PAIL
	public SocketAddress l;
	public java.util.UUID spoofedUUID;
	public com.mojang.authlib.properties.Property[] spoofedProfile;
	public boolean preparing = true;
	// Spigot End
	private PacketListener m;
	private IChatBaseComponent n;
	private boolean o;
	private boolean p;
	
	public NetworkManager(EnumProtocolDirection enumprotocoldirection) {
		this.h = enumprotocoldirection;
	}
	
	public void channelActive(ChannelHandlerContext channelhandlercontext) throws Exception {
		super.channelActive(channelhandlercontext);
		this.channel = channelhandlercontext.channel();
		this.l = this.channel.remoteAddress();
		// Spigot Start
		this.preparing = false;
		// Spigot End
		
		try {
			this.a(EnumProtocol.HANDSHAKING);
		} catch (Throwable throwable) {
			NetworkManager.g.fatal(throwable);
		}
		
	}
	
	public void a(EnumProtocol enumprotocol) {
		this.channel.attr(NetworkManager.c).set(enumprotocol);
		this.channel.config().setAutoRead(true);
		NetworkManager.g.debug("Enabled auto read");
	}
	
	public void channelInactive(ChannelHandlerContext channelhandlercontext) {
		this.close(new ChatMessage("disconnect.endOfStream"));
	}
	
	public void exceptionCaught(ChannelHandlerContext channelhandlercontext, Throwable throwable) {
		ChatMessage chatmessage;
		
		if (throwable instanceof TimeoutException) {
			chatmessage = new ChatMessage("disconnect.timeout");
		} else {
			chatmessage = new ChatMessage("disconnect.genericReason", "Internal Exception: " + throwable);
		}
		
		this.close(chatmessage);
		if (MinecraftServer.getServer().isDebugging()) throwable.printStackTrace(); // Spigot
	}
	
	protected void a(ChannelHandlerContext channelhandlercontext, Packet packet) throws Exception {
		if (this.channel.isOpen()) {
			try {
				packet.a(this.m);
			} catch (CancelledPacketHandleException ignored) {
			}
		}
		
	}
	
	public void a(PacketListener packetlistener) {
		Validate.notNull(packetlistener, "packetListener");
		NetworkManager.g.debug("Set listener of {} to {}", this, packetlistener);
		this.m = packetlistener;
	}
	
	public void handle(Packet packet) {
		if (this.g()) {
			this.m();
			this.a(packet, null);
		} else {
			this.j.writeLock().lock();
			
			try {
				this.i.add(new NetworkManager.QueuedPacket(packet, (GenericFutureListener[]) null));
			} finally {
				this.j.writeLock().unlock();
			}
		}
		
	}
	
	public void a(Packet packet, GenericFutureListener> genericfuturelistener, GenericFutureListener>... agenericfuturelistener) {
		if (this.g()) {
			this.m();
			this.a(packet, ArrayUtils.add(agenericfuturelistener, 0, genericfuturelistener));
		} else {
			this.j.writeLock().lock();
			
			try {
				this.i.add(new NetworkManager.QueuedPacket(packet, ArrayUtils.add(agenericfuturelistener, 0, genericfuturelistener)));
			} finally {
				this.j.writeLock().unlock();
			}
		}
		
	}
	
	private void a(final Packet packet, final GenericFutureListener>[] agenericfuturelistener) {
		final EnumProtocol enumprotocol = EnumProtocol.a(packet);
		final EnumProtocol enumprotocol1 = this.channel.attr(NetworkManager.c).get();
		
		if (enumprotocol1 != enumprotocol) {
			NetworkManager.g.debug("Disabled auto read");
			this.channel.config().setAutoRead(false);
		}
		
		if (this.channel.eventLoop().inEventLoop()) {
			if (enumprotocol != enumprotocol1) {
				this.a(enumprotocol);
			}
			
			ChannelFuture channelfuture = this.channel.writeAndFlush(packet);
			
			if (agenericfuturelistener != null) {
				channelfuture.addListeners(agenericfuturelistener);
			}
			
			channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
		} else {
			this.channel.eventLoop().execute(() -> {
				if (enumprotocol != enumprotocol1) {
					NetworkManager.this.a(enumprotocol);
				}
				
				ChannelFuture channelfuture = NetworkManager.this.channel.writeAndFlush(packet);
				
				if (agenericfuturelistener != null) {
					channelfuture.addListeners(agenericfuturelistener);
				}
				
				channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
			});
		}
		
	}
	
	private void m() {
		if (this.channel != null && this.channel.isOpen()) {
			this.j.readLock().lock();
			
			try {
				while (!this.i.isEmpty()) {
					NetworkManager.QueuedPacket packet = this.i.poll();
					this.a(packet.a, packet.b);
				}
			} finally {
				this.j.readLock().unlock();
			}
			
		}
	}
	
	public void a() {
		this.m();
		if (this.m instanceof IUpdatePlayerListBox) {
			((IUpdatePlayerListBox) this.m).c();
		}
		
		this.channel.flush();
	}
	
	public SocketAddress getSocketAddress() {
		return this.l;
	}
	
	public void close(IChatBaseComponent ichatbasecomponent) {
		// Spigot Start
		this.preparing = false;
		// Spigot End
		if (this.channel.isOpen()) {
			this.channel.close(); // We can't wait as this may be called from an event loop.
			this.n = ichatbasecomponent;
		}
		
	}
	
	public boolean c() {
		return this.channel instanceof LocalChannel || this.channel instanceof LocalServerChannel;
	}
	
	public void a(SecretKey secretkey) {
		this.o = true;
		this.channel.pipeline().addBefore("splitter", "decrypt", new PacketDecrypter(MinecraftEncryption.a(2, secretkey)));
		this.channel.pipeline().addBefore("prepender", "encrypt", new PacketEncrypter(MinecraftEncryption.a(1, secretkey)));
	}
	
	public boolean g() {
		return this.channel != null && this.channel.isOpen();
	}
	
	public boolean h() {
		return this.channel == null;
	}
	
	public PacketListener getPacketListener() {
		return this.m;
	}
	
	public IChatBaseComponent j() {
		return this.n;
	}
	
	public void k() {
		this.channel.config().setAutoRead(false);
	}
	
	public void a(int i) {
		final ChannelPipeline line = channel.pipeline();
		if (i >= 0) {
			if (line.get("decompress") instanceof PacketDecompressor) {
				((PacketDecompressor) line.get("decompress")).a(i);
			} else {
				line.addBefore("decoder", "decompress", new PacketDecompressor(i));
			}
			
			if (line.get("compress") instanceof PacketCompressor) {
				((PacketCompressor) line.get("decompress")).a(i);
			} else {
				line.addBefore("encoder", "compress", new PacketCompressor(i));
			}
		} else {
			if (line.get("decompress") instanceof PacketDecompressor) {
				line.remove("decompress");
			}
			
			if (line.get("compress") instanceof PacketCompressor) {
				line.remove("compress");
			}
		}
	}
	
	public void l() {
		if (this.channel != null && !this.channel.isOpen()) {
			if (!this.p) {
				this.p = true;
				if (this.j() != null) {
					this.getPacketListener().a(this.j());
				} else if (this.getPacketListener() != null) {
					this.getPacketListener().a(new ChatComponentText("Disconnected"));
				}
				this.i.clear(); // Free up packet queue.
			} else {
				NetworkManager.g.warn("handleDisconnection() called twice");
			}
			
		}
	}
	
	protected void channelRead0(ChannelHandlerContext channelhandlercontext, Packet object) throws Exception { // CraftBukkit - fix decompile error
		this.a(channelhandlercontext, object);
	}
	
	// Spigot Start
	public SocketAddress getRawAddress() {
		return this.channel.remoteAddress();
	}
	
	static class QueuedPacket {
		
		private final Packet a;
		private final GenericFutureListener>[] b;
		
		@SafeVarargs
		public QueuedPacket(Packet packet, GenericFutureListener>... agenericfuturelistener) {
			this.a = packet;
			this.b = agenericfuturelistener;
		}
	}
	// Spigot End
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy