    001    package net.minecraft.network.rcon;
    002
    003    import java.io.BufferedInputStream;
    004    import java.io.ByteArrayOutputStream;
    005    import java.io.DataOutputStream;
    006    import java.io.IOException;
    007    import java.net.Socket;
    008    import java.net.SocketTimeoutException;
    009
    010    public class RConThreadClient extends RConThreadBase
    011    {
    012        /**
    013         * True if the client has succefssfully logged into the RCon, otherwise false
    014         */
    015        private boolean loggedIn = false;
    016
    017        /** The client's Socket connection */
    018        private Socket clientSocket;
    019
    020        /** A buffer for incoming Socket data */
    021        private byte[] buffer = new byte[1460];
    022
    023        /** The RCon password */
    024        private String rconPassword;
    025
    026        RConThreadClient(IServer par1IServer, Socket par2Socket)
    027        {
    028            super(par1IServer);
    029            this.clientSocket = par2Socket;
    030
    031            try
    032            {
    033                this.clientSocket.setSoTimeout(0);
    034            }
    035            catch (Exception var4)
    036            {
    037                this.running = false;
    038            }
    039
    040            this.rconPassword = par1IServer.getStringProperty("rcon.password", "");
    041            this.logInfo("Rcon connection from: " + par2Socket.getInetAddress());
    042        }
    043
    044        public void run()
    045        {
    046            while (true)
    047            {
    048                try
    049                {
    050                    if (!this.running)
    051                    {
    052                        break;
    053                    }
    054
    055                    BufferedInputStream var1 = new BufferedInputStream(this.clientSocket.getInputStream());
    056                    int var2 = var1.read(this.buffer, 0, 1460);
    057
    058                    if (10 > var2)
    059                    {
    060                        return;
    061                    }
    062
    063                    byte var3 = 0;
    064                    int var4 = RConUtils.getBytesAsLEInt(this.buffer, 0, var2);
    065
    066                    if (var4 == var2 - 4)
    067                    {
    068                        int var21 = var3 + 4;
    069                        int var5 = RConUtils.getBytesAsLEInt(this.buffer, var21, var2);
    070                        var21 += 4;
    071                        int var6 = RConUtils.getRemainingBytesAsLEInt(this.buffer, var21);
    072                        var21 += 4;
    073
    074                        switch (var6)
    075                        {
    076                            case 2:
    077                                if (this.loggedIn)
    078                                {
    079                                    String var8 = RConUtils.getBytesAsString(this.buffer, var21, var2);
    080
    081                                    try
    082                                    {
    083                                        this.sendMultipacketResponse(var5, this.server.executeCommand(var8));
    084                                    }
    085                                    catch (Exception var16)
    086                                    {
    087                                        this.sendMultipacketResponse(var5, "Error executing: " + var8 + " (" + var16.getMessage() + ")");
    088                                    }
    089
    090                                    continue;
    091                                }
    092
    093                                this.sendLoginFailedResponse();
    094                                continue;
    095                            case 3:
    096                                String var7 = RConUtils.getBytesAsString(this.buffer, var21, var2);
    097                                int var10000 = var21 + var7.length();
    098
    099                                if (0 != var7.length() && var7.equals(this.rconPassword))
    100                                {
    101                                    this.loggedIn = true;
    102                                    this.sendResponse(var5, 2, "");
    103                                    continue;
    104                                }
    105
    106                                this.loggedIn = false;
    107                                this.sendLoginFailedResponse();
    108                                continue;
    109                            default:
    110                                this.sendMultipacketResponse(var5, String.format("Unknown request %s", new Object[] {Integer.toHexString(var6)}));
    111                                continue;
    112                        }
    113                    }
    114                }
    115                catch (SocketTimeoutException var17)
    116                {
    117                    break;
    118                }
    119                catch (IOException var18)
    120                {
    121                    break;
    122                }
    123                catch (Exception var19)
    124                {
    125                    System.out.println(var19);
    126                    break;
    127                }
    128                finally
    129                {
    130                    this.closeSocket();
    131                }
    132
    133                return;
    134            }
    135        }
    136
    137        /**
    138         * Sends the given response message to the client
    139         */
    140        private void sendResponse(int par1, int par2, String par3Str) throws IOException
    141        {
    142            ByteArrayOutputStream var4 = new ByteArrayOutputStream(1248);
    143            DataOutputStream var5 = new DataOutputStream(var4);
    144            var5.writeInt(Integer.reverseBytes(par3Str.length() + 10));
    145            var5.writeInt(Integer.reverseBytes(par1));
    146            var5.writeInt(Integer.reverseBytes(par2));
    147            var5.writeBytes(par3Str);
    148            var5.write(0);
    149            var5.write(0);
    150            this.clientSocket.getOutputStream().write(var4.toByteArray());
    151        }
    152
    153        /**
    154         * Sends the standard RCon 'authorization failed' response packet
    155         */
    156        private void sendLoginFailedResponse() throws IOException
    157        {
    158            this.sendResponse(-1, 2, "");
    159        }
    160
    161        /**
    162         * Splits the response message into individual packets and sends each one
    163         */
    164        private void sendMultipacketResponse(int par1, String par2Str) throws IOException
    165        {
    166            int var3 = par2Str.length();
    167
    168            do
    169            {
    170                int var4 = 4096 <= var3 ? 4096 : var3;
    171                this.sendResponse(par1, 0, par2Str.substring(0, var4));
    172                par2Str = par2Str.substring(var4);
    173                var3 = par2Str.length();
    174            }
    175            while (0 != var3);
    176        }
    177
    178        /**
    179         * Closes the client socket
    180         */
    181        private void closeSocket()
    182        {
    183            if (null != this.clientSocket)
    184            {
    185                try
    186                {
    187                    this.clientSocket.close();
    188                }
    189                catch (IOException var2)
    190                {
    191                    this.logWarning("IO: " + var2.getMessage());
    192                }
    193
    194                this.clientSocket = null;
    195            }
    196        }
    197    }