LoginServer.java
上传用户:gwt600
上传日期:2021-06-03
资源大小:704k
文件大小:14k
源码类别:

游戏

开发平台:

Java

  1. /*
  2. This file is part of the OdinMS Maple Story Server
  3. Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc> 
  4. Matthias Butz <matze@odinms.de>
  5. Jan Christian Meyer <vimes@odinms.de>
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU Affero General Public License version 3
  8. as published by the Free Software Foundation. You may not use, modify
  9. or distribute this program under any other version of the
  10. GNU Affero General Public License.
  11. This program 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
  14. GNU Affero General Public License for more details.
  15. You should have received a copy of the GNU Affero General Public License
  16. along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18. package net.sf.odinms.net.login;
  19. import java.io.FileReader;
  20. import java.io.IOException;
  21. import java.lang.management.ManagementFactory;
  22. import java.net.InetSocketAddress;
  23. import java.rmi.RemoteException;
  24. import java.rmi.registry.LocateRegistry;
  25. import java.rmi.registry.Registry;
  26. import java.sql.Connection;
  27. import java.sql.PreparedStatement;
  28. import java.sql.ResultSet;
  29. import java.util.HashMap;
  30. import java.util.Map;
  31. import java.util.Properties;
  32. import java.util.Set;
  33. import javax.management.MBeanServer;
  34. import javax.management.ObjectName;
  35. import javax.rmi.ssl.SslRMIClientSocketFactory;
  36. import net.sf.odinms.database.DatabaseConnection;
  37. import net.sf.odinms.net.MapleServerHandler;
  38. import net.sf.odinms.net.PacketProcessor;
  39. import net.sf.odinms.net.login.remote.LoginWorldInterface;
  40. import net.sf.odinms.net.mina.MapleCodecFactory;
  41. import net.sf.odinms.net.world.remote.WorldLoginInterface;
  42. import net.sf.odinms.net.world.remote.WorldRegistry;
  43. import net.sf.odinms.server.TimerManager;
  44. import org.apache.mina.common.ByteBuffer;
  45. import org.apache.mina.common.IoAcceptor;
  46. import org.apache.mina.common.SimpleByteBufferAllocator;
  47. import org.apache.mina.filter.codec.ProtocolCodecFilter;
  48. import org.apache.mina.transport.socket.nio.SocketAcceptor;
  49. import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
  50. import org.slf4j.Logger;
  51. import org.slf4j.LoggerFactory;
  52. public class LoginServer implements Runnable, LoginServerMBean {
  53.     public static int PORT = 8484;
  54.     private IoAcceptor acceptor;
  55.     static final Logger log = LoggerFactory.getLogger(LoginServer.class);
  56.     private static WorldRegistry worldRegistry = null;
  57.     private Map<Integer, String> channelServer = new HashMap<Integer, String>();
  58.     private LoginWorldInterface lwi;
  59.     private WorldLoginInterface wli;
  60.     private Properties prop = new Properties();
  61.     private Properties initialProp = new Properties();
  62.     private Boolean worldReady = Boolean.TRUE;
  63.     private Properties subnetInfo = new Properties();
  64.     private Map<Integer, Integer> load = new HashMap<Integer, Integer>();
  65.     private String serverName;
  66.     private String eventMessage;
  67.     int flag;
  68.     int maxCharacters;
  69.     int userLimit;
  70.     int loginInterval;
  71.     private long rankingInterval;
  72.         private boolean AutoReg;
  73.     private boolean serverCheck;
  74.     private static LoginServer instance = new LoginServer();
  75.     private int worlds;
  76.     private boolean autoReg,  resetStats;
  77.     static {
  78.         MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
  79.         try {
  80.             mBeanServer.registerMBean(instance, new ObjectName("net.sf.odinms.net.login:type=LoginServer,name=LoginServer"));
  81.         } catch (Exception e) {
  82.             log.error("MBEAN ERROR", e);
  83.         // not taht bad...
  84.         }
  85.     }
  86.     private LoginServer() {
  87.     }
  88.     public static LoginServer getInstance() {
  89.         return instance;
  90.     }
  91.     public Set<Integer> getChannels() {
  92.         return channelServer.keySet();
  93.     }
  94.     public void addChannel(int channel, String ip) {
  95.         channelServer.put(channel, ip);
  96.         load.put(channel, 0);
  97.     }
  98.     public void removeChannel(int channel) {
  99.         channelServer.remove(channel);
  100.         load.remove(channel);
  101.     }
  102.     public String getIP(int channel) {
  103.         return channelServer.get(channel);
  104.     }
  105.     
  106.     public int numberOfWorlds() {
  107.         return worlds;
  108.     }  
  109.     public int getPossibleLogins() {
  110.         int ret = 0;
  111.         try {
  112.             Connection con = DatabaseConnection.getConnection();
  113.             PreparedStatement limitCheck = con.prepareStatement("SELECT COUNT(*) FROM accounts WHERE loggedin > 1 AND gm=0");
  114.             ResultSet rs = limitCheck.executeQuery();
  115.             if (rs.next()) {
  116.                 int usersOn = rs.getInt(1);
  117.                 // log.info("userson: " + usersOn + ", limit: " + userLimit);
  118.                 if (usersOn < userLimit) {
  119.                     ret = userLimit - usersOn;
  120.                 }
  121.             }
  122.             rs.close();
  123.             limitCheck.close();
  124.         } catch (Exception ex) {
  125.             log.error("登陆限制错误:", ex);
  126.         }
  127.         return ret;
  128.     }
  129.     public void reconnectWorld() {
  130.         // check if the connection is really gone
  131.         try {
  132.             wli.isAvailable();
  133.         } catch (RemoteException ex) {
  134.             synchronized (worldReady) {
  135.                 worldReady = Boolean.FALSE;
  136.             }
  137.             synchronized (lwi) {
  138.                 synchronized (worldReady) {
  139.                     if (worldReady) {
  140.                         return;
  141.                     }
  142.                 }
  143.                 System.err.println("重新连接世界的服务器");
  144.                 synchronized (wli) {
  145.                     // completely re-establish the rmi connection
  146.                     try {
  147.                         FileReader fileReader = new FileReader(System.getProperty("net.sf.odinms.login.config"));
  148.                         initialProp.load(fileReader);
  149.                         fileReader.close();
  150.                         Registry registry = LocateRegistry.getRegistry(initialProp.getProperty("net.sf.odinms.world.host"),
  151.                                 Registry.REGISTRY_PORT, new SslRMIClientSocketFactory());
  152.                         worldRegistry = (WorldRegistry) registry.lookup("WorldRegistry");
  153.                         lwi = new LoginWorldInterfaceImpl();
  154.                         wli = worldRegistry.registerLoginServer(initialProp.getProperty("net.sf.odinms.login.key"), lwi);
  155.                         Properties dbProp = new Properties();
  156.                         fileReader = new FileReader("db.properties");
  157.                         dbProp.load(fileReader);
  158.                         fileReader.close();
  159.                         DatabaseConnection.setProps(dbProp);
  160.                         DatabaseConnection.getConnection();
  161.                         prop = wli.getWorldProperties();
  162.                         userLimit = Integer.parseInt(prop.getProperty("net.sf.odinms.login.userlimit"));
  163.                         serverName = prop.getProperty("net.sf.odinms.world.serverName");
  164.                         eventMessage = prop.getProperty("net.sf.odinms.login.eventMessage");
  165.                         flag = Integer.parseInt(prop.getProperty("net.sf.odinms.login.flag"));
  166.                         maxCharacters = Integer.parseInt(prop.getProperty("net.sf.odinms.login.maxCharacters"));
  167.                         worlds = Integer.parseInt(prop.getProperty("net.sf.odinms.world.numberOfWorlds"));
  168.                         resetStats = Boolean.parseBoolean(prop.getProperty("net.sf.odinms.login.resetStats", "false"));
  169.                         serverCheck = Boolean.parseBoolean(prop.getProperty("net.sf.odinms.login.serverCheck", "false"));
  170.                         try {
  171.                             fileReader = new FileReader("subnet.properties");
  172.                             subnetInfo.load(fileReader);
  173.                             fileReader.close();
  174.                         } catch (Exception e) {
  175.                             log.info("无法加载的子网配置,回落至世界默认", e);
  176.                         }
  177.                     } catch (Exception e) {
  178.                         System.err.println("重新连接失败:"+ e);
  179.                     }
  180.                     worldReady = Boolean.TRUE;
  181.                 }
  182.             }
  183.             synchronized (worldReady) {
  184.                 worldReady.notifyAll();
  185.             }
  186.         }
  187.     }
  188.     public boolean getAutoRegister() {
  189.         return autoReg;
  190.     }
  191.     @Override
  192.     public void run() {
  193.         try {
  194.             FileReader fileReader = new FileReader(System.getProperty("net.sf.odinms.login.config"));
  195.             initialProp.load(fileReader);
  196.             fileReader.close();
  197.             Registry registry = LocateRegistry.getRegistry(initialProp.getProperty("net.sf.odinms.world.host"),
  198.                     Registry.REGISTRY_PORT, new SslRMIClientSocketFactory());
  199.             worldRegistry = (WorldRegistry) registry.lookup("WorldRegistry");
  200.             lwi = new LoginWorldInterfaceImpl();
  201.             wli = worldRegistry.registerLoginServer(initialProp.getProperty("net.sf.odinms.login.key"), lwi);
  202.             Properties dbProp = new Properties();
  203.             fileReader = new FileReader("db.properties");
  204.             dbProp.load(fileReader);
  205.             fileReader.close();
  206.             DatabaseConnection.setProps(dbProp);
  207.             DatabaseConnection.getConnection();
  208.             prop = wli.getWorldProperties();
  209.             userLimit = Integer.parseInt(prop.getProperty("net.sf.odinms.login.userlimit"));
  210.             serverName = prop.getProperty("net.sf.odinms.world.serverName");
  211.             eventMessage = prop.getProperty("net.sf.odinms.login.eventMessage");
  212.             flag = Integer.parseInt(prop.getProperty("net.sf.odinms.login.flag"));
  213.             maxCharacters = Integer.parseInt(prop.getProperty("net.sf.odinms.login.maxCharacters"));
  214.             serverCheck = Boolean.parseBoolean(prop.getProperty("net.sf.odinms.login.serverCheck", "false"));
  215.             worlds = Integer.parseInt(prop.getProperty("net.sf.odinms.world.numberOfWorlds"));
  216.             resetStats = Boolean.parseBoolean(prop.getProperty("net.sf.odinms.login.resetStats", "false"));
  217.             try {
  218.                 fileReader = new FileReader("subnet.properties");
  219.                 subnetInfo.load(fileReader);
  220.                 fileReader.close();
  221.             } catch (Exception e) {
  222.                 log.trace("无法加载的子网配置,回落至世界默认", e);
  223.             }
  224.         } catch (Exception e) {
  225.             throw new RuntimeException("无法连接到世界服务器.", e);
  226.         }
  227.         ByteBuffer.setUseDirectBuffers(false);
  228.         ByteBuffer.setAllocator(new SimpleByteBufferAllocator());
  229.         acceptor = new SocketAcceptor();
  230.         SocketAcceptorConfig cfg = new SocketAcceptorConfig();
  231.         // cfg.setThreadModel(ThreadModel.MANUAL);
  232.         // cfg.getFilterChain().addLast("logger", new LoggingFilter());
  233.         // Loginserver is still on the default threadmodel so no executor filter here...
  234.         // ExecutorService executor = new ThreadPoolExecutor(4, 8, 60, TimeUnit.SECONDS,
  235.         // new LinkedBlockingQueue<Runnable>());
  236.         // cfg.getFilterChain().addLast("executor", new ExecutorFilter(executor));
  237.         cfg.getFilterChain().addLast("codec", new ProtocolCodecFilter(new MapleCodecFactory()));
  238.         TimerManager tMan = TimerManager.getInstance();
  239.         tMan.start();
  240.         loginInterval = Integer.parseInt(prop.getProperty("net.sf.odinms.login.interval"));
  241.         PORT = Integer.parseInt(prop.getProperty("net.sf.odinms.login.port"));
  242.         tMan.register(LoginWorker.getInstance(), loginInterval);
  243.         rankingInterval = Long.parseLong(prop.getProperty("net.sf.odinms.login.ranking.interval"));
  244.         tMan.register(new RankingWorker(), rankingInterval);
  245.         try {
  246.             acceptor.bind(new InetSocketAddress(PORT), new MapleServerHandler(PacketProcessor.getProcessor(PacketProcessor.Mode.LOGINSERVER)), cfg);
  247.             System.out.println("游戏监听端口: " + PORT );
  248.         } catch (IOException e) {
  249.             System.out.println("访问游戏端口: "+ PORT +" 失败"+ e);
  250.         }
  251.     }
  252.     public void shutdown() {
  253.         System.out.println("关闭中...");
  254.         try {
  255.             worldRegistry.deregisterLoginServer(lwi);
  256.         } catch (RemoteException e) {
  257.             // doesn't matter we're shutting down anyway
  258.         }
  259.         TimerManager.getInstance().stop();
  260.         System.exit(0);
  261.     }
  262.     public WorldLoginInterface getWorldInterface() {
  263.         synchronized (worldReady) {
  264.             while (!worldReady) {
  265.                 try {
  266.                     worldReady.wait();
  267.                 } catch (InterruptedException e) {
  268.                 }
  269.             }
  270.         }
  271.         return wli;
  272.     }
  273.     public static void main(String args[]) {
  274.         try {
  275.             LoginServer.getInstance().run();
  276.         } catch (Exception ex) {
  277.             log.error("Error initializing loginserver", ex);
  278.         }
  279.     }
  280.     public int getLoginInterval() {
  281.         return loginInterval;
  282.     }
  283.     public Properties getSubnetInfo() {
  284.         return subnetInfo;
  285.     }
  286.     public int getUserLimit() {
  287.         return userLimit;
  288.     }
  289.     public String getServerName() {
  290.         return serverName;
  291.     }
  292.     @Override
  293.     public String getEventMessage() {
  294.         return eventMessage;
  295.     }
  296.     @Override
  297.     public int getFlag() {
  298.         return flag;
  299.     }
  300.     public int getMaxCharacters() {
  301.         return maxCharacters;
  302.     }
  303.     public Map<Integer, Integer> getLoad() {
  304.         return load;
  305.     }
  306.     public void setLoad(Map<Integer, Integer> load) {
  307.         this.load = load;
  308.     }
  309.     @Override
  310.     public void setEventMessage(String newMessage) {
  311.         this.eventMessage = newMessage;
  312.     }
  313.     @Override
  314.     public void setFlag(int newflag) {
  315.         flag = newflag;
  316.     }
  317.     @Override
  318.     public int getNumberOfSessions() {
  319.         return acceptor.getManagedSessions(new InetSocketAddress(PORT)).size();
  320.     }
  321.     @Override
  322.     public void setUserLimit(int newLimit) {
  323.         userLimit = newLimit;
  324.     }
  325.     public void setServerCheck(boolean set) {
  326.         serverCheck = set;
  327.     }
  328.     public boolean isServerCheck() {
  329.         return serverCheck;
  330.     }
  331. }