Server.java 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package eu.tankernn.chat.server;
  2. import java.io.File;
  3. import java.io.FileNotFoundException;
  4. import java.io.FileReader;
  5. import java.io.IOException;
  6. import java.io.PrintWriter;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9. import java.util.Optional;
  10. import java.util.Properties;
  11. import java.util.logging.Level;
  12. import java.util.logging.Logger;
  13. import eu.tankernn.chat.common.MessagePacket;
  14. import io.netty.bootstrap.ServerBootstrap;
  15. import io.netty.channel.ChannelFuture;
  16. import io.netty.channel.ChannelInitializer;
  17. import io.netty.channel.ChannelOption;
  18. import io.netty.channel.EventLoopGroup;
  19. import io.netty.channel.nio.NioEventLoopGroup;
  20. import io.netty.channel.socket.SocketChannel;
  21. import io.netty.channel.socket.nio.NioServerSocketChannel;
  22. import io.netty.handler.codec.serialization.ObjectEncoder;
  23. import io.netty.handler.codec.string.StringDecoder;
  24. import io.netty.handler.timeout.ReadTimeoutHandler;
  25. public class Server {
  26. private static Thread clientListener;
  27. private static Properties prop = new Properties();
  28. private static File propFile = new File("server.properties");
  29. private static int port, maxUsers;
  30. private static final String version = "4.0";
  31. private static ArrayList<BanNote> banNotes = new ArrayList<BanNote>();
  32. private static ArrayList<Channel> channels = new ArrayList<Channel>();
  33. private static ClientCollection clients;
  34. private static ServerBootstrap bootstrap;
  35. private static LocalClient OPClient;
  36. private static final Logger log = Logger.getGlobal();
  37. private static CommandRegistry commandRegistry;
  38. public static void main(String[] arg) {
  39. // try {
  40. // LogManager.getLogManager().readConfiguration(Server.class.getResourceAsStream("/logger.properties"));
  41. // } catch (SecurityException | IOException e2) {
  42. // log.log(Level.SEVERE, e2.getMessage(), e2);
  43. // }
  44. log.info("Starting ChatServer version " + version + "...");
  45. log.fine("Loadning properties file...");
  46. try {
  47. prop.load(new FileReader(propFile));
  48. } catch (FileNotFoundException e1) {
  49. try {
  50. prop.load(Server.class
  51. .getResourceAsStream("/" + propFile.getName()));
  52. } catch (IOException e) {
  53. log.log(Level.SEVERE, e.getMessage(), e);
  54. }
  55. } catch (IOException e1) {
  56. log.log(Level.SEVERE, e1.getMessage(), e1);
  57. }
  58. log.fine("Reading numbers from properties object...");
  59. port = Integer.parseInt(prop.getProperty("port"));
  60. maxUsers = Integer.parseInt(prop.getProperty("maxUsers"));
  61. clients = new ClientCollection();
  62. getChannels().add(new Channel("Main"));
  63. log.fine("Starting commandhandler...");
  64. commandRegistry = new CommandRegistry();
  65. log.fine("Creating virtual local client...");
  66. OPClient = new LocalClient();
  67. log.fine("Starting client listener thread...");
  68. clientListener = new Thread(Server::run);
  69. clientListener.start();
  70. log.info("Server started successfully!");
  71. }
  72. public static void addClient(Client c) {
  73. clients.add(c);
  74. getChannels().get(0).add(c);
  75. wideBroadcast(new MessagePacket(c.username + " has connected."));
  76. }
  77. private static void run() {
  78. EventLoopGroup bossGroup = new NioEventLoopGroup();
  79. EventLoopGroup workerGroup = new NioEventLoopGroup();
  80. try {
  81. bootstrap = new ServerBootstrap();
  82. bootstrap.group(bossGroup, workerGroup)
  83. .channel(NioServerSocketChannel.class)
  84. .childHandler(new ChannelInitializer<SocketChannel>() {
  85. @Override
  86. public void initChannel(SocketChannel ch) throws Exception {
  87. ch.pipeline().addLast("decoder",
  88. new StringDecoder());
  89. ch.pipeline().addLast("encoder",
  90. new ObjectEncoder());
  91. ch.pipeline().addLast("timeouthandler",
  92. new ReadTimeoutHandler(5));
  93. ch.pipeline().addLast("handler",
  94. new ChatServerHandler());
  95. }
  96. }).option(ChannelOption.SO_BACKLOG, 128)
  97. .childOption(ChannelOption.SO_KEEPALIVE, true);
  98. // Bind and start to accept incoming connections.
  99. ChannelFuture f = bootstrap.bind(port).sync();
  100. // Wait until the server socket is closed.
  101. // In this example, this does not happen, but you can do that to
  102. // gracefully
  103. // shut down your server.
  104. f.channel().closeFuture().sync();
  105. } catch (InterruptedException e) {
  106. // No need to handle, just shut down
  107. } finally {
  108. workerGroup.shutdownGracefully();
  109. bossGroup.shutdownGracefully();
  110. }
  111. }
  112. public static Optional<Channel> getChannelByName(String name) throws NullPointerException {
  113. return getChannels().stream().filter(c -> c.name.equals(name))
  114. .findFirst();
  115. }
  116. public static void wideBroadcast(MessagePacket mess) {
  117. getClients().broadcast(mess);
  118. }
  119. public static String[] getUsersOnline() {
  120. return getClients().getUsernameArray();
  121. }
  122. public static String listClients(CharSequence c) {
  123. return getClients().listClients(c);
  124. }
  125. public static Optional<Client> getUserByName(String username) {
  126. return getClients().getClientByName(username);
  127. }
  128. public static void ban(BanNote ban) {
  129. banNotes.add(ban);
  130. }
  131. /**
  132. * Removes disconnected clients from all collections on the server.
  133. */
  134. public static void cleanUp() {
  135. getClients().cleanUp();
  136. getChannels().forEach(c -> c.cleanUp());
  137. }
  138. /**
  139. * Disconnects all users and closes log and socket.
  140. */
  141. public static void exit() {
  142. wideBroadcast(new MessagePacket("Shutting down server!"));
  143. clientListener.interrupt();
  144. clients.disconnectAll();
  145. getLocalClient().disconnect();
  146. try {
  147. prop.store(new PrintWriter(propFile), "ChatServer config file");
  148. } catch (IOException e1) {
  149. e1.printStackTrace();
  150. }
  151. }
  152. public static int getMaxUsers() {
  153. return maxUsers;
  154. }
  155. public static LocalClient getLocalClient() {
  156. return OPClient;
  157. }
  158. public static Logger getLogger() {
  159. return log;
  160. }
  161. public static ArrayList<Channel> getChannels() {
  162. return channels;
  163. }
  164. public static ClientCollection getClients() {
  165. return clients;
  166. }
  167. public static CommandRegistry getCommReg() {
  168. return commandRegistry;
  169. }
  170. public static List<BanNote> getBanned() {
  171. return banNotes;
  172. }
  173. }