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