package net.minecraft.server; 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 RemoteControlSession extends RemoteConnectionThread { private boolean g = false; private Socket h; private byte[] i = new byte[1460]; private String j; RemoteControlSession(IMinecraftServer iminecraftserver, Socket socket) { super(iminecraftserver); this.h = socket; // CraftBukkit start - set infinite timeout so we sleep until there is data available try { this.h.setSoTimeout(0); } catch (Exception ex) { this.running = false; } // CraftBukkit end this.j = iminecraftserver.a("rcon.password", ""); this.info("Rcon connection from: " + socket.getInetAddress()); } public void run() { // while (true) { // CraftBukkit - moved down try { while (true) { // CraftBukkit - moved from above if (!this.running) { return; } try { BufferedInputStream bufferedinputstream = new BufferedInputStream(this.h.getInputStream()); int i = bufferedinputstream.read(this.i, 0, 1460); if (10 <= i) { byte b0 = 0; int j = StatusChallengeUtils.b(this.i, 0, i); if (j != i - 4) { return; } int k = b0 + 4; int l = StatusChallengeUtils.b(this.i, k, i); k += 4; int i1 = StatusChallengeUtils.a(this.i, k); k += 4; switch (i1) { case 2: if (this.g) { String s = StatusChallengeUtils.a(this.i, k, i); try { this.a(l, this.server.d(s)); } catch (Exception exception) { this.a(l, "Error executing: " + s + " (" + exception.getMessage() + ")"); } continue; } this.e(); continue; case 3: String s1 = StatusChallengeUtils.a(this.i, k, i); int j1 = k + s1.length(); if (0 != s1.length() && s1.equals(this.j)) { this.g = true; this.a(l, 2, ""); continue; } this.g = false; this.e(); continue; default: this.a(l, String.format("Unknown request %s", new Object[] { Integer.toHexString(i1)})); continue; } } return; // CraftBukkit - return if we don't get enough data } catch (SocketTimeoutException sockettimeoutexception) { continue; } catch (IOException ioexception) { if (this.running) { this.info("IO: " + ioexception.getMessage()); } return; // CraftBukkit - shut down the thread after hitting an exception. } } // CraftBukkit - Loop shift } catch (Exception exception1) { System.out.println(exception1); return; } finally { this.f(); } // CraftBukkit - Loop shift } private void a(int i, int j, String s) throws IOException { // CraftBukkit - throws IOException ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(1248); DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream); dataoutputstream.writeInt(Integer.reverseBytes(s.length() + 10)); dataoutputstream.writeInt(Integer.reverseBytes(i)); dataoutputstream.writeInt(Integer.reverseBytes(j)); dataoutputstream.writeBytes(s); dataoutputstream.write(0); dataoutputstream.write(0); this.h.getOutputStream().write(bytearrayoutputstream.toByteArray()); } private void e() throws IOException { // CraftBukkit - throws IOException this.a(-1, 2, ""); } private void a(int i, String s) throws IOException { // CraftBukkit - throws IOException int j = s.length(); do { int k = 4096 <= j ? 4096 : j; this.a(i, 0, s.substring(0, k)); s = s.substring(k); j = s.length(); } while (0 != j); } private void f() { if (null != this.h) { try { this.h.close(); this.info("Rcon connection closed."); // CraftBukkit } catch (IOException ioexception) { this.warning("IO: " + ioexception.getMessage()); } this.h = null; } } }