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 }