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}