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