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