    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        try
    047        {
    048            while (true)
    049            {
    050                if (!this.running)
    051                {
    052                    break;
    053                }
    054
    055                BufferedInputStream bufferedinputstream = new BufferedInputStream(this.clientSocket.getInputStream());
    056                int i = bufferedinputstream.read(this.buffer, 0, 1460);
    057
    058                if (10 > i)
    059                {
    060                    return;
    061                }
    062
    063                byte b0 = 0;
    064                int j = RConUtils.getBytesAsLEInt(this.buffer, 0, i);
    065
    066                if (j == i - 4)
    067                {
    068                    int k = b0 + 4;
    069                    int l = RConUtils.getBytesAsLEInt(this.buffer, k, i);
    070                    k += 4;
    071                    int i1 = RConUtils.getRemainingBytesAsLEInt(this.buffer, k);
    072                    k += 4;
    073
    074                    switch (i1)
    075                    {
    076                        case 2:
    077                            if (this.loggedIn)
    078                            {
    079                                String s = RConUtils.getBytesAsString(this.buffer, k, i);
    080
    081                                try
    082                                {
    083                                    this.sendMultipacketResponse(l, this.server.executeCommand(s));
    084                                }
    085                                catch (Exception exception)
    086                                {
    087                                    this.sendMultipacketResponse(l, "Error executing: " + s + " (" + exception.getMessage() + ")");
    088                                }
    089
    090                                continue;
    091                            }
    092
    093                            this.sendLoginFailedResponse();
    094                            continue;
    095                        case 3:
    096                            String s1 = RConUtils.getBytesAsString(this.buffer, k, i);
    097                            int j1 = k + s1.length();
    098
    099                            if (0 != s1.length() && s1.equals(this.rconPassword))
    100                            {
    101                                this.loggedIn = true;
    102                                this.sendResponse(l, 2, "");
    103                                continue;
    104                            }
    105
    106                            this.loggedIn = false;
    107                            this.sendLoginFailedResponse();
    108                            continue;
    109                        default:
    110                            this.sendMultipacketResponse(l, String.format("Unknown request %s", new Object[] {Integer.toHexString(i1)}));
    111                            continue;
    112                    }
    113                }
    114            }
    115        }
    116        catch (SocketTimeoutException sockettimeoutexception)
    117        {
    118        }
    119        catch (IOException ioexception)
    120        {
    121        }
    122        catch (Exception exception1)
    123        {
    124            System.out.println(exception1);
    125        }
    126        finally
    127        {
    128            this.closeSocket();
    129        }
    130    }
    131
    132    /**
    133     * Sends the given response message to the client
    134     */
    135    private void sendResponse(int par1, int par2, String par3Str) throws IOException
    136    {
    137        ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(1248);
    138        DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream);
    139        dataoutputstream.writeInt(Integer.reverseBytes(par3Str.length() + 10));
    140        dataoutputstream.writeInt(Integer.reverseBytes(par1));
    141        dataoutputstream.writeInt(Integer.reverseBytes(par2));
    142        dataoutputstream.writeBytes(par3Str);
    143        dataoutputstream.write(0);
    144        dataoutputstream.write(0);
    145        this.clientSocket.getOutputStream().write(bytearrayoutputstream.toByteArray());
    146    }
    147
    148    /**
    149     * Sends the standard RCon 'authorization failed' response packet
    150     */
    151    private void sendLoginFailedResponse() throws IOException
    152    {
    153        this.sendResponse(-1, 2, "");
    154    }
    155
    156    /**
    157     * Splits the response message into individual packets and sends each one
    158     */
    159    private void sendMultipacketResponse(int par1, String par2Str) throws IOException
    160    {
    161        int j = par2Str.length();
    162
    163        do
    164        {
    165            int k = 4096 <= j ? 4096 : j;
    166            this.sendResponse(par1, 0, par2Str.substring(0, k));
    167            par2Str = par2Str.substring(k);
    168            j = par2Str.length();
    169        }
    170        while (0 != j);
    171    }
    172
    173    /**
    174     * Closes the client socket
    175     */
    176    private void closeSocket()
    177    {
    178        if (null != this.clientSocket)
    179        {
    180            try
    181            {
    182                this.clientSocket.close();
    183            }
    184            catch (IOException ioexception)
    185            {
    186                this.logWarning("IO: " + ioexception.getMessage());
    187            }
    188
    189            this.clientSocket = null;
    190        }
    191    }
    192}