    001package net.minecraft.network.rcon;
    002
    003import java.io.BufferedInputStream;
    004import java.io.ByteArrayOutputStream;
    005import java.io.DataOutputStream;
    006import java.io.IOException;
    007import java.net.Socket;
    008import java.net.SocketTimeoutException;
    009
    010public 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}