package net.glowstone.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.EventLoopGroup; import io.netty.channel.epoll.Epoll; import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.epoll.EpollServerSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import net.glowstone.GlowServer; import java.net.InetSocketAddress; import java.util.concurrent.CountDownLatch; public abstract class GlowSocketServer extends GlowNetworkServer { protected final EventLoopGroup bossGroup; protected final EventLoopGroup workerGroup; protected final ServerBootstrap bootstrap; protected Channel channel; public Channel getChannel() { return channel; } public GlowSocketServer(GlowServer server, CountDownLatch latch) { super(server, latch); boolean epoll = Epoll.isAvailable(); bossGroup = epoll ? new EpollEventLoopGroup() : new NioEventLoopGroup(); workerGroup = epoll ? new EpollEventLoopGroup() : new NioEventLoopGroup(); bootstrap = new ServerBootstrap(); bootstrap .group(bossGroup, workerGroup) .channel(epoll ? EpollServerSocketChannel.class : NioServerSocketChannel.class) .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.SO_KEEPALIVE, true); } public ChannelFuture bind(InetSocketAddress address) { ChannelFuture cfuture = this.bootstrap.bind(address).addListener(future -> { if (future.isSuccess()) { onBindSuccess(address); } else { onBindFailure(address, future.cause()); } }); channel = cfuture.channel(); return cfuture; } public void shutdown() { channel.close(); bootstrap.childGroup().shutdownGracefully(); bootstrap.group().shutdownGracefully(); } }