package org.openslx.imagemaster.thrift.server; import java.security.NoSuchAlgorithmException; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import org.apache.log4j.Logger; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.server.THsHaServer; import org.apache.thrift.server.TServer; import org.apache.thrift.server.TThreadPoolServer; import org.apache.thrift.transport.TFramedTransport; import org.apache.thrift.transport.TNonblockingServerSocket; import org.apache.thrift.transport.TNonblockingServerTransport; import org.apache.thrift.transport.TSSLTransportFactory; import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters; import org.apache.thrift.transport.TServerTransport; import org.apache.thrift.transport.TTransportException; import org.openslx.bwlp.thrift.iface.MasterServer; import org.openslx.imagemaster.Globals; import org.openslx.thrifthelper.TBinaryProtocolSafe; public class BinaryListener implements Runnable { private static final int MAX_MSG_LEN = 30 * 1000 * 1000; private final MasterServer.Processor processor = new MasterServer.Processor( new MasterServerHandler() ); final TProtocolFactory protFactory = new TBinaryProtocolSafe.Factory( true, true ); private static Logger log = Logger.getLogger( BinaryListener.class ); final TServer server; @Override public void run() { log.info( "Starting Binary Thrift" ); server.serve(); log.info( "Stopped Binary Thrift" ); System.exit( 1 ); // Exit so the server can fully restart } public BinaryListener( int port, boolean secure ) throws TTransportException, NoSuchAlgorithmException { if ( secure ) server = initSecure( port ); else server = initNormal( port ); } /** * Listen with TLS wrapping - has to use the thread pool server, since encrypted * servers cannot use nonblocking sockets :( * * @param port listen port * @return the server * @throws NoSuchAlgorithmException * @throws TTransportException */ private TServer initSecure( int port ) throws NoSuchAlgorithmException, TTransportException { SSLContext context = SSLContext.getDefault(); SSLSocketFactory sf = context.getSocketFactory(); String[] cipherSuites = sf.getSupportedCipherSuites(); // TODO: Remove insecure ones final TSSLTransportParameters params = new TSSLTransportParameters( "TLSv1.2", cipherSuites ); params.setKeyStore( Globals.getSslKeystoreFile(), Globals.getSslKeystorePassword() ); TServerTransport serverTransport; try { serverTransport = TSSLTransportFactory.getServerSocket( port, 0, null, params ); } catch ( TTransportException e ) { log.fatal( "Could not listen on port " + port ); throw e; } TThreadPoolServer.Args args = new TThreadPoolServer.Args( serverTransport ); args.protocolFactory( protFactory ); args.processor( processor ); args.minWorkerThreads( 4 ).maxWorkerThreads( 256 ); args.requestTimeout( 2 ).requestTimeoutUnit( TimeUnit.MINUTES ); args.transportFactory( new TFramedTransport.Factory( MAX_MSG_LEN ) ); return new TThreadPoolServer( args ); } /** * Create normal plain server, no encryption. * * @param port listen port * @return server instance * @throws TTransportException */ public TServer initNormal( int port ) throws TTransportException { final TNonblockingServerTransport serverTransport; try { serverTransport = new TNonblockingServerSocket( port ); } catch ( TTransportException e ) { log.fatal( "Could not listen on port " + port ); throw e; } THsHaServer.Args args = new THsHaServer.Args( serverTransport ); args.protocolFactory( protFactory ); args.processor( processor ); args.minWorkerThreads( 2 ).maxWorkerThreads( 6 ); args.maxReadBufferBytes = MAX_MSG_LEN; return new THsHaServer( args ); } }