Example usage for io.netty.handler.ssl SslHandler handshakeFuture

List of usage examples for io.netty.handler.ssl SslHandler handshakeFuture

Introduction

In this page you can find the example usage for io.netty.handler.ssl SslHandler handshakeFuture.

Prototype

public Future<Channel> handshakeFuture() 

Source Link

Document

Returns a Future that will get notified once the current TLS handshake completes.

Usage

From source file:org.eclipse.californium.elements.tcp.TlsClientConnector.java

License:Open Source License

/**
 * {@inheritDoc}//from   ww w .j  a v a2s.  co  m
 * 
 * Delay message sending after TLS handshake is completed.
 */
@Override
protected void send(final Channel channel, final EndpointContextMatcher endpointMatcher, final RawData msg) {
    final SslHandler sslHandler = channel.pipeline().get(SslHandler.class);
    if (sslHandler == null) {
        msg.onError(new IllegalStateException("Missing SslHandler"));
    } else {
        /*
         * Trigger handshake.
         */
        Future<Channel> handshakeFuture = sslHandler.handshakeFuture();
        handshakeFuture.addListener(new GenericFutureListener<Future<Channel>>() {

            @Override
            public void operationComplete(Future<Channel> future) throws Exception {
                if (future.isSuccess()) {
                    EndpointContext context = contextUtil.buildEndpointContext(channel);
                    if (context == null || context.get(TlsEndpointContext.KEY_SESSION_ID) == null) {
                        msg.onError(new IllegalStateException("Missing TlsEndpointContext " + context));
                        return;
                    }
                    /*
                     * Handshake succeeded! 
                     * Call super.send() to actually send the message.
                     */
                    TlsClientConnector.super.send(future.getNow(), endpointMatcher, msg);
                } else if (future.isCancelled()) {
                    msg.onError(new CancellationException());
                } else {
                    msg.onError(future.cause());
                }
            }
        });
    }
}

From source file:org.hornetq.core.remoting.impl.netty.NettyConnector.java

License:Apache License

