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                        byte var3 = 0;
061                        int var4 = RConUtils.getBytesAsLEInt(this.buffer, 0, var2);
062    
063                        if (var4 != var2 - 4)
064                        {
065                            return;
066                        }
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    }