package net.minecraft.server.rcon.thread;

import org.apache.logging.log4j.LogManager;
import java.util.Iterator;
import java.net.InetAddress;
import java.net.Socket;
import java.io.IOException;
import java.net.SocketTimeoutException;
import net.minecraft.server.dedicated.DedicatedServerProperties;
import com.google.common.collect.Lists;
import net.minecraft.server.ServerInterface;
import java.util.List;
import java.net.ServerSocket;
import org.apache.logging.log4j.Logger;

public class RconThread extends GenericThread {
    private static final Logger LOGGER;
    private final int port;
    private String serverIp;
    private ServerSocket socket;
    private final String rconPassword;
    private final List<RconClient> clients;
    private final ServerInterface serverInterface;
    
    public RconThread(final ServerInterface uv) {
        super("RCON Listener");
        this.clients = Lists.newArrayList();
        this.serverInterface = uv;
        final DedicatedServerProperties ye3 = uv.getProperties();
        this.port = ye3.rconPort;
        this.rconPassword = ye3.rconPassword;
        this.serverIp = uv.getServerIp();
        if (this.serverIp.isEmpty()) {
            this.serverIp = "0.0.0.0";
        }
    }
    
    private void clearClients() {
        this.clients.removeIf(acf -> !acf.isRunning());
    }
    
    @Override
    public void run() {
        RconThread.LOGGER.info("RCON running on {}:{}", this.serverIp, this.port);
        try {
            while (this.running) {
                try {
                    final Socket socket2 = this.socket.accept();
                    final RconClient acf3 = new RconClient(this.serverInterface, this.rconPassword, socket2);
                    acf3.start();
                    this.clients.add(acf3);
                    this.clearClients();
                }
                catch (SocketTimeoutException socketTimeoutException2) {
                    this.clearClients();
                }
                catch (IOException iOException2) {
                    if (!this.running) {
                        continue;
                    }
                    RconThread.LOGGER.info("IO exception: ", (Throwable)iOException2);
                }
            }
        }
        finally {
            this.closeSocket(this.socket);
        }
    }
    
    @Override
    public void start() {
        if (this.rconPassword.isEmpty()) {
            RconThread.LOGGER.warn("No rcon password set in server.properties, rcon disabled!");
            return;
        }
        if (0 >= this.port || 65535 < this.port) {
            RconThread.LOGGER.warn("Invalid rcon port {} found in server.properties, rcon disabled!", this.port);
            return;
        }
        if (this.running) {
            return;
        }
        try {
            (this.socket = new ServerSocket(this.port, 0, InetAddress.getByName(this.serverIp))).setSoTimeout(500);
            super.start();
        }
        catch (IOException iOException2) {
            RconThread.LOGGER.warn("Unable to initialise rcon on {}:{}", this.serverIp, this.port, iOException2);
        }
    }
    
    @Override
    public void stop() {
        this.running = false;
        this.closeSocket(this.socket);
        super.stop();
        for (final RconClient acf3 : this.clients) {
            if (acf3.isRunning()) {
                acf3.stop();
            }
        }
        this.clients.clear();
    }
    
    private void closeSocket(final ServerSocket serverSocket) {
        RconThread.LOGGER.debug("closeSocket: {}", serverSocket);
        try {
            serverSocket.close();
        }
        catch (IOException iOException3) {
            RconThread.LOGGER.warn("Failed to close socket", (Throwable)iOException3);
        }
    }
    
    static {
        LOGGER = LogManager.getLogger();
    }
}
