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}