package net.minecraft.network.rcon; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.net.SocketTimeoutException; public class RConThreadClient extends RConThreadBase { /** * True if the client has succefssfully logged into the RCon, otherwise false */ private boolean loggedIn = false; /** The client's Socket connection */ private Socket clientSocket; /** A buffer for incoming Socket data */ private byte[] buffer = new byte[1460]; /** The RCon password */ private String rconPassword; RConThreadClient(IServer par1IServer, Socket par2Socket) { super(par1IServer); this.clientSocket = par2Socket; try { this.clientSocket.setSoTimeout(0); } catch (Exception var4) { this.running = false; } this.rconPassword = par1IServer.getStringProperty("rcon.password", ""); this.logInfo("Rcon connection from: " + par2Socket.getInetAddress()); } public void run() { while (true) { try { if (!this.running) { break; } BufferedInputStream var1 = new BufferedInputStream(this.clientSocket.getInputStream()); int var2 = var1.read(this.buffer, 0, 1460); if (10 > var2) { return; } byte var3 = 0; int var4 = RConUtils.getBytesAsLEInt(this.buffer, 0, var2); if (var4 == var2 - 4) { int var21 = var3 + 4; int var5 = RConUtils.getBytesAsLEInt(this.buffer, var21, var2); var21 += 4; int var6 = RConUtils.getRemainingBytesAsLEInt(this.buffer, var21); var21 += 4; switch (var6) { case 2: if (this.loggedIn) { String var8 = RConUtils.getBytesAsString(this.buffer, var21, var2); try { this.sendMultipacketResponse(var5, this.server.executeCommand(var8)); } catch (Exception var16) { this.sendMultipacketResponse(var5, "Error executing: " + var8 + " (" + var16.getMessage() + ")"); } continue; } this.sendLoginFailedResponse(); continue; case 3: String var7 = RConUtils.getBytesAsString(this.buffer, var21, var2); int var10000 = var21 + var7.length(); if (0 != var7.length() && var7.equals(this.rconPassword)) { this.loggedIn = true; this.sendResponse(var5, 2, ""); continue; } this.loggedIn = false; this.sendLoginFailedResponse(); continue; default: this.sendMultipacketResponse(var5, String.format("Unknown request %s", new Object[] {Integer.toHexString(var6)})); continue; } } } catch (SocketTimeoutException var17) { break; } catch (IOException var18) { break; } catch (Exception var19) { System.out.println(var19); break; } finally { this.closeSocket(); } return; } } /** * Sends the given response message to the client */ private void sendResponse(int par1, int par2, String par3Str) throws IOException { ByteArrayOutputStream var4 = new ByteArrayOutputStream(1248); DataOutputStream var5 = new DataOutputStream(var4); var5.writeInt(Integer.reverseBytes(par3Str.length() + 10)); var5.writeInt(Integer.reverseBytes(par1)); var5.writeInt(Integer.reverseBytes(par2)); var5.writeBytes(par3Str); var5.write(0); var5.write(0); this.clientSocket.getOutputStream().write(var4.toByteArray()); } /** * Sends the standard RCon 'authorization failed' response packet */ private void sendLoginFailedResponse() throws IOException { this.sendResponse(-1, 2, ""); } /** * Splits the response message into individual packets and sends each one */ private void sendMultipacketResponse(int par1, String par2Str) throws IOException { int var3 = par2Str.length(); do { int var4 = 4096 <= var3 ? 4096 : var3; this.sendResponse(par1, 0, par2Str.substring(0, var4)); par2Str = par2Str.substring(var4); var3 = par2Str.length(); } while (0 != var3); } /** * Closes the client socket */ private void closeSocket() { if (null != this.clientSocket) { try { this.clientSocket.close(); } catch (IOException var2) { this.logWarning("IO: " + var2.getMessage()); } this.clientSocket = null; } } }