package de.jpaw.bonaparte.netty;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LineBasedFrameDecoder;
import io.netty.handler.ssl.SslHandler;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import javax.net.ssl.SSLEngine;
import de.jpaw.bonaparte.core.BonaPortable;
public class BonaparteNettySslPipelineFactory extends ChannelInitializer<SocketChannel> {
private final static int DEFAULT_NUM_THREADS = 12;
private final int maximumMessageLength;
private final SimpleChannelInboundHandler<BonaPortable> objectHandler;
private final boolean useSsl; // if true, enables SSL, otherwise performs exactly as the non-SSL version
private final boolean clientMode; // false
private final boolean needClientAuth; // true
private final ErrorForwarder errorForwarder;
private final DefaultEventExecutorGroup databaseWorkerThreadPool;
public BonaparteNettySslPipelineFactory(int maximumMessageLength, SimpleChannelInboundHandler<BonaPortable> objectHandler, boolean useSsl,
boolean clientMode, boolean needClientAuth, ErrorForwarder errorForwarder) {
this.maximumMessageLength = maximumMessageLength;
this.objectHandler = objectHandler;
this.useSsl = useSsl;
this.clientMode = clientMode;
this.needClientAuth = needClientAuth;
this.errorForwarder = errorForwarder;
this.databaseWorkerThreadPool = new DefaultEventExecutorGroup(DEFAULT_NUM_THREADS);
}
public BonaparteNettySslPipelineFactory(int maximumMessageLength, SimpleChannelInboundHandler<BonaPortable> objectHandler, boolean useSsl,
boolean clientMode, boolean needClientAuth, ErrorForwarder errorForwarder, int numThreads) {
this.maximumMessageLength = maximumMessageLength;
this.objectHandler = objectHandler;
this.useSsl = useSsl;
this.clientMode = clientMode;
this.needClientAuth = needClientAuth;
this.errorForwarder = errorForwarder;
if (numThreads > 1) {
databaseWorkerThreadPool = new DefaultEventExecutorGroup(numThreads);
} else {
databaseWorkerThreadPool = null;
}
}
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
if (useSsl) {
// create the SSL engine
SSLEngine engine = NettySslContextFactory.getServerContext().createSSLEngine();
engine.setUseClientMode(clientMode);
engine.setNeedClientAuth(needClientAuth);
// add ssl to pipeline first, as in the SecureChat example
pipeline.addLast("ssl", new SslHandler(engine));
}
// Add the text line codec combination first,
pipeline.addLast("framer", new LineBasedFrameDecoder(maximumMessageLength, false, false));
// transmission serialization format
pipeline.addLast("decoder", new BonaparteNettyDecoder(errorForwarder));
pipeline.addLast("encoder", new BonaparteNettyEncoder());
// and then business logic.
if (databaseWorkerThreadPool != null)
pipeline.addLast(databaseWorkerThreadPool, "handler", objectHandler); // separate worker pool
else
pipeline.addLast("handler", objectHandler); // do it in the I/O thread
}
}