io.hekate.network.netty.NettyClientHandshakeHandler.java Source code

Java tutorial

Introduction

Here is the source code for io.hekate.network.netty.NettyClientHandshakeHandler.java

Source

/*
 * Copyright 2019 The Hekate Project
 *
 * The Hekate Project licenses this file to you 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 io.hekate.network.netty;

import io.hekate.network.netty.NetworkProtocol.HandshakeAccept;
import io.hekate.network.netty.NetworkProtocol.HandshakeReject;
import io.hekate.network.netty.NetworkProtocol.HandshakeRequest;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.ssl.SslHandshakeCompletionEvent;
import java.net.ConnectException;
import org.slf4j.Logger;

class NettyClientHandshakeHandler<T> extends SimpleChannelInboundHandler {
    private final Logger log;

    private final boolean debug;

    private final boolean trace;

    private final String id;

    private final String protocol;

    private final int affinity;

    private final T login;

    private final boolean ssl;

    public NettyClientHandshakeHandler(String id, String protocol, int affinity, T login, Logger log, boolean ssl) {
        this.id = id;
        this.protocol = protocol;
        this.affinity = affinity;
        this.login = login;
        this.ssl = ssl;
        this.log = log;
        this.debug = log.isDebugEnabled();
        this.trace = log.isTraceEnabled();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);

        if (ssl) {
            if (trace) {
                log.trace("Deferred handshake until SSL connection is established [to={}]", id);
            }
        } else {
            handshake(ctx);
        }
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof SslHandshakeCompletionEvent) {
            if (((SslHandshakeCompletionEvent) evt).isSuccess()) {
                if (trace) {
                    log.trace("SSL connection established [to={}]", id);
                }

                handshake(ctx);
            }
        }

        super.userEventTriggered(ctx, evt);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        ctx.fireExceptionCaught(new ConnectException("Got disconnected on handshake [channel=" + id + ']'));
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (trace) {
            log.trace("Received handshake response [from={}, message={}]", id, msg);
        }

        NetworkProtocol handshakeMsg = (NetworkProtocol) msg;

        if (handshakeMsg.type() == NetworkProtocol.Type.HANDSHAKE_REJECT) {
            HandshakeReject reject = (HandshakeReject) handshakeMsg;

            String reason = reject.reason();

            if (debug) {
                log.debug("Server rejected connection [to={}, reason={}]", id, reason);
            }

            ctx.fireExceptionCaught(new ConnectException(reason));
        } else {
            HandshakeAccept accept = (HandshakeAccept) handshakeMsg;

            // Unregister self from the pipeline (handshake is a one time event).
            ctx.pipeline().remove(this);

            // Fire handshake event.
            ctx.fireUserEventTriggered(new NettyClientHandshakeEvent(accept));
        }
    }

    private void handshake(ChannelHandlerContext ctx) {
        HandshakeRequest request = new HandshakeRequest(protocol, login, affinity);

        if (trace) {
            log.trace("Connected ...sending handshake request [to={}, from={}, request={}]", id,
                    ctx.channel().localAddress(), request);
        }

        ctx.writeAndFlush(request);
    }
}