/* package com.growcontrol.server.net; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import java.net.UnknownHostException; import java.util.Collection; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import com.growcontrol.common.netty.NetParent; import com.growcontrol.common.netty.SocketState; import com.growcontrol.common.packets.PacketDirection; import com.growcontrol.server.gcServerVars; import com.growcontrol.server.configs.NetServerConfig; import com.poixson.commonapp.net.firewall.NetFirewall; import com.poixson.commonjava.Utils.exceptions.RequiredArgumentException; import com.poixson.commonjava.xLogger.xLog; public class NetServer implements NetParent { private static final String LOG_NAME = "NET"; public final NetServerConfig netConfig; public final String serverKey; protected volatile boolean closed = false; protected final ServerBootstrap bootstrap; protected final NetServerInitializer initer; protected final Channel serverChannel; protected final ConcurrentMap<Channel, ServerSocketState> states = new ConcurrentHashMap<Channel, ServerSocketState>(); //throws UnknownHostException, SocketException, InterruptedException { public NetServer(final NetServerConfig netConfig) throws UnknownHostException, InterruptedException { if (netConfig == null) throw new RequiredArgumentException("netConfig"); if (!netConfig.isEnabled()) throw new UnsupportedOperationException("This socket server is disabled!"); this.netConfig = netConfig; this.serverKey = this.netConfig.toString(); this.log().finer("Starting socket server.."); // server bootstrap { final NetServerManager manager = NetServerManager.get(); this.bootstrap = new ServerBootstrap(); this.bootstrap.group( manager.bossGroup, manager.workGroup ); } // socket backlog { final int backlog = gcServerVars.getConfig().getSocketBacklog(); this.bootstrap.option( ChannelOption.SO_BACKLOG, backlog ); } this.bootstrap.channel(NioServerSocketChannel.class); // debug if (this.log().isLoggable(xLevel.DETAIL)) { final LoggingHandler handlerLogger = new LoggingHandler(LogLevel.INFO); this.bootstrap.handler(handlerLogger); this.bootstrap.childHandler(handlerLogger); } // socket initializer this.initer = new NetServerInitializer(this); this.bootstrap.childHandler(this.initer); // start listening this.serverChannel = this.bootstrap.bind( this.netConfig.getInetAddress(), this.netConfig.getPort() ).sync().channel(); this.log().info("Socket server listening for connections.."); } / ** * New socket connection accepted. * @param state * @return true to accept the connection or false to deny. * / public boolean register(final ServerSocketState socketState) { if (socketState == null) throw new RequiredArgumentException("socketState"); final SocketChannel channel = socketState.getChannel(); if (channel == null) throw new RuntimeException("Channel is null, socket may have disconnected already!"); this.states.put(channel, socketState); // check firewall { final NetFirewall firewall = this.getFirewall(); final Boolean result = firewall.check( channel.localAddress(), channel.remoteAddress() ); // default firewall action if (result == null) { this.log().finer("No matching firewall rule for this socket: "+socketState.toString()); //TODO: this.log().severe("THIS IS UNFINISHED: NetServer->register() default firewall action"); } else // allowed by firewall if (result) { this.log().fine("Firewall allowed connection: "+socketState.toString()); } else { this.log().warning("Firewall blocked connection: "+socketState.toString()); return false; } } //TODO: store the socket return true; } / ** * Remove disconnected socket. * @param state * / // socket disconnected public void unregister(final ServerSocketState socketState) { if (socketState == null) throw new RequiredArgumentException("socketState"); this.states.remove(socketState); } public ServerSocketState getServerSocketState(final Channel channel) { if (channel == null) return null; return this.states.get(channel); } @Override public SocketState getSocketState(final Channel channel) { return this.getServerSocketState(channel); } @Override public int getSocketsCount() { return this.states.size(); } public String getServerKey() { return this.serverKey; } @Override public String getKeyHash() { return this.getServerKey(); } public NetFirewall getFirewall() { return NetServerManager.get() .getFirewall(); } @Override public PacketDirection getDirection() { return PacketDirection.SERVER_TO_CLIENT; } / ** * Stop listening for connections. * / @Override public void close() { try { this.closeSoon() .sync(); } catch (InterruptedException e) { this.log().trace(e); } } public ChannelFuture closeSoon() { this.log().info("Stopping socket server.."); this.closed = true; return this.serverChannel.close(); } / ** * Disconnect all connected sockets. * / @Override public void CloseAll() { // clone states list final Collection<ServerSocketState> states = this.states.values(); if (states.isEmpty()) return; this.log().info("Closing sockets.."); // close sockets final Set<ChannelFuture> futureCloses = new HashSet<ChannelFuture>(); for (final ServerSocketState state : states) { futureCloses.add( state.closeSoon() ); } // wait for sockets to close for (final ChannelFuture future : futureCloses) { try { future.sync(); } catch (InterruptedException e) { this.log().trace(e); break; } } this.log().info( (new StringBuilder()) .append("Closed ") .append(futureCloses.size()) .append(" sockets") .toString() ); final int stillConnected = this.states.size(); if (stillConnected > 0) { this.log().warning( (new StringBuilder()) .append(stillConnected) .append(" sockets still connected!") .toString() ); } } @Override public boolean isClosed() { return this.closed; } // logger private volatile xLog _log = null; public xLog log() { if (this._log == null) this._log = xLog.getRoot(LOG_NAME) .get("S|"+this.serverKey); return this._log; } } */