L2LoginServer.java 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * Copyright (C) 2004-2013 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.loginserver;
  20. import java.io.File;
  21. import java.io.FileInputStream;
  22. import java.io.IOException;
  23. import java.io.InputStream;
  24. import java.io.InputStreamReader;
  25. import java.io.LineNumberReader;
  26. import java.net.InetAddress;
  27. import java.net.UnknownHostException;
  28. import java.security.GeneralSecurityException;
  29. import java.sql.SQLException;
  30. import java.util.logging.Level;
  31. import java.util.logging.LogManager;
  32. import java.util.logging.Logger;
  33. import org.mmocore.network.SelectorConfig;
  34. import org.mmocore.network.SelectorThread;
  35. import com.l2jserver.Config;
  36. import com.l2jserver.L2DatabaseFactory;
  37. import com.l2jserver.Server;
  38. import com.l2jserver.loginserver.mail.MailSystem;
  39. import com.l2jserver.loginserver.network.L2LoginClient;
  40. import com.l2jserver.loginserver.network.L2LoginPacketHandler;
  41. import com.l2jserver.status.Status;
  42. /**
  43. * @author KenM
  44. */
  45. public final class L2LoginServer
  46. {
  47. private final Logger _log = Logger.getLogger(L2LoginServer.class.getName());
  48. public static final int PROTOCOL_REV = 0x0106;
  49. private static L2LoginServer _instance;
  50. private GameServerListener _gameServerListener;
  51. private SelectorThread<L2LoginClient> _selectorThread;
  52. private Status _statusServer;
  53. private Thread _restartLoginServer;
  54. public static void main(String[] args)
  55. {
  56. _instance = new L2LoginServer();
  57. }
  58. public static L2LoginServer getInstance()
  59. {
  60. return _instance;
  61. }
  62. public L2LoginServer()
  63. {
  64. Server.serverMode = Server.MODE_LOGINSERVER;
  65. // Local Constants
  66. final String LOG_FOLDER = "log"; // Name of folder for log file
  67. final String LOG_NAME = "./log.cfg"; // Name of log file
  68. /*** Main ***/
  69. // Create log folder
  70. File logFolder = new File(Config.DATAPACK_ROOT, LOG_FOLDER);
  71. logFolder.mkdir();
  72. // Create input stream for log file -- or store file data into memory
  73. try (InputStream is = new FileInputStream(new File(LOG_NAME)))
  74. {
  75. LogManager.getLogManager().readConfiguration(is);
  76. }
  77. catch (IOException e)
  78. {
  79. _log.warning(getClass().getSimpleName() + ": " + e.getMessage());
  80. }
  81. // Load Config
  82. Config.load();
  83. // Prepare Database
  84. try
  85. {
  86. L2DatabaseFactory.getInstance();
  87. }
  88. catch (SQLException e)
  89. {
  90. _log.log(Level.SEVERE, "FATAL: Failed initializing database. Reason: " + e.getMessage(), e);
  91. System.exit(1);
  92. }
  93. try
  94. {
  95. LoginController.load();
  96. }
  97. catch (GeneralSecurityException e)
  98. {
  99. _log.log(Level.SEVERE, "FATAL: Failed initializing LoginController. Reason: " + e.getMessage(), e);
  100. System.exit(1);
  101. }
  102. GameServerTable.getInstance();
  103. loadBanFile();
  104. if (Config.EMAIL_SYS_ENABLED)
  105. {
  106. MailSystem.getInstance();
  107. }
  108. InetAddress bindAddress = null;
  109. if (!Config.LOGIN_BIND_ADDRESS.equals("*"))
  110. {
  111. try
  112. {
  113. bindAddress = InetAddress.getByName(Config.LOGIN_BIND_ADDRESS);
  114. }
  115. catch (UnknownHostException e)
  116. {
  117. _log.log(Level.WARNING, "WARNING: The LoginServer bind address is invalid, using all avaliable IPs. Reason: " + e.getMessage(), e);
  118. }
  119. }
  120. final SelectorConfig sc = new SelectorConfig();
  121. sc.MAX_READ_PER_PASS = Config.MMO_MAX_READ_PER_PASS;
  122. sc.MAX_SEND_PER_PASS = Config.MMO_MAX_SEND_PER_PASS;
  123. sc.SLEEP_TIME = Config.MMO_SELECTOR_SLEEP_TIME;
  124. sc.HELPER_BUFFER_COUNT = Config.MMO_HELPER_BUFFER_COUNT;
  125. final L2LoginPacketHandler lph = new L2LoginPacketHandler();
  126. final SelectorHelper sh = new SelectorHelper();
  127. try
  128. {
  129. _selectorThread = new SelectorThread<>(sc, sh, lph, sh, sh);
  130. }
  131. catch (IOException e)
  132. {
  133. _log.log(Level.SEVERE, "FATAL: Failed to open Selector. Reason: " + e.getMessage(), e);
  134. System.exit(1);
  135. }
  136. try
  137. {
  138. _gameServerListener = new GameServerListener();
  139. _gameServerListener.start();
  140. _log.info("Listening for GameServers on " + Config.GAME_SERVER_LOGIN_HOST + ":" + Config.GAME_SERVER_LOGIN_PORT);
  141. }
  142. catch (IOException e)
  143. {
  144. _log.log(Level.SEVERE, "FATAL: Failed to start the Game Server Listener. Reason: " + e.getMessage(), e);
  145. System.exit(1);
  146. }
  147. if (Config.IS_TELNET_ENABLED)
  148. {
  149. try
  150. {
  151. _statusServer = new Status(Server.serverMode);
  152. _statusServer.start();
  153. }
  154. catch (IOException e)
  155. {
  156. _log.log(Level.WARNING, "Failed to start the Telnet Server. Reason: " + e.getMessage(), e);
  157. }
  158. }
  159. else
  160. {
  161. _log.info("Telnet server is currently disabled.");
  162. }
  163. try
  164. {
  165. _selectorThread.openServerSocket(bindAddress, Config.PORT_LOGIN);
  166. }
  167. catch (IOException e)
  168. {
  169. _log.log(Level.SEVERE, "FATAL: Failed to open server socket. Reason: " + e.getMessage(), e);
  170. System.exit(1);
  171. }
  172. _selectorThread.start();
  173. _log.info("Login Server ready on " + (bindAddress == null ? "*" : bindAddress.getHostAddress()) + ":" + Config.PORT_LOGIN);
  174. }
  175. public Status getStatusServer()
  176. {
  177. return _statusServer;
  178. }
  179. public GameServerListener getGameServerListener()
  180. {
  181. return _gameServerListener;
  182. }
  183. private void loadBanFile()
  184. {
  185. final File bannedFile = new File("./banned_ip.cfg");
  186. if (bannedFile.exists() && bannedFile.isFile())
  187. {
  188. String line;
  189. String[] parts;
  190. try (FileInputStream fis = new FileInputStream(bannedFile);
  191. InputStreamReader is = new InputStreamReader(fis);
  192. LineNumberReader reader = new LineNumberReader(is))
  193. {
  194. while ((line = reader.readLine()) != null)
  195. {
  196. line = line.trim();
  197. // check if this line isn't a comment line
  198. if ((line.length() > 0) && (line.charAt(0) != '#'))
  199. {
  200. // split comments if any
  201. parts = line.split("#", 2);
  202. // discard comments in the line, if any
  203. line = parts[0];
  204. parts = line.split(" ");
  205. String address = parts[0];
  206. long duration = 0;
  207. if (parts.length > 1)
  208. {
  209. try
  210. {
  211. duration = Long.parseLong(parts[1]);
  212. }
  213. catch (NumberFormatException e)
  214. {
  215. _log.warning("Skipped: Incorrect ban duration (" + parts[1] + ") on (" + bannedFile.getName() + "). Line: " + reader.getLineNumber());
  216. continue;
  217. }
  218. }
  219. try
  220. {
  221. LoginController.getInstance().addBanForAddress(address, duration);
  222. }
  223. catch (UnknownHostException e)
  224. {
  225. _log.warning("Skipped: Invalid address (" + parts[0] + ") on (" + bannedFile.getName() + "). Line: " + reader.getLineNumber());
  226. }
  227. }
  228. }
  229. }
  230. catch (IOException e)
  231. {
  232. _log.log(Level.WARNING, "Error while reading the bans file (" + bannedFile.getName() + "). Details: " + e.getMessage(), e);
  233. }
  234. _log.info("Loaded " + LoginController.getInstance().getBannedIps().size() + " IP Bans.");
  235. }
  236. else
  237. {
  238. _log.warning("IP Bans file (" + bannedFile.getName() + ") is missing or is a directory, skipped.");
  239. }
  240. if (Config.LOGIN_SERVER_SCHEDULE_RESTART)
  241. {
  242. _log.info("Scheduled LS restart after " + Config.LOGIN_SERVER_SCHEDULE_RESTART_TIME + " hours");
  243. _restartLoginServer = new LoginServerRestart();
  244. _restartLoginServer.setDaemon(true);
  245. _restartLoginServer.start();
  246. }
  247. }
  248. class LoginServerRestart extends Thread
  249. {
  250. public LoginServerRestart()
  251. {
  252. setName("LoginServerRestart");
  253. }
  254. @Override
  255. public void run()
  256. {
  257. while (!isInterrupted())
  258. {
  259. try
  260. {
  261. Thread.sleep(Config.LOGIN_SERVER_SCHEDULE_RESTART_TIME * 3600000);
  262. }
  263. catch (InterruptedException e)
  264. {
  265. return;
  266. }
  267. shutdown(true);
  268. }
  269. }
  270. }
  271. public void shutdown(boolean restart)
  272. {
  273. Runtime.getRuntime().exit(restart ? 2 : 0);
  274. }
  275. }