public Connection createConnection() {
    if (channelClazz == null) {
        return null;
    }/*from   w  ww .j  ava 2s  .  c  o m*/

    // HORNETQ-907 - strip off IPv6 scope-id (if necessary)
    SocketAddress remoteDestination = new InetSocketAddress(host, port);
    InetAddress inetAddress = ((InetSocketAddress) remoteDestination).getAddress();
    if (inetAddress instanceof Inet6Address) {
        Inet6Address inet6Address = (Inet6Address) inetAddress;
        if (inet6Address.getScopeId() != 0) {
            try {
                remoteDestination = new InetSocketAddress(InetAddress.getByAddress(inet6Address.getAddress()),
                        ((InetSocketAddress) remoteDestination).getPort());
            } catch (UnknownHostException e) {
                throw new IllegalArgumentException(e.getMessage());
            }
        }
    }

    HornetQClientLogger.LOGGER.debug("Remote destination: " + remoteDestination);

    ChannelFuture future;
    //port 0 does not work so only use local address if set
    if (localPort != 0) {
        SocketAddress localDestination;
        if (localAddress != null) {
            localDestination = new InetSocketAddress(localAddress, localPort);
        } else {
            localDestination = new InetSocketAddress(localPort);
        }
        future = bootstrap.connect(remoteDestination, localDestination);
    } else {
        future = bootstrap.connect(remoteDestination);
    }

    future.awaitUninterruptibly();

    if (future.isSuccess()) {
        final Channel ch = future.channel();
        SslHandler sslHandler = ch.pipeline().get(SslHandler.class);
        if (sslHandler != null) {
            Future<Channel> handshakeFuture = sslHandler.handshakeFuture();
            if (handshakeFuture.awaitUninterruptibly(30000)) {
                if (handshakeFuture.isSuccess()) {
                    ChannelPipeline channelPipeline = ch.pipeline();
                    HornetQChannelHandler channelHandler = channelPipeline.get(HornetQChannelHandler.class);
                    channelHandler.active = true;
                } else {
                    ch.close().awaitUninterruptibly();
                    HornetQClientLogger.LOGGER.errorCreatingNettyConnection(handshakeFuture.cause());
                    return null;
                }
            } else {
                //handshakeFuture.setFailure(new SSLException("Handshake was not completed in 30 seconds"));
                ch.close().awaitUninterruptibly();
                return null;
            }

        }
        if (httpUpgradeEnabled) {
            // Send a HTTP GET + Upgrade request that will be handled by the http-upgrade handler.
            try {
                //get this first incase it removes itself
                HttpUpgradeHandler httpUpgradeHandler = (HttpUpgradeHandler) ch.pipeline().get("http-upgrade");
                URI uri = new URI("http", null, host, port, null, null, null);
                HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET,
                        uri.getRawPath());
                request.headers().set(HttpHeaders.Names.HOST, host);
                request.headers().set(HttpHeaders.Names.UPGRADE, HORNETQ_REMOTING);
                request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.UPGRADE);

                final String endpoint = ConfigurationHelper.getStringProperty(
                        TransportConstants.HTTP_UPGRADE_ENDPOINT_PROP_NAME, null, configuration);
                if (endpoint != null) {
                    request.headers().set(TransportConstants.HTTP_UPGRADE_ENDPOINT_PROP_NAME, endpoint);
                }

                // Get 16 bit nonce and base 64 encode it
                byte[] nonce = randomBytes(16);
                String key = base64(nonce);
                request.headers().set(SEC_HORNETQ_REMOTING_KEY, key);
                ch.attr(REMOTING_KEY).set(key);

                HornetQClientLogger.LOGGER.debugf("Sending HTTP request %s", request);

                // Send the HTTP request.
                ch.writeAndFlush(request);

                if (!httpUpgradeHandler.awaitHandshake()) {
                    return null;
                }
            } catch (URISyntaxException e) {
                HornetQClientLogger.LOGGER.errorCreatingNettyConnection(e);
                return null;
            }
        } else {
            ChannelPipeline channelPipeline = ch.pipeline();
            HornetQChannelHandler channelHandler = channelPipeline.get(HornetQChannelHandler.class);
            channelHandler.active = true;
        }

        // No acceptor on a client connection
        Listener connectionListener = new Listener();
        NettyConnection conn = new NettyConnection(configuration, ch, connectionListener,
                !httpEnabled && batchDelay > 0, false);
        connectionListener.connectionCreated(null, conn, HornetQClient.DEFAULT_CORE_PROTOCOL);
        return conn;
    } else {
        Throwable t = future.cause();

        if (t != null && !(t instanceof ConnectException)) {
            HornetQClientLogger.LOGGER.errorCreatingNettyConnection(future.cause());
        }

        return null;
    }
}

From source file:org.jboss.aerogear.webpush.WebPushClientInitializer.java

License:Apache License

/**
 * Configure the pipeline for ALPN negotiation to HTTP/2.
 *//*from   w  w  w.  j  a va 2 s  .  c o m*/
private void configureSsl(SocketChannel ch) {
    ChannelPipeline pipeline = ch.pipeline();
    final SslHandler sslHandler = sslCtx.newHandler(ch.alloc(), host, port);
    sslHandler.handshakeFuture().addListener(new SslHandshakeListener(callback));
    pipeline.addLast("SslHandler", sslHandler);
    pipeline.addLast("Http2Handler", connectionHandler);
    ch.pipeline().addLast("Logger", new UserEventLogger(callback));
    configureEndOfPipeline(pipeline);
}

From source file:org.jdiameter.client.impl.transport.tls.netty.StartTlsClientHandler.java

License:Open Source License

