    001    package net.minecraft.src;
    002
    003    import java.io.IOException;
    004    import java.net.InetAddress;
    005    import java.net.Socket;
    006    import java.security.PrivateKey;
    007    import java.security.PublicKey;
    008    import java.util.Arrays;
    009    import java.util.Random;
    010    import java.util.logging.Logger;
    011    import javax.crypto.SecretKey;
    012
    013    import cpw.mods.fml.common.network.FMLNetworkHandler;
    014    import net.minecraft.server.MinecraftServer;
    015
    016    public class NetLoginHandler extends NetHandler
    017    {
    018        private byte[] field_72536_d;
    019
    020        /** The Minecraft logger. */
    021        public static Logger logger = Logger.getLogger("Minecraft");
    022
    023        /** The Random object used to generate serverId hex strings. */
    024        private static Random rand = new Random();
    025        public TcpConnection myTCPConnection;
    026        public boolean connectionComplete = false;
    027
    028        /** Reference to the MinecraftServer object. */
    029        private MinecraftServer mcServer;
    030        private int connectionTimer = 0;
    031        public String clientUsername = null;
    032        private volatile boolean field_72544_i = false;
    033
    034        /** server ID that is randomly generated by this login handler. */
    035        private String loginServerId = "";
    036        private SecretKey field_72542_k = null;
    037
    038        public NetLoginHandler(MinecraftServer par1MinecraftServer, Socket par2Socket, String par3Str) throws IOException
    039        {
    040            this.mcServer = par1MinecraftServer;
    041            this.myTCPConnection = new TcpConnection(par2Socket, par3Str, this, par1MinecraftServer.getKeyPair().getPrivate());
    042            this.myTCPConnection.field_74468_e = 0;
    043        }
    044
    045        /**
    046         * Logs the user in if a login packet is found, otherwise keeps processing network packets unless the timeout has
    047         * occurred.
    048         */
    049        public void tryLogin()
    050        {
    051            if (this.field_72544_i)
    052            {
    053                this.initializePlayerConnection();
    054            }
    055
    056            if (this.connectionTimer++ == 6000)
    057            {
    058                this.raiseErrorAndDisconnect("Took too long to log in");
    059            }
    060            else
    061            {
    062                this.myTCPConnection.processReadPackets();
    063            }
    064        }
    065
    066        public void raiseErrorAndDisconnect(String par1Str)
    067        {
    068            try
    069            {
    070                logger.info("Disconnecting " + this.getUsernameAndAddress() + ": " + par1Str);
    071                this.myTCPConnection.addToSendQueue(new Packet255KickDisconnect(par1Str));
    072                this.myTCPConnection.serverShutdown();
    073                this.connectionComplete = true;
    074            }
    075            catch (Exception var3)
    076            {
    077                var3.printStackTrace();
    078            }
    079        }
    080
    081        public void handleClientProtocol(Packet2ClientProtocol par1Packet2ClientProtocol)
    082        {
    083            this.clientUsername = par1Packet2ClientProtocol.getUsername();
    084
    085            if (!this.clientUsername.equals(StringUtils.stripControlCodes(this.clientUsername)))
    086            {
    087                this.raiseErrorAndDisconnect("Invalid username!");
    088            }
    089            else
    090            {
    091                PublicKey var2 = this.mcServer.getKeyPair().getPublic();
    092
    093                if (par1Packet2ClientProtocol.getProtocolVersion() != 39)
    094                {
    095                    if (par1Packet2ClientProtocol.getProtocolVersion() > 39)
    096                    {
    097                        this.raiseErrorAndDisconnect("Outdated server!");
    098                    }
    099                    else
    100                    {
    101                        this.raiseErrorAndDisconnect("Outdated client!");
    102                    }
    103                }
    104                else
    105                {
    106                    this.loginServerId = this.mcServer.isServerInOnlineMode() ? Long.toString(rand.nextLong(), 16) : "-";
    107                    this.field_72536_d = new byte[4];
    108                    rand.nextBytes(this.field_72536_d);
    109                    this.myTCPConnection.addToSendQueue(new Packet253ServerAuthData(this.loginServerId, var2, this.field_72536_d));
    110                }
    111            }
    112        }
    113
    114        public void handleSharedKey(Packet252SharedKey par1Packet252SharedKey)
    115        {
    116            PrivateKey var2 = this.mcServer.getKeyPair().getPrivate();
    117            this.field_72542_k = par1Packet252SharedKey.func_73303_a(var2);
    118
    119            if (!Arrays.equals(this.field_72536_d, par1Packet252SharedKey.func_73302_b(var2)))
    120            {
    121                this.raiseErrorAndDisconnect("Invalid client reply");
    122            }
    123
    124            this.myTCPConnection.addToSendQueue(new Packet252SharedKey());
    125        }
    126
    127        public void handleClientCommand(Packet205ClientCommand par1Packet205ClientCommand)
    128        {
    129            if (par1Packet205ClientCommand.forceRespawn == 0)
    130            {
    131                if (this.mcServer.isServerInOnlineMode())
    132                {
    133                    (new ThreadLoginVerifier(this)).start();
    134                }
    135                else
    136                {
    137                    this.field_72544_i = true;
    138                }
    139            }
    140        }
    141
    142        public void handleLogin(Packet1Login par1Packet1Login) {
    143            FMLNetworkHandler.handleLoginPacketOnServer(this, par1Packet1Login);
    144        }
    145
    146        /**
    147         * on success the specified username is connected to the minecraftInstance, otherwise they are packet255'd
    148         */
    149        public void initializePlayerConnection()
    150        {
    151            FMLNetworkHandler.onConnectionReceivedFromClient(this, this.mcServer, this.myTCPConnection.getSocketAddress(), this.clientUsername);
    152        }
    153
    154        public void completeConnection(String var1)
    155        {
    156            if (var1 != null)
    157            {
    158                this.raiseErrorAndDisconnect(var1);
    159            }
    160            else
    161            {
    162                EntityPlayerMP var2 = this.mcServer.getConfigurationManager().createPlayerForUser(this.clientUsername);
    163
    164                if (var2 != null)
    165                {
    166                    this.mcServer.getConfigurationManager().initializeConnectionToPlayer(this.myTCPConnection, var2);
    167                }
    168            }
    169
    170            this.connectionComplete = true;
    171        }
    172
    173        public void handleErrorMessage(String par1Str, Object[] par2ArrayOfObj)
    174        {
    175            logger.info(this.getUsernameAndAddress() + " lost connection");
    176            this.connectionComplete = true;
    177        }
    178
    179        /**
    180         * Handle a server ping packet.
    181         */
    182        public void handleServerPing(Packet254ServerPing par1Packet254ServerPing)
    183        {
    184            try
    185            {
    186                String var2 = this.mcServer.getMOTD() + "\u00a7" + this.mcServer.getConfigurationManager().getCurrentPlayerCount() + "\u00a7" + this.mcServer.getConfigurationManager().getMaxPlayers();
    187                InetAddress var3 = null;
    188
    189                if (this.myTCPConnection.getSocket() != null)
    190                {
    191                    var3 = this.myTCPConnection.getSocket().getInetAddress();
    192                }
    193
    194                this.myTCPConnection.addToSendQueue(new Packet255KickDisconnect(var2));
    195                this.myTCPConnection.serverShutdown();
    196
    197                if (var3 != null && this.mcServer.getNetworkThread() instanceof DedicatedServerListenThread)
    198                {
    199                    ((DedicatedServerListenThread)this.mcServer.getNetworkThread()).func_71761_a(var3);
    200                }
    201
    202                this.connectionComplete = true;
    203            }
    204            catch (Exception var4)
    205            {
    206                var4.printStackTrace();
    207            }
    208        }
    209
    210        /**
    211         * Default handler called for packets that don't have their own handlers in NetClientHandler; currentlly does
    212         * nothing.
    213         */
    214        public void unexpectedPacket(Packet par1Packet)
    215        {
    216            this.raiseErrorAndDisconnect("Protocol error");
    217        }
    218
    219        public String getUsernameAndAddress()
    220        {
    221            return this.clientUsername != null ? this.clientUsername + " [" + this.myTCPConnection.getSocketAddress().toString() + "]" : this.myTCPConnection.getSocketAddress().toString();
    222        }
    223
    224        /**
    225         * determine if it is a server handler
    226         */
    227        public boolean isServerHandler()
    228        {
    229            return true;
    230        }
    231
    232        /**
    233         * Returns the server Id randomly generated by this login handler.
    234         */
    235        static String getServerId(NetLoginHandler par0NetLoginHandler)
    236        {
    237            return par0NetLoginHandler.loginServerId;
    238        }
    239
    240        /**
    241         * Returns the reference to Minecraft Server.
    242         */
    243        static MinecraftServer getLoginMinecraftServer(NetLoginHandler par0NetLoginHandler)
    244        {
    245            return par0NetLoginHandler.mcServer;
    246        }
    247
    248        static SecretKey func_72525_c(NetLoginHandler par0NetLoginHandler)
    249        {
    250            return par0NetLoginHandler.field_72542_k;
    251        }
    252
    253        /**
    254         * Returns the connecting client username.
    255         */
    256        static String getClientUsername(NetLoginHandler par0NetLoginHandler)
    257        {
    258            return par0NetLoginHandler.clientUsername;
    259        }
    260
    261        public static boolean func_72531_a(NetLoginHandler par0NetLoginHandler, boolean par1)
    262        {
    263            return par0NetLoginHandler.field_72544_i = par1;
    264        }
    265
    266        public void handleCustomPayload(Packet250CustomPayload par1Packet250CustomPayload)
    267        {
    268            FMLNetworkHandler.handlePacket250Packet(par1Packet250CustomPayload, myTCPConnection, this);
    269        }
    270
    271        @Override
    272        public void handleVanilla250Packet(Packet250CustomPayload payload)
    273        {
    274            // NOOP for login
    275        }
    276
    277        public EntityPlayer getPlayer()
    278        {
    279            return null;
    280        };
    281    }