RconClient.java

net.minecraft.server.rcon.thread.RconClient

信息

  • 全限定名:net.minecraft.server.rcon.thread.RconClient
  • 类型:public class
  • 包:net.minecraft.server.rcon.thread
  • 源码路径:src/main/java/net/minecraft/server/rcon/thread/RconClient.java
  • 起始行号:L15
  • 继承:GenericThread
  • 职责:

    TODO

字段/常量

  • LOGGER

    • 类型: Logger
    • 修饰符: private static final
    • 源码定位: L16
    • 说明:

      TODO

  • SERVERDATA_AUTH

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L17
    • 说明:

      TODO

  • SERVERDATA_EXECCOMMAND

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L18
    • 说明:

      TODO

  • SERVERDATA_RESPONSE_VALUE

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L19
    • 说明:

      TODO

  • SERVERDATA_AUTH_RESPONSE

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L20
    • 说明:

      TODO

  • SERVERDATA_AUTH_FAILURE

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L21
    • 说明:

      TODO

  • authed

    • 类型: boolean
    • 修饰符: private
    • 源码定位: L22
    • 说明:

      TODO

  • client

    • 类型: Socket
    • 修饰符: private final
    • 源码定位: L23
    • 说明:

      TODO

  • buf

    • 类型: byte[]
    • 修饰符: private final
    • 源码定位: L24
    • 说明:

      TODO

  • rconPassword

    • 类型: String
    • 修饰符: private final
    • 源码定位: L25
    • 说明:

      TODO

  • serverInterface

    • 类型: ServerInterface
    • 修饰符: private final
    • 源码定位: L26
    • 说明:

      TODO

内部类/嵌套类型

构造器

RconClient(ServerInterface serverInterface, String rconPassword, Socket socket) @ L28

  • 构造器名:RconClient
  • 源码定位:L28
  • 修饰符:package-private

参数:

  • serverInterface: ServerInterface
  • rconPassword: String
  • socket: Socket

说明:

TODO

方法

下面的方法块按源码顺序生成。

public void run() @ L42

  • 方法名:run
  • 源码定位:L42
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

private void send(int requestid, int cmd, String str) @ L108

  • 方法名:send
  • 源码定位:L108
  • 返回类型:void
  • 修饰符:private

参数:

  • requestid: int
  • cmd: int
  • str: String

说明:

TODO

private void sendAuthFailure() @ L121

  • 方法名:sendAuthFailure
  • 源码定位:L121
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

private void sendCmdResponse(int requestid, String response) @ L125

  • 方法名:sendCmdResponse
  • 源码定位:L125
  • 返回类型:void
  • 修饰符:private

参数:

  • requestid: int
  • response: String

说明:

TODO

public void stop() @ L136

  • 方法名:stop
  • 源码定位:L136
  • 返回类型:void
  • 修饰符:public

参数:

说明:

TODO

private void closeSocket() @ L143

  • 方法名:closeSocket
  • 源码定位:L143
  • 返回类型:void
  • 修饰符:private

参数:

说明:

TODO

代码

public class RconClient extends GenericThread {
    private static final Logger LOGGER = LogUtils.getLogger();
    private static final int SERVERDATA_AUTH = 3;
    private static final int SERVERDATA_EXECCOMMAND = 2;
    private static final int SERVERDATA_RESPONSE_VALUE = 0;
    private static final int SERVERDATA_AUTH_RESPONSE = 2;
    private static final int SERVERDATA_AUTH_FAILURE = -1;
    private boolean authed;
    private final Socket client;
    private final byte[] buf = new byte[1460];
    private final String rconPassword;
    private final ServerInterface serverInterface;
 
    RconClient(ServerInterface serverInterface, String rconPassword, Socket socket) {
        super("RCON Client " + socket.getInetAddress());
        this.serverInterface = serverInterface;
        this.client = socket;
 
        try {
            this.client.setSoTimeout(0);
        } catch (Exception var5) {
            this.running = false;
        }
 
        this.rconPassword = rconPassword;
    }
 
    @Override
    public void run() {
        try {
            try {
                while (this.running) {
                    BufferedInputStream inputStream = new BufferedInputStream(this.client.getInputStream());
                    int read = inputStream.read(this.buf, 0, 1460);
                    if (10 > read) {
                        return;
                    }
 
                    int offset = 0;
                    int pktsize = PktUtils.intFromByteArray(this.buf, 0, read);
                    if (pktsize != read - 4) {
                        return;
                    }
 
                    offset += 4;
                    int requestid = PktUtils.intFromByteArray(this.buf, offset, read);
                    offset += 4;
                    int cmd = PktUtils.intFromByteArray(this.buf, offset);
                    offset += 4;
                    switch (cmd) {
                        case 2:
                            if (this.authed) {
                                String command = PktUtils.stringFromByteArray(this.buf, offset, read);
 
                                try {
                                    this.sendCmdResponse(requestid, this.serverInterface.runCommand(command));
                                } catch (Exception var15) {
                                    this.sendCmdResponse(requestid, "Error executing: " + command + " (" + var15.getMessage() + ")");
                                }
                                break;
                            }
 
                            this.sendAuthFailure();
                            break;
                        case 3:
                            String password = PktUtils.stringFromByteArray(this.buf, offset, read);
                            offset += password.length();
                            if (!password.isEmpty() && password.equals(this.rconPassword)) {
                                this.authed = true;
                                this.send(requestid, 2, "");
                                break;
                            }
 
                            this.authed = false;
                            this.sendAuthFailure();
                            break;
                        default:
                            this.sendCmdResponse(requestid, String.format(Locale.ROOT, "Unknown request %s", Integer.toHexString(cmd)));
                    }
                }
 
                return;
            } catch (IOException var16) {
            } catch (Exception var17) {
                LOGGER.error("Exception whilst parsing RCON input", (Throwable)var17);
            }
        } finally {
            this.closeSocket();
            LOGGER.info("Thread {} shutting down", this.name);
            this.running = false;
        }
    }
 
    private void send(int requestid, int cmd, String str) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1248);
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
        byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
        dataOutputStream.writeInt(Integer.reverseBytes(bytes.length + 10));
        dataOutputStream.writeInt(Integer.reverseBytes(requestid));
        dataOutputStream.writeInt(Integer.reverseBytes(cmd));
        dataOutputStream.write(bytes);
        dataOutputStream.write(0);
        dataOutputStream.write(0);
        this.client.getOutputStream().write(outputStream.toByteArray());
    }
 
    private void sendAuthFailure() throws IOException {
        this.send(-1, 2, "");
    }
 
    private void sendCmdResponse(int requestid, String response) throws IOException {
        int len = response.length();
 
        do {
            int dataLen = 4096 <= len ? 4096 : len;
            this.send(requestid, 0, response.substring(0, dataLen));
            response = response.substring(dataLen);
            len = response.length();
        } while (0 != len);
    }
 
    @Override
    public void stop() {
        this.running = false;
        this.closeSocket();
        super.stop();
    }
 
    private void closeSocket() {
        try {
            this.client.close();
        } catch (IOException var2) {
            LOGGER.warn("Failed to close socket", (Throwable)var2);
        }
    }
}

引用的其他类

  • ServerInterface

    • 引用位置: 参数/字段
  • PktUtils

    • 引用位置: 方法调用
    • 关联成员: PktUtils.intFromByteArray(), PktUtils.stringFromByteArray()
  • GenericThread

    • 引用位置: 继承