com.hazelcast.openshift.TunnelClientAcceptor.java Source code

Java tutorial

Introduction

Here is the source code for com.hazelcast.openshift.TunnelClientAcceptor.java

Source

/*
 * Copyright (c) 2008-2015, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hazelcast.openshift;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;

class TunnelClientAcceptor extends SimpleChannelInboundHandler<HttpRequest> {

    private final EventLoopGroup workerGroup;
    private final String forwardHost;
    private final int forwardPort;

    TunnelClientAcceptor(EventLoopGroup workerGroup, String forwardHost, int forwardPort) {
        this.workerGroup = workerGroup;
        this.forwardHost = forwardHost;
        this.forwardPort = forwardPort;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpRequest msg) throws Exception {
        HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
        ctx.writeAndFlush(response).sync();

        ChannelPipeline pipeline = ctx.pipeline();

        Channel forward = createRemoteChannel(ctx.channel());
        if (forward == null) {
            ctx.close();
            return;
        }

        forward.closeFuture().addListener(f -> ctx.close());
        ctx.channel().closeFuture().addListener(f -> forward.close());

        pipeline.addLast(new ProxyForwardHandler(forward));
        pipeline.remove(HttpRequestDecoder.class);
        pipeline.remove(HttpResponseEncoder.class);
        pipeline.remove(this);
    }

    private Channel createRemoteChannel(Channel socket) throws Exception {
        Bootstrap bootstrap = createBootstrap(socket);
        ChannelFuture connectFuture = bootstrap.connect(forwardHost, forwardPort);
        ChannelFuture future = connectFuture.sync();
        if (!future.isSuccess()) {
            return null;
        }

        return future.channel();
    }

    protected Bootstrap createBootstrap(Channel socket) {
        return new Bootstrap().channel(NioSocketChannel.class).group(workerGroup)
                .option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer<SocketChannel>() {

                    @Override
                    protected void initChannel(SocketChannel channel) throws Exception {
                        System.out.println("Configure plain-socket: (" + socket + ") => (" + forwardHost + ":"
                                + forwardPort + ")");
                        ChannelPipeline pipeline = channel.pipeline();
                        pipeline.addLast(new ProxyForwardHandler(socket));
                    }
                });
    }
}