@SuppressWarnings("unchecked")
@Override/*ww w  .  j a  va  2  s .c o  m*/
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
    logger.debug("StartTlsClientHandler");
    ByteBuf buf = (ByteBuf) msg;
    byte[] bytes = new byte[buf.readableBytes()];
    buf.getBytes(buf.readerIndex(), bytes);

    if ("StartTlsResponse".equals(new String(bytes))) {
        logger.debug("received StartTlsResponse");

        SslContext sslContext = SslContextFactory.getSslContextForClient(this.tlsTransportClient.getConfig());
        SSLEngine sslEngine = sslContext.newEngine(ctx.alloc());
        sslEngine.setUseClientMode(true);
        SslHandler sslHandler = new SslHandler(sslEngine, false);

        final ChannelPipeline pipeline = ctx.pipeline();
        pipeline.remove("startTlsClientHandler");
        pipeline.addLast("sslHandler", sslHandler);

        logger.debug("StartTls starting handshake");

        sslHandler.handshakeFuture().addListener(new GenericFutureListener() {
            @Override
            public void operationComplete(Future future) throws Exception {
                if (future.isSuccess()) {
                    logger.debug("StartTls handshake succesfull");

                    tlsTransportClient.setTlsHandshakingState(TlsHandshakingState.SHAKEN);

                    logger.debug("restoring all handlers");

                    pipeline.addLast("decoder",
                            new DiameterMessageDecoder(
                                    StartTlsClientHandler.this.tlsTransportClient.getParent(),
                                    StartTlsClientHandler.this.tlsTransportClient.getParser()));
                    pipeline.addLast("msgHandler", new DiameterMessageHandler(
                            StartTlsClientHandler.this.tlsTransportClient.getParent(), true));

                    pipeline.addLast("encoder", new DiameterMessageEncoder(
                            StartTlsClientHandler.this.tlsTransportClient.getParser()));
                    pipeline.addLast("inbandWriter", new InbandSecurityHandler());
                }
            }
        });

    }
}

From source file:org.jdiameter.client.impl.transport.tls.netty.StartTlsServerHandler.java

License:Open Source License

@SuppressWarnings({ "unchecked", "rawtypes" })
@Override/*from w  ww . j av a2s  .  c  o  m*/
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    logger.debug("StartTlsServerHandler");
    ByteBuf buf = (ByteBuf) msg;
    byte[] bytes = new byte[buf.readableBytes()];
    buf.getBytes(buf.readerIndex(), bytes);

    if ("StartTlsRequest".equals(new String(bytes))) {
        logger.debug("Received StartTlsRequest");
        SslContext sslContext = SslContextFactory.getSslContextForServer(this.tlsTransportClient.getConfig());
        SSLEngine sslEngine = sslContext.newEngine(ctx.alloc());
        sslEngine.setUseClientMode(false);
        SslHandler sslHandler = new SslHandler(sslEngine, false);

        final ChannelPipeline pipeline = ctx.pipeline();

        pipeline.remove("decoder");
        pipeline.remove("msgHandler");
        pipeline.remove("encoder");
        pipeline.remove("inbandWriter");
        pipeline.remove(this);

        pipeline.addLast("sslHandler", sslHandler);

        sslHandler.handshakeFuture().addListener(new GenericFutureListener() {

            @Override
            public void operationComplete(Future future) throws Exception {
                if (future.isSuccess()) {
                    logger.debug("StartTls server handshake succesfull");

                    tlsTransportClient.setTlsHandshakingState(TlsHandshakingState.SHAKEN);

                    logger.debug("restoring all handlers");

                    pipeline.addLast("decoder",
                            new DiameterMessageDecoder(
                                    StartTlsServerHandler.this.tlsTransportClient.getParent(),
                                    StartTlsServerHandler.this.tlsTransportClient.getParser()));
                    pipeline.addLast("msgHandler", new DiameterMessageHandler(
                            StartTlsServerHandler.this.tlsTransportClient.getParent(), true));

                    pipeline.addLast("encoder", new DiameterMessageEncoder(
                            StartTlsServerHandler.this.tlsTransportClient.getParser()));
                    pipeline.addLast("inbandWriter", new InbandSecurityHandler());

                }
            }
        });

        ReferenceCountUtil.release(msg);
        logger.debug("Sending StartTlsResponse");
        ctx.writeAndFlush(Unpooled.wrappedBuffer("StartTlsResponse".getBytes()))
                .addListener(new GenericFutureListener() {

                    @Override
                    public void operationComplete(Future f) throws Exception {
                        if (!f.isSuccess()) {
                            logger.error(f.cause().getMessage(), f.cause());
                        }

                    }
                });
    } else {
        ctx.fireChannelRead(msg);
    }

}

