    001package net.minecraft.network.rcon;
    002
    003import java.io.IOException;
    004import java.net.InetAddress;
    005import java.net.ServerSocket;
    006import java.net.Socket;
    007import java.net.SocketTimeoutException;
    008import java.util.HashMap;
    009import java.util.Iterator;
    010import java.util.Map;
    011import java.util.Map.Entry;
    012
    013public class RConThreadMain extends RConThreadBase
    014{
    015    /** Port RCon is running on */
    016    private int rconPort;
    017
    018    /** Port the server is running on */
    019    private int serverPort;
    020
    021    /** Hostname RCon is running on */
    022    private String hostname;
    023
    024    /** The RCon ServerSocket. */
    025    private ServerSocket serverSocket = null;
    026
    027    /** The RCon password */
    028    private String rconPassword;
    029
    030    /** A map of client addresses to their running Threads */
    031    private Map clientThreads;
    032
    033    public RConThreadMain(IServer par1IServer)
    034    {
    035        super(par1IServer);
    036        this.rconPort = par1IServer.getIntProperty("rcon.port", 0);
    037        this.rconPassword = par1IServer.getStringProperty("rcon.password", "");
    038        this.hostname = par1IServer.getHostname();
    039        this.serverPort = par1IServer.getPort();
    040
    041        if (0 == this.rconPort)
    042        {
    043            this.rconPort = this.serverPort + 10;
    044            this.logInfo("Setting default rcon port to " + this.rconPort);
    045            par1IServer.setProperty("rcon.port", Integer.valueOf(this.rconPort));
    046
    047            if (0 == this.rconPassword.length())
    048            {
    049                par1IServer.setProperty("rcon.password", "");
    050            }
    051
    052            par1IServer.saveProperties();
    053        }
    054
    055        if (0 == this.hostname.length())
    056        {
    057            this.hostname = "0.0.0.0";
    058        }
    059
    060        this.initClientThreadList();
    061        this.serverSocket = null;
    062    }
    063
    064    private void initClientThreadList()
    065    {
    066        this.clientThreads = new HashMap();
    067    }
    068
    069    /**
    070     * Cleans up the clientThreads map by removing client Threads that are not running
    071     */
    072    private void cleanClientThreadsMap()
    073    {
    074        Iterator iterator = this.clientThreads.entrySet().iterator();
    075
    076        while (iterator.hasNext())
    077        {
    078            Entry entry = (Entry)iterator.next();
    079
    080            if (!((RConThreadClient)entry.getValue()).isRunning())
    081            {
    082                iterator.remove();
    083            }
    084        }
    085    }
    086
    087    public void run()
    088    {
    089        this.logInfo("RCON running on " + this.hostname + ":" + this.rconPort);
    090
    091        try
    092        {
    093            while (this.running)
    094            {
    095                try
    096                {
    097                    Socket socket = this.serverSocket.accept();
    098                    socket.setSoTimeout(500);
    099                    RConThreadClient rconthreadclient = new RConThreadClient(this.server, socket);
    100                    rconthreadclient.startThread();
    101                    this.clientThreads.put(socket.getRemoteSocketAddress(), rconthreadclient);
    102                    this.cleanClientThreadsMap();
    103                }
    104                catch (SocketTimeoutException sockettimeoutexception)
    105                {
    106                    this.cleanClientThreadsMap();
    107                }
    108                catch (IOException ioexception)
    109                {
    110                    if (this.running)
    111                    {
    112                        this.logInfo("IO: " + ioexception.getMessage());
    113                    }
    114                }
    115            }
    116        }
    117        finally
    118        {
    119            this.closeServerSocket(this.serverSocket);
    120        }
    121    }
    122
    123    /**
    124     * Creates a new Thread object from this class and starts running
    125     */
    126    public void startThread()
    127    {
    128        if (0 == this.rconPassword.length())
    129        {
    130            this.logWarning("No rcon password set in \'" + this.server.getSettingsFilename() + "\', rcon disabled!");
    131        }
    132        else if (0 < this.rconPort && 65535 >= this.rconPort)
    133        {
    134            if (!this.running)
    135            {
    136                try
    137                {
    138                    this.serverSocket = new ServerSocket(this.rconPort, 0, InetAddress.getByName(this.hostname));
    139                    this.serverSocket.setSoTimeout(500);
    140                    super.startThread();
    141                }
    142                catch (IOException ioexception)
    143                {
    144                    this.logWarning("Unable to initialise rcon on " + this.hostname + ":" + this.rconPort + " : " + ioexception.getMessage());
    145                }
    146            }
    147        }
    148        else
    149        {
    150            this.logWarning("Invalid rcon port " + this.rconPort + " found in \'" + this.server.getSettingsFilename() + "\', rcon disabled!");
    151        }
    152    }
    153}