package net.minecraft.network;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.local.LocalAddress;
import io.netty.channel.local.LocalServerChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import net.minecraft.client.network.NetHandlerHandshakeMemory;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.network.play.server.S40PacketDisconnect;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.NetHandlerHandshakeTCP;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.MessageDeserializer;
import net.minecraft.util.MessageDeserializer2;
import net.minecraft.util.MessageSerializer;
import net.minecraft.util.MessageSerializer2;
import net.minecraft.util.ReportedException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class NetworkSystem
{
private static final Logger logger = LogManager.getLogger();
private static final NioEventLoopGroup eventLoops = new NioEventLoopGroup(0, (new ThreadFactoryBuilder()).setNameFormat("Netty IO #%d").setDaemon(true).build());
/** Reference to the MinecraftServer object. */
private final MinecraftServer mcServer;
/** True if this NetworkSystem has never had his endpoints terminated */
public volatile boolean isAlive;
/** Contains all endpoints added to this NetworkSystem */
private final List endpoints = Collections.synchronizedList(new ArrayList());
/** A list containing all NetworkManager instances of all endpoints */
private final List networkManagers = Collections.synchronizedList(new ArrayList());
private static final String __OBFID = "CL_00001447";
public NetworkSystem(MinecraftServer server)
{
this.mcServer = server;
this.isAlive = true;
}
/**
* Adds a channel that listens on publicly accessible network ports
*/
public void addLanEndpoint(InetAddress address, int port) throws IOException
{
List list = this.endpoints;
synchronized (this.endpoints)
{
this.endpoints.add(((ServerBootstrap)((ServerBootstrap)(new ServerBootstrap()).channel(NioServerSocketChannel.class)).childHandler(new ChannelInitializer()
{
private static final String __OBFID = "CL_00001448";
protected void initChannel(Channel p_initChannel_1_)
{
try
{
p_initChannel_1_.config().setOption(ChannelOption.IP_TOS, Integer.valueOf(24));
}
catch (ChannelException channelexception1)
{
;
}
try
{
p_initChannel_1_.config().setOption(ChannelOption.TCP_NODELAY, Boolean.valueOf(false));
}
catch (ChannelException channelexception)
{
;
}
p_initChannel_1_.pipeline().addLast("timeout", new ReadTimeoutHandler(FMLNetworkHandler.READ_TIMEOUT)).addLast("legacy_query", new PingResponseHandler(NetworkSystem.this)).addLast("splitter", new MessageDeserializer2()).addLast("decoder", new MessageDeserializer(NetworkManager.STATISTICS)).addLast("prepender", new MessageSerializer2()).addLast("encoder", new MessageSerializer(NetworkManager.STATISTICS));
NetworkManager networkmanager = new NetworkManager(false);
NetworkSystem.this.networkManagers.add(networkmanager);
p_initChannel_1_.pipeline().addLast("packet_handler", networkmanager);
networkmanager.setNetHandler(new NetHandlerHandshakeTCP(NetworkSystem.this.mcServer, networkmanager));
}
}).group(eventLoops).localAddress(address, port)).bind().syncUninterruptibly());
}
}
/**
* Adds a channel that listens locally
*/
@SideOnly(Side.CLIENT)
public SocketAddress addLocalEndpoint()
{
List list = this.endpoints;
ChannelFuture channelfuture;
synchronized (this.endpoints)
{
channelfuture = ((ServerBootstrap)((ServerBootstrap)(new ServerBootstrap()).channel(LocalServerChannel.class)).childHandler(new ChannelInitializer()
{
private static final String __OBFID = "CL_00001449";
protected void initChannel(Channel p_initChannel_1_)
{
NetworkManager networkmanager = new NetworkManager(false);
networkmanager.setNetHandler(new NetHandlerHandshakeMemory(NetworkSystem.this.mcServer, networkmanager));
NetworkSystem.this.networkManagers.add(networkmanager);
p_initChannel_1_.pipeline().addLast("packet_handler", networkmanager);
}
}).group(eventLoops).localAddress(LocalAddress.ANY)).bind().syncUninterruptibly();
this.endpoints.add(channelfuture);
}
return channelfuture.channel().localAddress();
}
/**
* Shuts down all open endpoints (with immediate effect?)
*/
public void terminateEndpoints()
{
this.isAlive = false;
Iterator iterator = this.endpoints.iterator();
while (iterator.hasNext())
{
ChannelFuture channelfuture = (ChannelFuture)iterator.next();
channelfuture.channel().close().syncUninterruptibly();
}
}
/**
* Will try to process the packets received by each NetworkManager, gracefully manage processing failures and cleans
* up dead connections
*/
public void networkTick()
{
List list = this.networkManagers;
synchronized (this.networkManagers)
{
Iterator iterator = this.networkManagers.iterator();
while (iterator.hasNext())
{
final NetworkManager networkmanager = (NetworkManager)iterator.next();
if (!networkmanager.isChannelOpen())
{
iterator.remove();
if (networkmanager.getExitMessage() != null)
{
networkmanager.getNetHandler().onDisconnect(networkmanager.getExitMessage());
}
else if (networkmanager.getNetHandler() != null)
{
networkmanager.getNetHandler().onDisconnect(new ChatComponentText("Disconnected"));
}
}
else
{
try
{
networkmanager.processReceivedPackets();
}
catch (Exception exception)
{
if (networkmanager.isLocalChannel())
{
CrashReport crashreport = CrashReport.makeCrashReport(exception, "Ticking memory connection");
CrashReportCategory crashreportcategory = crashreport.makeCategory("Ticking connection");
crashreportcategory.addCrashSectionCallable("Connection", new Callable()
{
private static final String __OBFID = "CL_00001450";
public String call()
{
return networkmanager.toString();
}
});
throw new ReportedException(crashreport);
}
logger.warn("Failed to handle packet for " + networkmanager.getRemoteAddress(), exception);
final ChatComponentText chatcomponenttext = new ChatComponentText("Internal server error");
networkmanager.scheduleOutboundPacket(new S40PacketDisconnect(chatcomponenttext), new GenericFutureListener[] {new GenericFutureListener()
{
private static final String __OBFID = "CL_00001451";
public void operationComplete(Future p_operationComplete_1_)
{
networkmanager.closeChannel(chatcomponenttext);
}
}
});
networkmanager.disableAutoRead();
}
}
}
}
}
public MinecraftServer getServer()
{
return this.mcServer;
}
}