From source file:org.opendaylight.openflowjava.protocol.impl.core.TcpChannelInitializer.java

License:Open Source License

@Override
protected void initChannel(final SocketChannel ch) {
    if (ch.remoteAddress() != null) {
        final InetAddress switchAddress = ch.remoteAddress().getAddress();
        final int port = ch.localAddress().getPort();
        final int remotePort = ch.remoteAddress().getPort();
        LOG.debug("Incoming connection from (remote address): {}:{} --> :{}", switchAddress.toString(),
                remotePort, port);/*  w  w  w  .  j  a  va  2 s  .  co m*/

        if (!getSwitchConnectionHandler().accept(switchAddress)) {
            ch.disconnect();
            LOG.debug("Incoming connection rejected");
            return;
        }
    }
    LOG.debug("Incoming connection accepted - building pipeline");
    allChannels.add(ch);
    ConnectionFacade connectionFacade = null;
    connectionFacade = connectionAdapterFactory.createConnectionFacade(ch, null, useBarrier());
    try {
        LOG.debug("Calling OF plugin: {}", getSwitchConnectionHandler());
        getSwitchConnectionHandler().onSwitchConnected(connectionFacade);
        connectionFacade.checkListeners();
        ch.pipeline().addLast(PipelineHandlers.IDLE_HANDLER.name(),
                new IdleHandler(getSwitchIdleTimeout(), TimeUnit.MILLISECONDS));
        boolean tlsPresent = false;

        // If this channel is configured to support SSL it will only support SSL
        if (getTlsConfiguration() != null) {
            tlsPresent = true;
            final SslContextFactory sslFactory = new SslContextFactory(getTlsConfiguration());
            final SSLEngine engine = sslFactory.getServerContext().createSSLEngine();
            engine.setNeedClientAuth(true);
            engine.setUseClientMode(false);
            List<String> suitesList = getTlsConfiguration().getCipherSuites();
            if (suitesList != null && !suitesList.isEmpty()) {
                LOG.debug("Requested Cipher Suites are: {}", suitesList);
                String[] suites = suitesList.toArray(new String[suitesList.size()]);
                engine.setEnabledCipherSuites(suites);
                LOG.debug("Cipher suites enabled in SSLEngine are: {}",
                        engine.getEnabledCipherSuites().toString());
            }
            final SslHandler ssl = new SslHandler(engine);
            final Future<Channel> handshakeFuture = ssl.handshakeFuture();
            final ConnectionFacade finalConnectionFacade = connectionFacade;
            handshakeFuture.addListener(new GenericFutureListener<Future<? super Channel>>() {
                @Override
                public void operationComplete(final Future<? super Channel> future) throws Exception {
                    finalConnectionFacade.fireConnectionReadyNotification();
                }
            });
            ch.pipeline().addLast(PipelineHandlers.SSL_HANDLER.name(), ssl);
        }
        ch.pipeline().addLast(PipelineHandlers.OF_FRAME_DECODER.name(),
                new OFFrameDecoder(connectionFacade, tlsPresent));
        ch.pipeline().addLast(PipelineHandlers.OF_VERSION_DETECTOR.name(), new OFVersionDetector());
        final OFDecoder ofDecoder = new OFDecoder();
        ofDecoder.setDeserializationFactory(getDeserializationFactory());
        ch.pipeline().addLast(PipelineHandlers.OF_DECODER.name(), ofDecoder);
        final OFEncoder ofEncoder = new OFEncoder();
        ofEncoder.setSerializationFactory(getSerializationFactory());
        ch.pipeline().addLast(PipelineHandlers.OF_ENCODER.name(), ofEncoder);
        ch.pipeline().addLast(PipelineHandlers.DELEGATING_INBOUND_HANDLER.name(),
                new DelegatingInboundHandler(connectionFacade));
        if (!tlsPresent) {
            connectionFacade.fireConnectionReadyNotification();
        }
    } catch (final Exception e) {
        LOG.warn("Failed to initialize channel", e);
        ch.close();
    }
}

