001 package net.minecraft.src;
002
003 import java.io.IOException;
004 import java.net.InetAddress;
005 import java.net.Socket;
006 import java.security.PrivateKey;
007 import java.security.PublicKey;
008 import java.util.Arrays;
009 import java.util.Random;
010 import java.util.logging.Logger;
011 import javax.crypto.SecretKey;
012
013 import cpw.mods.fml.common.network.FMLNetworkHandler;
014 import net.minecraft.server.MinecraftServer;
015
016 public class NetLoginHandler extends NetHandler
017 {
018 private byte[] field_72536_d;
019
020 /** The Minecraft logger. */
021 public static Logger logger = Logger.getLogger("Minecraft");
022
023 /** The Random object used to generate serverId hex strings. */
024 private static Random rand = new Random();
025 public TcpConnection myTCPConnection;
026 public boolean connectionComplete = false;
027
028 /** Reference to the MinecraftServer object. */
029 private MinecraftServer mcServer;
030 private int connectionTimer = 0;
031 public String clientUsername = null;
032 private volatile boolean field_72544_i = false;
033
034 /** server ID that is randomly generated by this login handler. */
035 private String loginServerId = "";
036 private SecretKey field_72542_k = null;
037
038 public NetLoginHandler(MinecraftServer par1MinecraftServer, Socket par2Socket, String par3Str) throws IOException
039 {
040 this.mcServer = par1MinecraftServer;
041 this.myTCPConnection = new TcpConnection(par2Socket, par3Str, this, par1MinecraftServer.getKeyPair().getPrivate());
042 this.myTCPConnection.field_74468_e = 0;
043 }
044
045 /**
046 * Logs the user in if a login packet is found, otherwise keeps processing network packets unless the timeout has
047 * occurred.
048 */
049 public void tryLogin()
050 {
051 if (this.field_72544_i)
052 {
053 this.initializePlayerConnection();
054 }
055
056 if (this.connectionTimer++ == 6000)
057 {
058 this.raiseErrorAndDisconnect("Took too long to log in");
059 }
060 else
061 {
062 this.myTCPConnection.processReadPackets();
063 }
064 }
065
066 public void raiseErrorAndDisconnect(String par1Str)
067 {
068 try
069 {
070 logger.info("Disconnecting " + this.getUsernameAndAddress() + ": " + par1Str);
071 this.myTCPConnection.addToSendQueue(new Packet255KickDisconnect(par1Str));
072 this.myTCPConnection.serverShutdown();
073 this.connectionComplete = true;
074 }
075 catch (Exception var3)
076 {
077 var3.printStackTrace();
078 }
079 }
080
081 public void handleClientProtocol(Packet2ClientProtocol par1Packet2ClientProtocol)
082 {
083 this.clientUsername = par1Packet2ClientProtocol.getUsername();
084
085 if (!this.clientUsername.equals(StringUtils.stripControlCodes(this.clientUsername)))
086 {
087 this.raiseErrorAndDisconnect("Invalid username!");
088 }
089 else
090 {
091 PublicKey var2 = this.mcServer.getKeyPair().getPublic();
092
093 if (par1Packet2ClientProtocol.getProtocolVersion() != 39)
094 {
095 if (par1Packet2ClientProtocol.getProtocolVersion() > 39)
096 {
097 this.raiseErrorAndDisconnect("Outdated server!");
098 }
099 else
100 {
101 this.raiseErrorAndDisconnect("Outdated client!");
102 }
103 }
104 else
105 {
106 this.loginServerId = this.mcServer.isServerInOnlineMode() ? Long.toString(rand.nextLong(), 16) : "-";
107 this.field_72536_d = new byte[4];
108 rand.nextBytes(this.field_72536_d);
109 this.myTCPConnection.addToSendQueue(new Packet253ServerAuthData(this.loginServerId, var2, this.field_72536_d));
110 }
111 }
112 }
113
114 public void handleSharedKey(Packet252SharedKey par1Packet252SharedKey)
115 {
116 PrivateKey var2 = this.mcServer.getKeyPair().getPrivate();
117 this.field_72542_k = par1Packet252SharedKey.func_73303_a(var2);
118
119 if (!Arrays.equals(this.field_72536_d, par1Packet252SharedKey.func_73302_b(var2)))
120 {
121 this.raiseErrorAndDisconnect("Invalid client reply");
122 }
123
124 this.myTCPConnection.addToSendQueue(new Packet252SharedKey());
125 }
126
127 public void handleClientCommand(Packet205ClientCommand par1Packet205ClientCommand)
128 {
129 if (par1Packet205ClientCommand.forceRespawn == 0)
130 {
131 if (this.mcServer.isServerInOnlineMode())
132 {
133 (new ThreadLoginVerifier(this)).start();
134 }
135 else
136 {
137 this.field_72544_i = true;
138 }
139 }
140 }
141
142 public void handleLogin(Packet1Login par1Packet1Login) {
143 FMLNetworkHandler.handleLoginPacketOnServer(this, par1Packet1Login);
144 }
145
146 /**
147 * on success the specified username is connected to the minecraftInstance, otherwise they are packet255'd
148 */
149 public void initializePlayerConnection()
150 {
151 FMLNetworkHandler.onConnectionReceivedFromClient(this, this.mcServer, this.myTCPConnection.getSocketAddress(), this.clientUsername);
152 }
153
154 public void completeConnection(String var1)
155 {
156 if (var1 != null)
157 {
158 this.raiseErrorAndDisconnect(var1);
159 }
160 else
161 {
162 EntityPlayerMP var2 = this.mcServer.getConfigurationManager().createPlayerForUser(this.clientUsername);
163
164 if (var2 != null)
165 {
166 this.mcServer.getConfigurationManager().initializeConnectionToPlayer(this.myTCPConnection, var2);
167 }
168 }
169
170 this.connectionComplete = true;
171 }
172
173 public void handleErrorMessage(String par1Str, Object[] par2ArrayOfObj)
174 {
175 logger.info(this.getUsernameAndAddress() + " lost connection");
176 this.connectionComplete = true;
177 }
178
179 /**
180 * Handle a server ping packet.
181 */
182 public void handleServerPing(Packet254ServerPing par1Packet254ServerPing)
183 {
184 try
185 {
186 String var2 = this.mcServer.getMOTD() + "\u00a7" + this.mcServer.getConfigurationManager().getCurrentPlayerCount() + "\u00a7" + this.mcServer.getConfigurationManager().getMaxPlayers();
187 InetAddress var3 = null;
188
189 if (this.myTCPConnection.getSocket() != null)
190 {
191 var3 = this.myTCPConnection.getSocket().getInetAddress();
192 }
193
194 this.myTCPConnection.addToSendQueue(new Packet255KickDisconnect(var2));
195 this.myTCPConnection.serverShutdown();
196
197 if (var3 != null && this.mcServer.getNetworkThread() instanceof DedicatedServerListenThread)
198 {
199 ((DedicatedServerListenThread)this.mcServer.getNetworkThread()).func_71761_a(var3);
200 }
201
202 this.connectionComplete = true;
203 }
204 catch (Exception var4)
205 {
206 var4.printStackTrace();
207 }
208 }
209
210 /**
211 * Default handler called for packets that don't have their own handlers in NetClientHandler; currentlly does
212 * nothing.
213 */
214 public void unexpectedPacket(Packet par1Packet)
215 {
216 this.raiseErrorAndDisconnect("Protocol error");
217 }
218
219 public String getUsernameAndAddress()
220 {
221 return this.clientUsername != null ? this.clientUsername + " [" + this.myTCPConnection.getSocketAddress().toString() + "]" : this.myTCPConnection.getSocketAddress().toString();
222 }
223
224 /**
225 * determine if it is a server handler
226 */
227 public boolean isServerHandler()
228 {
229 return true;
230 }
231
232 /**
233 * Returns the server Id randomly generated by this login handler.
234 */
235 static String getServerId(NetLoginHandler par0NetLoginHandler)
236 {
237 return par0NetLoginHandler.loginServerId;
238 }
239
240 /**
241 * Returns the reference to Minecraft Server.
242 */
243 static MinecraftServer getLoginMinecraftServer(NetLoginHandler par0NetLoginHandler)
244 {
245 return par0NetLoginHandler.mcServer;
246 }
247
248 static SecretKey func_72525_c(NetLoginHandler par0NetLoginHandler)
249 {
250 return par0NetLoginHandler.field_72542_k;
251 }
252
253 /**
254 * Returns the connecting client username.
255 */
256 static String getClientUsername(NetLoginHandler par0NetLoginHandler)
257 {
258 return par0NetLoginHandler.clientUsername;
259 }
260
261 public static boolean func_72531_a(NetLoginHandler par0NetLoginHandler, boolean par1)
262 {
263 return par0NetLoginHandler.field_72544_i = par1;
264 }
265
266 public void handleCustomPayload(Packet250CustomPayload par1Packet250CustomPayload)
267 {
268 FMLNetworkHandler.handlePacket250Packet(par1Packet250CustomPayload, myTCPConnection, this);
269 }
270
271 @Override
272 public void handleVanilla250Packet(Packet250CustomPayload payload)
273 {
274 // NOOP for login
275 }
276
277 public EntityPlayer getPlayer()
278 {
279 return null;
280 };
281 }