// Copyright © 2011-2013, Esko Luontola <www.orfjackal.net> // This software is released under the Apache License 2.0. // The license text is at http://www.apache.org/licenses/LICENSE-2.0 package fi.jumi.core.network; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.*; import org.jboss.netty.channel.group.DefaultChannelGroup; import org.jboss.netty.channel.socket.oio.OioServerSocketChannelFactory; import org.jboss.netty.handler.codec.serialization.*; import org.jboss.netty.handler.logging.LoggingHandler; import org.jboss.netty.logging.InternalLogLevel; import javax.annotation.concurrent.Immutable; import java.net.InetSocketAddress; import java.util.concurrent.*; @Immutable public class NettyNetworkServer implements NetworkServer { private final DefaultChannelGroup allChannels = new DefaultChannelGroup(); private final InternalLogLevel logLevel; private final ChannelFactory channelFactory; public NettyNetworkServer() { this(false); } public NettyNetworkServer(boolean logging) { this(logging, Executors.newCachedThreadPool()); } public NettyNetworkServer(boolean logging, ExecutorService workerExecutor) { this.logLevel = logging ? InternalLogLevel.INFO : InternalLogLevel.DEBUG; this.channelFactory = new OioServerSocketChannelFactory(workerExecutor, workerExecutor); } @Override public <In, Out> int listenOnAnyPort(NetworkEndpointFactory<In, Out> endpointFactory) { Channel ch = listen(0, endpointFactory); InetSocketAddress addr = (InetSocketAddress) ch.getLocalAddress(); return addr.getPort(); } private <In, Out> Channel listen(int port, NetworkEndpointFactory<In, Out> endpointFactory) { ServerBootstrap bootstrap = new ServerBootstrap(channelFactory); bootstrap.setPipelineFactory( () -> Channels.pipeline( new ObjectEncoder(), new ObjectDecoder(ClassResolvers.softCachingResolver(getClass().getClassLoader())), new LoggingHandler(NettyNetworkServer.class, logLevel), new NettyNetworkEndpointAdapter<>(endpointFactory.createEndpoint()), new AddToChannelGroupHandler(allChannels))); bootstrap.setOption("child.tcpNoDelay", true); bootstrap.setOption("child.keepAlive", true); Channel channel = bootstrap.bind(new InetSocketAddress(port)); allChannels.add(channel); return channel; } @Override public void close() { allChannels.close().awaitUninterruptibly(); channelFactory.releaseExternalResources(); } }