From source file:org.ow2.petals.bc.gateway.commons.handlers.AuthenticatorSSLHandler.java

License:Open Source License

private void setUpSslHandlers(final ChannelHandlerContext ctx, final AbstractDomain domain,
        final @Nullable String certificate, final @Nullable String key, final @Nullable String passphrase,
        final @Nullable String remoteCertificate) throws SSLException {

    // TODO could we use certificate only for auth and not encryption?
    // TODO support openssl
    final SslHandler sslHandler;
    if (pdOrAuth.isB() && certificate != null && key != null) {
        // server side ssl, do not forget startTls so that our accept can be sent after the handler is added

        final ServiceUnitDataHandler handler = domain.getSUHandler();

        final SslContextBuilder builder = SslContextBuilder
                .forServer(ServiceUnitUtil.getFile(handler.getInstallRoot(), certificate),
                        ServiceUnitUtil.getFile(handler.getInstallRoot(), key), passphrase)
                .sslProvider(SslProvider.JDK).ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
                .sessionCacheSize(0).sessionTimeout(0);

        if (remoteCertificate != null) {
            builder.trustManager(ServiceUnitUtil.getFile(handler.getInstallRoot(), remoteCertificate))
                    .clientAuth(ClientAuth.REQUIRE);
        }/*www.  ja  v  a  2  s  . co m*/

        // until https://github.com/netty/netty/issues/5170 is accepted
        // we need to create the handler by hand
        sslHandler = new SslHandler(builder.build().newEngine(ctx.alloc()), true);
    } else if (pdOrAuth.isA() && remoteCertificate != null) {
        // client side

        final String installRoot = domain.getSUHandler().getInstallRoot();
        final SslContextBuilder builder = SslContextBuilder.forClient().sslProvider(SslProvider.JDK)
                .trustManager(ServiceUnitUtil.getFile(installRoot, remoteCertificate))
                .ciphers(null, IdentityCipherSuiteFilter.INSTANCE).sessionCacheSize(0).sessionTimeout(0);

        if (certificate != null && key != null) {
            builder.keyManager(ServiceUnitUtil.getFile(installRoot, certificate),
                    ServiceUnitUtil.getFile(installRoot, key), passphrase);
        }

        sslHandler = builder.build().newHandler(ctx.alloc());
    } else {
        sslHandler = null;
    }

    // For a server, it contains the transporter name and the consumer domain name (it was updated in channelRead0)
    // For a client, it contains the provider domain name (it was set by the component)
    final String logName = logger.getName();

    // let's replace the debug logger with something specific to this consumer
    ctx.pipeline().replace(HandlerConstants.LOG_DEBUG_HANDLER, HandlerConstants.LOG_DEBUG_HANDLER,
            new LoggingHandler(logName, LogLevel.TRACE));

    ctx.pipeline().replace(HandlerConstants.LOG_ERRORS_HANDLER, HandlerConstants.LOG_ERRORS_HANDLER,
            new LastLoggingHandler(logName + ".errors"));

    if (sslHandler != null) {
        // if there is a sslHandler, then we can only add the domain handler after the handshake is finished
        // if not we risk sending things too early in it

        sslHandler.handshakeFuture().addListener(new FutureListener<Channel>() {
            @Override
            public void operationComplete(final @Nullable Future<Channel> future) throws Exception {
                assert future != null;
                if (!future.isSuccess()) {
                    authenticationFuture.setFailure(future.cause());
                } else {
                    // I must keep the handler here until now in case there is an exception so that I can log it
                    ctx.pipeline().replace(HandlerConstants.DOMAIN_HANDLER, HandlerConstants.DOMAIN_HANDLER,
                            dhb.build(domain));
                    authenticationFuture.setSuccess(ctx.channel());
                }
            }
        });

        ctx.pipeline().addAfter(HandlerConstants.LOG_DEBUG_HANDLER, HandlerConstants.SSL_HANDLER, sslHandler);
    }

    if (pdOrAuth.isB()) {
        if (logger.isLoggable(Level.FINE)) {
            logger.fine("Sending an Accept (" + ctx.channel().remoteAddress() + ")");
        }

        // this must be sent after the ssh handler is replaced (when using ssl) so that we are ready to receive ssl data right away
        // but this must be sent before the domain handler is replaced (when not using ssl), because it will send
        // data and it must arrive AFTER our Accept
        ctx.writeAndFlush(new AuthAccept());
    }

    // else it is done in the FutureListener
    if (sslHandler == null) {
        ctx.pipeline().replace(HandlerConstants.DOMAIN_HANDLER, HandlerConstants.DOMAIN_HANDLER,
                dhb.build(domain));
        authenticationFuture.setSuccess(ctx.channel());
    }
}

