/* package com.growcontrol.server.net; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.util.SelfSignedCertificate; import java.net.UnknownHostException; import java.security.cert.CertificateException; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.net.ssl.SSLException; import com.growcontrol.server.configs.NetServerConfig; import com.poixson.commonapp.net.firewall.NetFirewall; import com.poixson.commonjava.Utils.Keeper; import com.poixson.commonjava.Utils.utilsThread; import com.poixson.commonjava.Utils.xCloseableMany; import com.poixson.commonjava.Utils.xTimeU; import com.poixson.commonjava.Utils.exceptions.RequiredArgumentException; import com.poixson.commonjava.Utils.threads.xThreadFactory; import com.poixson.commonjava.xLogger.xLog; / * NetServerManager -> NetServer -> NetServerInitializer ServerSocketState -> NetServerHandler PacketState * / public class NetServerManager implements xCloseableMany { private static final String LOG_NAME = "NET"; // manager instance private static volatile NetServerManager instance = null; private static final Object instanceLock = new Object(); // servers protected final ConcurrentMap<String, NetServer> netServers = new ConcurrentHashMap<String, NetServer>(); // thread groups protected final EventLoopGroup bossGroup; protected final EventLoopGroup workGroup; // firewall protected final NetFirewall firewall; // ssl protected final SslContext sslContext; public static NetServer get(final NetServerConfig netConfig) { if (netConfig == null) throw new RequiredArgumentException("netConfig"); try { return get().getServer(netConfig); } catch (UnknownHostException e) { log().trace(e); return null; } catch (InterruptedException e) { log().trace(e); return null; } } public static NetServerManager get() { if (instance == null) { synchronized(instanceLock) { try { if (instance == null) { instance = new NetServerManager(); } } catch (SSLException e) { instance = null; log().trace(e); return null; } catch (CertificateException e) { instance = null; log().trace(e); return null; } } } return instance; } protected NetServerManager() throws SSLException, CertificateException { Keeper.add(this); // thread groups final int cores = Runtime.getRuntime().availableProcessors(); this.bossGroup = new NioEventLoopGroup(1, new xThreadFactory("netty-boss", true)); this.workGroup = new NioEventLoopGroup(cores, new xThreadFactory("netty-work", true)); // this method is bad for servers // bossGroup = Executors.newCachedThreadPool(); // workGroup = Executors.newCachedThreadPool(); // this method is used in netty examples // bossGroup = new NioEventLoopGroup(); // workGroup = new NioEventLoopGroup(); // firewall this.firewall = new NetFirewall(); // ssl final SelfSignedCertificate cert = new SelfSignedCertificate(); this.sslContext = SslContextBuilder.forServer(cert.certificate(), cert.privateKey()).build(); //TODO: // // ssl packet handler // this.bootstrap.childHandler( // new ServerSocketChannelInitializer(this.log(), this.sslContext) // ); // if (this.log().isLoggable(xLevel.DETAIL)) { // NettyDetailedLogger.Install(this.log()); // } } public NetServer getServer(final NetServerConfig netConfig) throws UnknownHostException, InterruptedException { if (netConfig == null) throw new RequiredArgumentException("netConfig"); final String key = netConfig.toString(); // get existing server { final NetServer server = this.netServers.get(key); if (server != null && !server.isClosed()) { return server; } } // new server synchronized(this.netServers){ // check once more { final NetServer server = this.netServers.get(key); if (server != null) { if (server.isClosed()) { this.ClearClosed(); } else { return server; } } } // new server { final NetServer server = new NetServer(netConfig); this.netServers.put(key, server); return server; } } } // @Override // public void Start() { // if (!this.running.compareAndSet(false, true)) // return; // final Map<String, NetConfig> cfgs = new HashMap<String, NetConfig>(); // synchronized(this.tempConfigs) { // for (final NetConfig cfg : this.tempConfigs) { // final String key = cfg.toString(); // if (utils.isEmpty(key)) continue; // if (cfgs.containsKey(key)) continue; // cfgs.put(key, cfg); // } // } // synchronized(this.servers) { // // stop removed servers // if (!this.servers.isEmpty()) { // final Iterator<Entry<String, NetServer>> it = this.servers.entrySet().iterator(); // while (it.hasNext()) { // final Entry<String, NetServer> entry = it.next(); // // stop no longer needed servers // final NetConfig cfg = cfgs.get(entry.getKey()); // if (cfg == null || !cfg.enabled) { // final NetServer server = entry.getValue(); // utils.safeClose(server); // it.remove(); // } // } // } // // start new servers // if (cfgs.isEmpty()) { // this.log().warning("No socket server configs loaded."); // } else { // this.log().info("Starting socket servers.."); // for (final Entry<String, NetConfig> entry : cfgs.entrySet()) { // final String key = entry.getKey(); // final NetConfig cfg = entry.getValue(); // // server already exists // if (this.servers.containsKey(key)) // continue; // // not enabled // if (!cfg.enabled) // continue; // try { // final NetServer server = new NetServer(cfg); // this.servers.put(key, server); // } catch (UnknownHostException e) { // this.log().severe("Failed to start socket server "+key); // this.log().trace(e); // continue; // } catch (SocketException e) { // if ("Permission denied".equals(e.getMessage())) // this.log().severe("Valid port numbers are >= 1024 for non-root users"); // this.log().trace(e); // } catch (InterruptedException e) { // this.log().severe("Failed to start socket server "+key); // this.log().trace(e); // this.Stop(); // return; // } // } // } // } // // unexpected stop // if (!this.running.get()) // this.Stop(); // } @Override public boolean isClosed() { throw new UnsupportedOperationException(); } @Override public void close() { throw new UnsupportedOperationException(); } @Override public void CloseAll() { if (this.netServers.size() == 0) return; log().info("Closing socket servers.."); int serversCount = 0; int socketsCount = 0; synchronized(this.netServers) { final Collection<NetServer> servers = this.netServers.values(); // close servers { final Set<ChannelFuture> futureCloses = new HashSet<ChannelFuture>(); final Iterator<NetServer> it = servers.iterator(); while (it.hasNext()) { final NetServer server = it.next(); if (!server.isClosed()) serversCount++; futureCloses.add( server.closeSoon() ); } // wait for servers to stop listening for (final ChannelFuture future : futureCloses) { try { future.sync(); } catch (InterruptedException e) { log().trace(e); break; } } } // wait a moment utilsThread.Sleep(50L); // close sockets { log().info("Closing sockets.."); final Iterator<NetServer> it = servers.iterator(); while (it.hasNext()) { final NetServer server = it.next(); socketsCount += server.getSocketsCount(); server.CloseAll(); } } this.ClearClosed(); } if (serversCount > 0) { log().info( (new StringBuilder()) .append("Closed ") .append(serversCount) .append(" socket servers, and ") .append(socketsCount) .append(" sockets") .toString() ); } // stop thread pools this.bossGroup.shutdownGracefully( 500L, 800L, xTimeU.MS ); this.workGroup.shutdownGracefully( 500L, 800L, xTimeU.MS ); } public void ClearClosed() { if (this.netServers.size() == 0) return; synchronized(this.netServers) { final Iterator<NetServer> it = this.netServers.values().iterator(); while (it.hasNext()) { final NetServer server = it.next(); if (server.isClosed()) { this.netServers.remove(server.getServerKey()); } } } } public NetFirewall getFirewall() { return this.firewall; } // logger private static volatile xLog _log = null; public static xLog log() { if (_log == null) { _log = xLog.getRoot(LOG_NAME); } return _log; } } */