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() != 47)
097 {
098 if (par1Packet2ClientProtocol.getProtocolVersion() > 47)
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(47), 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 }