From source file:org.teiid.transport.SSLAwareChannelHandler.java

License:Apache License

@Override
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
    ChannelListener listener = this.listenerFactory.createChannelListener(new ObjectChannelImpl(ctx.channel()));
    this.listeners.put(ctx.channel(), listener);
    maxChannels = Math.max(maxChannels, this.listeners.size());
    SslHandler sslHandler = ctx.pipeline().get(SslHandler.class);
    if (sslHandler != null) {
        sslHandler.handshakeFuture().addListener(new GenericFutureListener<DefaultPromise<Channel>>() {
            @Override/*from  www. j ava 2s. c o m*/
            public void operationComplete(DefaultPromise<Channel> future) throws Exception {
                onConnection(ctx.channel());

            }
        });
    } else {
        onConnection(ctx.channel());
    }
}

From source file:org.vertx.java.core.http.impl.DefaultHttpClient.java

License:Open Source License

void internalConnect(final Handler<ClientConnection> connectHandler,
        final Handler<Throwable> connectErrorHandler) {
    if (bootstrap == null) {
        // Share the event loop thread to also serve the HttpClient's network traffic.
        VertxEventLoopGroup pool = new VertxEventLoopGroup();
        pool.addWorker(actualCtx.getEventLoop());
        bootstrap = new Bootstrap();
        bootstrap.group(pool);//from  ww  w  . j a v  a 2  s .c om
        bootstrap.channel(NioSocketChannel.class);
        tcpHelper.checkSSL(vertx);

        bootstrap.handler(new ChannelInitializer<Channel>() {
            @Override
            protected void initChannel(Channel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                if (tcpHelper.isSSL()) {
                    SSLEngine engine = tcpHelper.getSSLContext().createSSLEngine(host, port);
                    if (tcpHelper.isVerifyHost()) {
                        SSLParameters sslParameters = engine.getSSLParameters();
                        sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
                        engine.setSSLParameters(sslParameters);
                    }
                    engine.setUseClientMode(true); //We are on the client side of the connection
                    pipeline.addLast("ssl", new SslHandler(engine));
                }

                pipeline.addLast("codec", new HttpClientCodec(4096, 8192, 8192, false, false));
                if (tryUseCompression) {
                    pipeline.addLast("inflater", new HttpContentDecompressor(true));
                }
                pipeline.addLast("handler", new ClientHandler());
            }
        });
    }
    tcpHelper.applyConnectionOptions(bootstrap);
    ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
    future.addListener(new ChannelFutureListener() {
        public void operationComplete(ChannelFuture channelFuture) throws Exception {
            final Channel ch = channelFuture.channel();
            if (channelFuture.isSuccess()) {
                if (tcpHelper.isSSL()) {
                    // TCP connected, so now we must do the SSL handshake

                    SslHandler sslHandler = ch.pipeline().get(SslHandler.class);

                    Future<Channel> fut = sslHandler.handshakeFuture();
                    fut.addListener(new GenericFutureListener<Future<Channel>>() {
                        @Override
                        public void operationComplete(Future<Channel> future) throws Exception {
                            if (future.isSuccess()) {
                                connected(ch, connectHandler);
                            } else {
                                connectionFailed(ch, connectErrorHandler,
                                        new SSLHandshakeException("Failed to create SSL connection"));
                            }
                        }
                    });
                } else {
                    connected(ch, connectHandler);
                }
            } else {
                connectionFailed(ch, connectErrorHandler, channelFuture.cause());
            }
        }
    });
}

