package net.minecraft.network.rcon;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@SideOnly(Side.SERVER)
public class RConThreadClient extends RConThreadBase
{
private static final Logger LOGGER = LogManager.getLogger();
/** True if the client has succefssfully logged into the RCon, otherwise false */
private boolean loggedIn;
/** 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;
private static final String __OBFID = "CL_00001804";
RConThreadClient(IServer p_i1537_1_, Socket socket)
{
super(p_i1537_1_, "RCON Client");
this.clientSocket = socket;
try
{
this.clientSocket.setSoTimeout(0);
}
catch (Exception exception)
{
this.running = false;
}
this.rconPassword = p_i1537_1_.getStringProperty("rcon.password", "");
this.logInfo("Rcon connection from: " + socket.getInetAddress());
}
public void run()
{
while (true)
{
try
{
if (!this.running)
{
break;
}
BufferedInputStream bufferedinputstream = new BufferedInputStream(this.clientSocket.getInputStream());
int i = bufferedinputstream.read(this.buffer, 0, 1460);
if (10 > i)
{
return;
}
byte b0 = 0;
int j = RConUtils.getBytesAsLEInt(this.buffer, 0, i);
if (j == i - 4)
{
int i1 = b0 + 4;
int k = RConUtils.getBytesAsLEInt(this.buffer, i1, i);
i1 += 4;
int l = RConUtils.getRemainingBytesAsLEInt(this.buffer, i1);
i1 += 4;
switch (l)
{
case 2:
if (this.loggedIn)
{
String s1 = RConUtils.getBytesAsString(this.buffer, i1, i);
try
{
this.sendMultipacketResponse(k, this.server.handleRConCommand(s1));
}
catch (Exception exception)
{
this.sendMultipacketResponse(k, "Error executing: " + s1 + " (" + exception.getMessage() + ")");
}
continue;
}
this.sendLoginFailedResponse();
continue;
case 3:
String s = RConUtils.getBytesAsString(this.buffer, i1, i);
int j1 = i1 + s.length();
if (0 != s.length() && s.equals(this.rconPassword))
{
this.loggedIn = true;
this.sendResponse(k, 2, "");
continue;
}
this.loggedIn = false;
this.sendLoginFailedResponse();
continue;
default:
this.sendMultipacketResponse(k, String.format("Unknown request %s", new Object[] {Integer.toHexString(l)}));
continue;
}
}
}
catch (SocketTimeoutException sockettimeoutexception)
{
break;
}
catch (IOException ioexception)
{
break;
}
catch (Exception exception1)
{
LOGGER.error("Exception whilst parsing RCON input", exception1);
break;
}
finally
{
this.closeSocket();
}
return;
}
}
/**
* Sends the given response message to the client
*/
private void sendResponse(int p_72654_1_, int p_72654_2_, String message) throws IOException
{
ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(1248);
DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream);
byte[] abyte = message.getBytes("UTF-8");
dataoutputstream.writeInt(Integer.reverseBytes(abyte.length + 10));
dataoutputstream.writeInt(Integer.reverseBytes(p_72654_1_));
dataoutputstream.writeInt(Integer.reverseBytes(p_72654_2_));
dataoutputstream.write(abyte);
dataoutputstream.write(0);
dataoutputstream.write(0);
this.clientSocket.getOutputStream().write(bytearrayoutputstream.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 p_72655_1_, String p_72655_2_) throws IOException
{
int j = p_72655_2_.length();
do
{
int k = 4096 <= j ? 4096 : j;
this.sendResponse(p_72655_1_, 0, p_72655_2_.substring(0, k));
p_72655_2_ = p_72655_2_.substring(k);
j = p_72655_2_.length();
}
while (0 != j);
}
/**
* Closes the client socket
*/
private void closeSocket()
{
if (null != this.clientSocket)
{
try
{
this.clientSocket.close();
}
catch (IOException ioexception)
{
this.logWarning("IO: " + ioexception.getMessage());
}
this.clientSocket = null;
}
}
}