2
0

LoginServerThread.java 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. /*
  2. * Copyright (C) 2004-2015 L2J Server
  3. *
  4. * This file is part of L2J Server.
  5. *
  6. * L2J Server is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * L2J Server is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.l2jserver.gameserver;
  20. import java.io.BufferedOutputStream;
  21. import java.io.IOException;
  22. import java.io.InputStream;
  23. import java.io.OutputStream;
  24. import java.math.BigInteger;
  25. import java.net.Socket;
  26. import java.net.SocketException;
  27. import java.net.UnknownHostException;
  28. import java.security.GeneralSecurityException;
  29. import java.security.KeyFactory;
  30. import java.security.interfaces.RSAPublicKey;
  31. import java.security.spec.RSAKeyGenParameterSpec;
  32. import java.security.spec.RSAPublicKeySpec;
  33. import java.sql.Connection;
  34. import java.sql.PreparedStatement;
  35. import java.sql.ResultSet;
  36. import java.sql.SQLException;
  37. import java.util.ArrayList;
  38. import java.util.List;
  39. import java.util.Map;
  40. import java.util.concurrent.ConcurrentHashMap;
  41. import java.util.concurrent.CopyOnWriteArrayList;
  42. import org.slf4j.Logger;
  43. import org.slf4j.LoggerFactory;
  44. import com.l2jserver.Config;
  45. import com.l2jserver.commons.database.pool.impl.ConnectionFactory;
  46. import com.l2jserver.gameserver.model.L2World;
  47. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  48. import com.l2jserver.gameserver.network.L2GameClient;
  49. import com.l2jserver.gameserver.network.L2GameClient.GameClientState;
  50. import com.l2jserver.gameserver.network.SystemMessageId;
  51. import com.l2jserver.gameserver.network.gameserverpackets.AuthRequest;
  52. import com.l2jserver.gameserver.network.gameserverpackets.BlowFishKey;
  53. import com.l2jserver.gameserver.network.gameserverpackets.ChangeAccessLevel;
  54. import com.l2jserver.gameserver.network.gameserverpackets.ChangePassword;
  55. import com.l2jserver.gameserver.network.gameserverpackets.PlayerAuthRequest;
  56. import com.l2jserver.gameserver.network.gameserverpackets.PlayerInGame;
  57. import com.l2jserver.gameserver.network.gameserverpackets.PlayerLogout;
  58. import com.l2jserver.gameserver.network.gameserverpackets.PlayerTracert;
  59. import com.l2jserver.gameserver.network.gameserverpackets.ReplyCharacters;
  60. import com.l2jserver.gameserver.network.gameserverpackets.SendMail;
  61. import com.l2jserver.gameserver.network.gameserverpackets.ServerStatus;
  62. import com.l2jserver.gameserver.network.gameserverpackets.TempBan;
  63. import com.l2jserver.gameserver.network.loginserverpackets.AuthResponse;
  64. import com.l2jserver.gameserver.network.loginserverpackets.ChangePasswordResponse;
  65. import com.l2jserver.gameserver.network.loginserverpackets.InitLS;
  66. import com.l2jserver.gameserver.network.loginserverpackets.KickPlayer;
  67. import com.l2jserver.gameserver.network.loginserverpackets.LoginServerFail;
  68. import com.l2jserver.gameserver.network.loginserverpackets.PlayerAuthResponse;
  69. import com.l2jserver.gameserver.network.loginserverpackets.RequestCharacters;
  70. import com.l2jserver.gameserver.network.serverpackets.CharSelectionInfo;
  71. import com.l2jserver.gameserver.network.serverpackets.LoginFail;
  72. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  73. import com.l2jserver.util.Rnd;
  74. import com.l2jserver.util.Util;
  75. import com.l2jserver.util.crypt.NewCrypt;
  76. import com.l2jserver.util.network.BaseSendablePacket;
  77. public class LoginServerThread extends Thread
  78. {
  79. protected static final Logger _log = LoggerFactory.getLogger(LoginServerThread.class);
  80. protected static final Logger _logAccounting = LoggerFactory.getLogger("accounting");
  81. /** @see com.l2jserver.loginserver.L2LoginServer#PROTOCOL_REV */
  82. private static final int REVISION = 0x0106;
  83. private final String _hostname;
  84. private final int _port;
  85. private final int _gamePort;
  86. private Socket _loginSocket;
  87. private OutputStream _out;
  88. /**
  89. * The BlowFish engine used to encrypt packets<br>
  90. * It is first initialized with a unified key:<br>
  91. * "_;v.]05-31!|+-%xT!^[$\00"<br>
  92. * <br>
  93. * and then after handshake, with a new key sent by<br>
  94. * login server during the handshake. This new key is stored<br>
  95. * in blowfishKey
  96. */
  97. private NewCrypt _blowfish;
  98. private byte[] _hexID;
  99. private final boolean _acceptAlternate;
  100. private int _requestID;
  101. private final boolean _reserveHost;
  102. private int _maxPlayer;
  103. private final List<WaitingClient> _waitingClients;
  104. private final Map<String, L2GameClient> _accountsInGameServer = new ConcurrentHashMap<>();
  105. private int _status;
  106. private String _serverName;
  107. private final List<String> _subnets;
  108. private final List<String> _hosts;
  109. /**
  110. * Instantiates a new login server thread.
  111. */
  112. protected LoginServerThread()
  113. {
  114. super("LoginServerThread");
  115. _port = Config.GAME_SERVER_LOGIN_PORT;
  116. _gamePort = Config.PORT_GAME;
  117. _hostname = Config.GAME_SERVER_LOGIN_HOST;
  118. _hexID = Config.HEX_ID;
  119. if (_hexID == null)
  120. {
  121. _requestID = Config.REQUEST_ID;
  122. _hexID = Util.generateHex(16);
  123. }
  124. else
  125. {
  126. _requestID = Config.SERVER_ID;
  127. }
  128. _acceptAlternate = Config.ACCEPT_ALTERNATE_ID;
  129. _reserveHost = Config.RESERVE_HOST_ON_LOGIN;
  130. _subnets = Config.GAME_SERVER_SUBNETS;
  131. _hosts = Config.GAME_SERVER_HOSTS;
  132. _waitingClients = new CopyOnWriteArrayList<>();
  133. _maxPlayer = Config.MAXIMUM_ONLINE_USERS;
  134. }
  135. @Override
  136. public void run()
  137. {
  138. while (!isInterrupted())
  139. {
  140. int lengthHi = 0;
  141. int lengthLo = 0;
  142. int length = 0;
  143. boolean checksumOk = false;
  144. try
  145. {
  146. // Connection
  147. _log.info("Connecting to login on {}:{}", _hostname, _port);
  148. _loginSocket = new Socket(_hostname, _port);
  149. InputStream in = _loginSocket.getInputStream();
  150. _out = new BufferedOutputStream(_loginSocket.getOutputStream());
  151. // init Blowfish
  152. byte[] blowfishKey = Util.generateHex(40);
  153. // Protect the new blowfish key what cannot begin with zero
  154. if (blowfishKey[0] == 0)
  155. {
  156. blowfishKey[0] = (byte) Rnd.get(32, 64);
  157. }
  158. _blowfish = new NewCrypt("_;v.]05-31!|+-%xT!^[$\00");
  159. while (!isInterrupted())
  160. {
  161. lengthLo = in.read();
  162. lengthHi = in.read();
  163. length = (lengthHi * 256) + lengthLo;
  164. if (lengthHi < 0)
  165. {
  166. _log.info("LoginServerThread: Login terminated the connection.");
  167. break;
  168. }
  169. byte[] incoming = new byte[length - 2];
  170. int receivedBytes = 0;
  171. int newBytes = 0;
  172. int left = length - 2;
  173. while ((newBytes != -1) && (receivedBytes < (length - 2)))
  174. {
  175. newBytes = in.read(incoming, receivedBytes, left);
  176. receivedBytes = receivedBytes + newBytes;
  177. left -= newBytes;
  178. }
  179. if (receivedBytes != (length - 2))
  180. {
  181. _log.warn("Incomplete Packet is sent to the server, closing connection.(LS)");
  182. break;
  183. }
  184. // decrypt if we have a key
  185. _blowfish.decrypt(incoming, 0, incoming.length);
  186. checksumOk = NewCrypt.verifyChecksum(incoming);
  187. if (!checksumOk)
  188. {
  189. _log.warn("Incorrect packet checksum, ignoring packet (LS)");
  190. break;
  191. }
  192. int packetType = incoming[0] & 0xff;
  193. switch (packetType)
  194. {
  195. case 0x00:
  196. InitLS init = new InitLS(incoming);
  197. if (init.getRevision() != REVISION)
  198. {
  199. // TODO: revision mismatch
  200. _log.warn("/!\\ Revision mismatch between LS and GS /!\\");
  201. break;
  202. }
  203. RSAPublicKey publicKey;
  204. try
  205. {
  206. KeyFactory kfac = KeyFactory.getInstance("RSA");
  207. BigInteger modulus = new BigInteger(init.getRSAKey());
  208. RSAPublicKeySpec kspec1 = new RSAPublicKeySpec(modulus, RSAKeyGenParameterSpec.F4);
  209. publicKey = (RSAPublicKey) kfac.generatePublic(kspec1);
  210. }
  211. catch (GeneralSecurityException e)
  212. {
  213. _log.warn("Trouble while init the public key send by login");
  214. break;
  215. }
  216. // send the blowfish key through the rsa encryption
  217. sendPacket(new BlowFishKey(blowfishKey, publicKey));
  218. // now, only accept packet with the new encryption
  219. _blowfish = new NewCrypt(blowfishKey);
  220. sendPacket(new AuthRequest(_requestID, _acceptAlternate, _hexID, _gamePort, _reserveHost, _maxPlayer, _subnets, _hosts));
  221. break;
  222. case 0x01:
  223. LoginServerFail lsf = new LoginServerFail(incoming);
  224. _log.info("Damn! Registeration Failed: {}", lsf.getReasonString());
  225. // login will close the connection here
  226. break;
  227. case 0x02:
  228. AuthResponse aresp = new AuthResponse(incoming);
  229. int serverID = aresp.getServerId();
  230. _serverName = aresp.getServerName();
  231. Config.saveHexid(serverID, hexToString(_hexID));
  232. _log.info("Registered on login as Server {}: {}", serverID, _serverName);
  233. ServerStatus st = new ServerStatus();
  234. if (Config.SERVER_LIST_BRACKET)
  235. {
  236. st.addAttribute(ServerStatus.SERVER_LIST_SQUARE_BRACKET, ServerStatus.ON);
  237. }
  238. else
  239. {
  240. st.addAttribute(ServerStatus.SERVER_LIST_SQUARE_BRACKET, ServerStatus.OFF);
  241. }
  242. st.addAttribute(ServerStatus.SERVER_TYPE, Config.SERVER_LIST_TYPE);
  243. if (Config.SERVER_GMONLY)
  244. {
  245. st.addAttribute(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_GM_ONLY);
  246. }
  247. else
  248. {
  249. st.addAttribute(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_AUTO);
  250. }
  251. if (Config.SERVER_LIST_AGE == 15)
  252. {
  253. st.addAttribute(ServerStatus.SERVER_AGE, ServerStatus.SERVER_AGE_15);
  254. }
  255. else if (Config.SERVER_LIST_AGE == 18)
  256. {
  257. st.addAttribute(ServerStatus.SERVER_AGE, ServerStatus.SERVER_AGE_18);
  258. }
  259. else
  260. {
  261. st.addAttribute(ServerStatus.SERVER_AGE, ServerStatus.SERVER_AGE_ALL);
  262. }
  263. sendPacket(st);
  264. if (L2World.getInstance().getAllPlayersCount() > 0)
  265. {
  266. final List<String> playerList = new ArrayList<>();
  267. for (L2PcInstance player : L2World.getInstance().getPlayers())
  268. {
  269. playerList.add(player.getAccountName());
  270. }
  271. sendPacket(new PlayerInGame(playerList));
  272. }
  273. break;
  274. case 0x03:
  275. PlayerAuthResponse par = new PlayerAuthResponse(incoming);
  276. String account = par.getAccount();
  277. WaitingClient wcToRemove = null;
  278. synchronized (_waitingClients)
  279. {
  280. for (WaitingClient wc : _waitingClients)
  281. {
  282. if (wc.account.equals(account))
  283. {
  284. wcToRemove = wc;
  285. }
  286. }
  287. }
  288. if (wcToRemove != null)
  289. {
  290. if (par.isAuthed())
  291. {
  292. PlayerInGame pig = new PlayerInGame(par.getAccount());
  293. sendPacket(pig);
  294. wcToRemove.gameClient.setState(GameClientState.AUTHED);
  295. wcToRemove.gameClient.setSessionId(wcToRemove.session);
  296. CharSelectionInfo cl = new CharSelectionInfo(wcToRemove.account, wcToRemove.gameClient.getSessionId().playOkID1);
  297. wcToRemove.gameClient.getConnection().sendPacket(cl);
  298. wcToRemove.gameClient.setCharSelection(cl.getCharInfo());
  299. }
  300. else
  301. {
  302. _log.warn("Session key is not correct. Closing connection for account {}.", wcToRemove.account);
  303. // wcToRemove.gameClient.getConnection().sendPacket(new LoginFail(LoginFail.SYSTEM_ERROR_LOGIN_LATER));
  304. wcToRemove.gameClient.close(new LoginFail(LoginFail.SYSTEM_ERROR_LOGIN_LATER));
  305. _accountsInGameServer.remove(wcToRemove.account);
  306. }
  307. _waitingClients.remove(wcToRemove);
  308. }
  309. break;
  310. case 0x04:
  311. KickPlayer kp = new KickPlayer(incoming);
  312. doKickPlayer(kp.getAccount());
  313. break;
  314. case 0x05:
  315. RequestCharacters rc = new RequestCharacters(incoming);
  316. getCharsOnServer(rc.getAccount());
  317. break;
  318. case 0x06:
  319. new ChangePasswordResponse(incoming);
  320. break;
  321. }
  322. }
  323. }
  324. catch (UnknownHostException e)
  325. {
  326. _log.warn("Unknown host!", e);
  327. }
  328. catch (SocketException e)
  329. {
  330. _log.warn("LoginServer not avaible, trying to reconnect...");
  331. }
  332. catch (IOException e)
  333. {
  334. _log.warn("Disconnected from Login, Trying to reconnect!", e);
  335. }
  336. finally
  337. {
  338. try
  339. {
  340. _loginSocket.close();
  341. if (isInterrupted())
  342. {
  343. return;
  344. }
  345. }
  346. catch (Exception e)
  347. {
  348. }
  349. }
  350. try
  351. {
  352. Thread.sleep(5000); // 5 seconds tempo.
  353. }
  354. catch (InterruptedException e)
  355. {
  356. return; // never swallow an interrupt!
  357. }
  358. }
  359. }
  360. /**
  361. * Adds the waiting client and send request.
  362. * @param acc the account
  363. * @param client the game client
  364. * @param key the session key
  365. */
  366. public void addWaitingClientAndSendRequest(String acc, L2GameClient client, SessionKey key)
  367. {
  368. WaitingClient wc = new WaitingClient(acc, client, key);
  369. synchronized (_waitingClients)
  370. {
  371. _waitingClients.add(wc);
  372. }
  373. PlayerAuthRequest par = new PlayerAuthRequest(acc, key);
  374. try
  375. {
  376. sendPacket(par);
  377. }
  378. catch (IOException e)
  379. {
  380. _log.warn("Error while sending player auth request!");
  381. }
  382. }
  383. /**
  384. * Removes the waiting client.
  385. * @param client the client
  386. */
  387. public void removeWaitingClient(L2GameClient client)
  388. {
  389. WaitingClient toRemove = null;
  390. synchronized (_waitingClients)
  391. {
  392. for (WaitingClient c : _waitingClients)
  393. {
  394. if (c.gameClient == client)
  395. {
  396. toRemove = c;
  397. }
  398. }
  399. if (toRemove != null)
  400. {
  401. _waitingClients.remove(toRemove);
  402. }
  403. }
  404. }
  405. /**
  406. * Send logout for the given account.
  407. * @param account the account
  408. */
  409. public void sendLogout(String account)
  410. {
  411. if (account == null)
  412. {
  413. return;
  414. }
  415. PlayerLogout pl = new PlayerLogout(account);
  416. try
  417. {
  418. sendPacket(pl);
  419. }
  420. catch (IOException e)
  421. {
  422. _log.warn("Error while sending logout packet to login!");
  423. }
  424. finally
  425. {
  426. _accountsInGameServer.remove(account);
  427. }
  428. }
  429. /**
  430. * Adds the game server login.
  431. * @param account the account
  432. * @param client the client
  433. * @return {@code true} if account was not already logged in, {@code false} otherwise
  434. */
  435. public boolean addGameServerLogin(String account, L2GameClient client)
  436. {
  437. return _accountsInGameServer.putIfAbsent(account, client) == null;
  438. }
  439. /**
  440. * Send access level.
  441. * @param account the account
  442. * @param level the access level
  443. */
  444. public void sendAccessLevel(String account, int level)
  445. {
  446. ChangeAccessLevel cal = new ChangeAccessLevel(account, level);
  447. try
  448. {
  449. sendPacket(cal);
  450. }
  451. catch (IOException e)
  452. {
  453. }
  454. }
  455. /**
  456. * Send client tracert.
  457. * @param account the account
  458. * @param address the address
  459. */
  460. public void sendClientTracert(String account, String[] address)
  461. {
  462. PlayerTracert ptc = new PlayerTracert(account, address[0], address[1], address[2], address[3], address[4]);
  463. try
  464. {
  465. sendPacket(ptc);
  466. }
  467. catch (IOException e)
  468. {
  469. }
  470. }
  471. /**
  472. * Send mail.
  473. * @param account the account
  474. * @param mailId the mail id
  475. * @param args the args
  476. */
  477. public void sendMail(String account, String mailId, String... args)
  478. {
  479. SendMail sem = new SendMail(account, mailId, args);
  480. try
  481. {
  482. sendPacket(sem);
  483. }
  484. catch (IOException e)
  485. {
  486. }
  487. }
  488. /**
  489. * Send temp ban.
  490. * @param account the account
  491. * @param ip the ip
  492. * @param time the time
  493. */
  494. public void sendTempBan(String account, String ip, long time)
  495. {
  496. TempBan tbn = new TempBan(account, ip, time);
  497. try
  498. {
  499. sendPacket(tbn);
  500. }
  501. catch (IOException e)
  502. {
  503. }
  504. }
  505. /**
  506. * Hex to string.
  507. * @param hex the hex value
  508. * @return the hex value as string
  509. */
  510. private String hexToString(byte[] hex)
  511. {
  512. return new BigInteger(hex).toString(16);
  513. }
  514. /**
  515. * Kick player for the given account.
  516. * @param account the account
  517. */
  518. public void doKickPlayer(String account)
  519. {
  520. L2GameClient client = _accountsInGameServer.get(account);
  521. if (client != null)
  522. {
  523. _logAccounting.warn("Kicked by login: {}", client);
  524. client.setAditionalClosePacket(SystemMessage.getSystemMessage(SystemMessageId.ANOTHER_LOGIN_WITH_ACCOUNT));
  525. client.closeNow();
  526. }
  527. }
  528. /**
  529. * Gets the chars on server.
  530. * @param account the account
  531. */
  532. private void getCharsOnServer(String account)
  533. {
  534. int chars = 0;
  535. List<Long> charToDel = new ArrayList<>();
  536. try (Connection con = ConnectionFactory.getInstance().getConnection();
  537. PreparedStatement ps = con.prepareStatement("SELECT deletetime FROM characters WHERE account_name=?"))
  538. {
  539. ps.setString(1, account);
  540. try (ResultSet rs = ps.executeQuery())
  541. {
  542. while (rs.next())
  543. {
  544. chars++;
  545. long delTime = rs.getLong("deletetime");
  546. if (delTime != 0)
  547. {
  548. charToDel.add(delTime);
  549. }
  550. }
  551. }
  552. }
  553. catch (SQLException e)
  554. {
  555. _log.warn("Exception: getCharsOnServer!", e);
  556. }
  557. ReplyCharacters rec = new ReplyCharacters(account, chars, charToDel);
  558. try
  559. {
  560. sendPacket(rec);
  561. }
  562. catch (IOException e)
  563. {
  564. }
  565. }
  566. /**
  567. * Send packet.
  568. * @param sl the sendable packet
  569. * @throws IOException Signals that an I/O exception has occurred.
  570. */
  571. private void sendPacket(BaseSendablePacket sl) throws IOException
  572. {
  573. byte[] data = sl.getContent();
  574. NewCrypt.appendChecksum(data);
  575. _blowfish.crypt(data, 0, data.length);
  576. int len = data.length + 2;
  577. synchronized (_out) // avoids tow threads writing in the mean time
  578. {
  579. _out.write(len & 0xff);
  580. _out.write((len >> 8) & 0xff);
  581. _out.write(data);
  582. _out.flush();
  583. }
  584. }
  585. /**
  586. * Sets the max player.
  587. * @param maxPlayer The maxPlayer to set.
  588. */
  589. public void setMaxPlayer(int maxPlayer)
  590. {
  591. sendServerStatus(ServerStatus.MAX_PLAYERS, maxPlayer);
  592. _maxPlayer = maxPlayer;
  593. }
  594. /**
  595. * Gets the max player.
  596. * @return Returns the maxPlayer.
  597. */
  598. public int getMaxPlayer()
  599. {
  600. return _maxPlayer;
  601. }
  602. /**
  603. * Send server status.
  604. * @param id the id
  605. * @param value the value
  606. */
  607. public void sendServerStatus(int id, int value)
  608. {
  609. ServerStatus ss = new ServerStatus();
  610. ss.addAttribute(id, value);
  611. try
  612. {
  613. sendPacket(ss);
  614. }
  615. catch (IOException e)
  616. {
  617. }
  618. }
  619. /**
  620. * Send Server Type Config to LS.
  621. */
  622. public void sendServerType()
  623. {
  624. ServerStatus ss = new ServerStatus();
  625. ss.addAttribute(ServerStatus.SERVER_TYPE, Config.SERVER_LIST_TYPE);
  626. try
  627. {
  628. sendPacket(ss);
  629. }
  630. catch (IOException e)
  631. {
  632. }
  633. }
  634. /**
  635. * Send change password.
  636. * @param accountName the account name
  637. * @param charName the char name
  638. * @param oldpass the old pass
  639. * @param newpass the new pass
  640. */
  641. public void sendChangePassword(String accountName, String charName, String oldpass, String newpass)
  642. {
  643. ChangePassword cp = new ChangePassword(accountName, charName, oldpass, newpass);
  644. try
  645. {
  646. sendPacket(cp);
  647. }
  648. catch (IOException e)
  649. {
  650. }
  651. }
  652. /**
  653. * Gets the status string.
  654. * @return the status string
  655. */
  656. public String getStatusString()
  657. {
  658. return ServerStatus.STATUS_STRING[_status];
  659. }
  660. /**
  661. * Gets the server name.
  662. * @return the server name.
  663. */
  664. public String getServerName()
  665. {
  666. return _serverName;
  667. }
  668. /**
  669. * Sets the server status.
  670. * @param status the new server status
  671. */
  672. public void setServerStatus(int status)
  673. {
  674. switch (status)
  675. {
  676. case ServerStatus.STATUS_AUTO:
  677. sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_AUTO);
  678. _status = status;
  679. break;
  680. case ServerStatus.STATUS_DOWN:
  681. sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_DOWN);
  682. _status = status;
  683. break;
  684. case ServerStatus.STATUS_FULL:
  685. sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_FULL);
  686. _status = status;
  687. break;
  688. case ServerStatus.STATUS_GM_ONLY:
  689. sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_GM_ONLY);
  690. _status = status;
  691. break;
  692. case ServerStatus.STATUS_GOOD:
  693. sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_GOOD);
  694. _status = status;
  695. break;
  696. case ServerStatus.STATUS_NORMAL:
  697. sendServerStatus(ServerStatus.SERVER_LIST_STATUS, ServerStatus.STATUS_NORMAL);
  698. _status = status;
  699. break;
  700. default:
  701. throw new IllegalArgumentException("Status does not exists:" + status);
  702. }
  703. }
  704. public L2GameClient getClient(String name)
  705. {
  706. return name != null ? _accountsInGameServer.get(name) : null;
  707. }
  708. public static class SessionKey
  709. {
  710. public int playOkID1;
  711. public int playOkID2;
  712. public int loginOkID1;
  713. public int loginOkID2;
  714. /**
  715. * Instantiates a new session key.
  716. * @param loginOK1 the login o k1
  717. * @param loginOK2 the login o k2
  718. * @param playOK1 the play o k1
  719. * @param playOK2 the play o k2
  720. */
  721. public SessionKey(int loginOK1, int loginOK2, int playOK1, int playOK2)
  722. {
  723. playOkID1 = playOK1;
  724. playOkID2 = playOK2;
  725. loginOkID1 = loginOK1;
  726. loginOkID2 = loginOK2;
  727. }
  728. @Override
  729. public String toString()
  730. {
  731. return "PlayOk: " + playOkID1 + " " + playOkID2 + " LoginOk:" + loginOkID1 + " " + loginOkID2;
  732. }
  733. }
  734. private static class WaitingClient
  735. {
  736. public String account;
  737. public L2GameClient gameClient;
  738. public SessionKey session;
  739. /**
  740. * Instantiates a new waiting client.
  741. * @param acc the acc
  742. * @param client the client
  743. * @param key the key
  744. */
  745. public WaitingClient(String acc, L2GameClient client, SessionKey key)
  746. {
  747. account = acc;
  748. gameClient = client;
  749. session = key;
  750. }
  751. }
  752. /**
  753. * Gets the single instance of LoginServerThread.
  754. * @return single instance of LoginServerThread
  755. */
  756. public static LoginServerThread getInstance()
  757. {
  758. return SingletonHolder._instance;
  759. }
  760. private static class SingletonHolder
  761. {
  762. protected static final LoginServerThread _instance = new LoginServerThread();
  763. }
  764. }