From source file:org.vertx.java.core.net.impl.DefaultNetClient.java

License:Open Source License

private void connect(final int port, final String host, final Handler<AsyncResult<NetSocket>> connectHandler,
        final int remainingAttempts) {
    if (bootstrap == null) {
        tcpHelper.checkSSL(vertx);/*from ww  w .  jav a  2s  . c  o m*/

        bootstrap = new Bootstrap();
        bootstrap.group(actualCtx.getEventLoop());
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.handler(new ChannelInitializer<Channel>() {
            @Override
            protected void initChannel(Channel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                if (tcpHelper.isSSL()) {
                    SslHandler sslHandler = tcpHelper.createSslHandler(vertx, true);
                    pipeline.addLast("ssl", sslHandler);
                }
                if (tcpHelper.isSSL()) {
                    // only add ChunkedWriteHandler when SSL is enabled otherwise it is not needed as FileRegion is used.
                    pipeline.addLast("chunkedWriter", new ChunkedWriteHandler()); // For large file / sendfile support
                }
                pipeline.addLast("handler", new VertxNetHandler(vertx, socketMap));
            }
        });
        configurable = false;
    }
    tcpHelper.applyConnectionOptions(bootstrap);
    ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
    future.addListener(new ChannelFutureListener() {
        public void operationComplete(ChannelFuture channelFuture) throws Exception {
            final Channel ch = channelFuture.channel();

            if (channelFuture.isSuccess()) {

                if (tcpHelper.isSSL()) {
                    // TCP connected, so now we must do the SSL handshake

                    SslHandler sslHandler = ch.pipeline().get(SslHandler.class);

                    Future<Channel> fut = sslHandler.handshakeFuture();
                    fut.addListener(new GenericFutureListener<Future<Channel>>() {
                        @Override
                        public void operationComplete(Future<Channel> future) throws Exception {
                            if (future.isSuccess()) {
                                connected(ch, connectHandler);
                            } else {
                                failed(ch, future.cause(), connectHandler);
                            }
                        }
                    });
                } else {
                    connected(ch, connectHandler);
                }
            } else {
                if (remainingAttempts > 0 || remainingAttempts == -1) {
                    actualCtx.execute(ch.eventLoop(), new Runnable() {
                        public void run() {
                            log.debug("Failed to create connection. Will retry in " + reconnectInterval
                                    + " milliseconds");
                            //Set a timer to retry connection
                            vertx.setTimer(reconnectInterval, new Handler<Long>() {
                                public void handle(Long timerID) {
                                    connect(port, host, connectHandler,
                                            remainingAttempts == -1 ? remainingAttempts
                                                    : remainingAttempts - 1);
                                }
                            });
                        }
                    });
                } else {
                    failed(ch, channelFuture.cause(), connectHandler);
                }
            }
        }
    });
}