001package net.minecraft.server;
002
003import cpw.mods.fml.common.FMLLog;
004import cpw.mods.fml.relauncher.Side;
005import cpw.mods.fml.relauncher.SideOnly;
006import java.io.IOException;
007import java.net.InetAddress;
008import java.net.ServerSocket;
009import java.net.Socket;
010import java.util.ArrayList;
011import java.util.Collections;
012import java.util.HashMap;
013import java.util.List;
014import java.util.logging.Level;
015
016import net.minecraft.network.NetLoginHandler;
017import net.minecraft.network.NetworkListenThread;
018
019public class ServerListenThread extends Thread
020{
021    private final List pendingConnections = Collections.synchronizedList(new ArrayList());
022
023    /**
024     * This map stores a list of InetAddresses and the last time which they connected at
025     */
026    private final HashMap recentConnections = new HashMap();
027    private int connectionCounter = 0;
028    private final ServerSocket myServerSocket;
029    private NetworkListenThread myNetworkListenThread;
030    private final InetAddress myServerAddress;
031    private final int myPort;
032
033    public ServerListenThread(NetworkListenThread par1NetworkListenThread, InetAddress par2InetAddress, int par3) throws IOException
034    {
035        super("Listen thread");
036        this.myNetworkListenThread = par1NetworkListenThread;
037        this.myPort = par3;
038        this.myServerSocket = new ServerSocket(par3, 0, par2InetAddress);
039        this.myServerAddress = par2InetAddress == null ? this.myServerSocket.getInetAddress() : par2InetAddress;
040        this.myServerSocket.setPerformancePreferences(0, 2, 1);
041    }
042
043    public void processPendingConnections()
044    {
045        List list = this.pendingConnections;
046
047        synchronized (this.pendingConnections)
048        {
049            for (int i = 0; i < this.pendingConnections.size(); ++i)
050            {
051                NetLoginHandler netloginhandler = (NetLoginHandler)this.pendingConnections.get(i);
052
053                try
054                {
055                    netloginhandler.tryLogin();
056                }
057                catch (Exception exception)
058                {
059                    netloginhandler.raiseErrorAndDisconnect("Internal server error");
060                    FMLLog.log(Level.SEVERE, exception, "Error handling login related packet - connection from %s refused", netloginhandler.getUsernameAndAddress());
061                    this.myNetworkListenThread.getServer().func_98033_al().func_98235_b("Failed to handle packet for " + netloginhandler.getUsernameAndAddress() + ": " + exception, exception);
062                }
063
064                if (netloginhandler.connectionComplete)
065                {
066                    this.pendingConnections.remove(i--);
067                }
068
069                netloginhandler.myTCPConnection.wakeThreads();
070            }
071        }
072    }
073
074    public void run()
075    {
076        while (this.myNetworkListenThread.isListening)
077        {
078            try
079            {
080                Socket socket = this.myServerSocket.accept();
081                InetAddress inetaddress = socket.getInetAddress();
082                long i = System.currentTimeMillis();
083                HashMap hashmap = this.recentConnections;
084
085                synchronized (this.recentConnections)
086                {
087                    if (this.recentConnections.containsKey(inetaddress) && !isLocalHost(inetaddress) && i - ((Long)this.recentConnections.get(inetaddress)).longValue() < 4000L)
088                    {
089                        this.recentConnections.put(inetaddress, Long.valueOf(i));
090                        socket.close();
091                        continue;
092                    }
093
094                    this.recentConnections.put(inetaddress, Long.valueOf(i));
095                }
096
097                NetLoginHandler netloginhandler = new NetLoginHandler(this.myNetworkListenThread.getServer(), socket, "Connection #" + this.connectionCounter++);
098                this.addPendingConnection(netloginhandler);
099            }
100            catch (IOException ioexception)
101            {
102                ioexception.printStackTrace();
103            }
104        }
105
106        this.myNetworkListenThread.getServer().func_98033_al().func_98233_a("Closing listening thread");
107    }
108
109    private void addPendingConnection(NetLoginHandler par1NetLoginHandler)
110    {
111        if (par1NetLoginHandler == null)
112        {
113            throw new IllegalArgumentException("Got null pendingconnection!");
114        }
115        else
116        {
117            List list = this.pendingConnections;
118
119            synchronized (this.pendingConnections)
120            {
121                this.pendingConnections.add(par1NetLoginHandler);
122            }
123        }
124    }
125
126    private static boolean isLocalHost(InetAddress par0InetAddress)
127    {
128        return "127.0.0.1".equals(par0InetAddress.getHostAddress());
129    }
130
131    public void func_71769_a(InetAddress par1InetAddress)
132    {
133        if (par1InetAddress != null)
134        {
135            HashMap hashmap = this.recentConnections;
136
137            synchronized (this.recentConnections)
138            {
139                this.recentConnections.remove(par1InetAddress);
140            }
141        }
142    }
143
144    public void func_71768_b()
145    {
146        try
147        {
148            this.myServerSocket.close();
149        }
150        catch (Throwable throwable)
151        {
152            ;
153        }
154    }
155
156    @SideOnly(Side.CLIENT)
157    public InetAddress getInetAddress()
158    {
159        return this.myServerAddress;
160    }
161
162    @SideOnly(Side.CLIENT)
163    public int getMyPort()
164    {
165        return this.myPort;
166    }
167}