org.jupiter.transport.netty.JNettyTcpConnector.java Source code

Java tutorial

Introduction

Here is the source code for org.jupiter.transport.netty.JNettyTcpConnector.java

Source

/*
 * Copyright (c) 2015 The Jupiter Project
 *
 * 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 org.jupiter.transport.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import org.jupiter.common.util.JConstants;
import org.jupiter.transport.JConnection;
import org.jupiter.transport.JOption;
import org.jupiter.transport.UnresolvedAddress;
import org.jupiter.transport.channel.JChannelGroup;
import org.jupiter.transport.exception.ConnectFailedException;
import org.jupiter.transport.netty.handler.IdleStateChecker;
import org.jupiter.transport.netty.handler.ProtocolDecoder;
import org.jupiter.transport.netty.handler.ProtocolEncoder;
import org.jupiter.transport.netty.handler.connector.ConnectionWatchdog;
import org.jupiter.transport.netty.handler.connector.ConnectorHandler;
import org.jupiter.transport.netty.handler.connector.ConnectorIdleStateTrigger;
import org.jupiter.transport.processor.ConsumerProcessor;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;

import static org.jupiter.common.util.Preconditions.checkNotNull;

/**
 * Jupiter tcp connector based on netty.
 *
 *************************************************************************
 *                                  ?
 *
 *                           Server          
 *                                                  
 *                                  
 *                                                  
 *                                              I/O Response
 *                                                  
 *
 *                                                  
 *                                  
 *                                                                 
 *
 *                                                                 
 *                 ?                  
 *   ConnectionWatchdog#outbound        ConnectionWatchdog#inbound  
 *                                    
 *                                                                  
 *                 
 *                ?                   ?   
 *     IdleStateChecker#outBound         IdleStateChecker#inBound
 *                                      
 *                                                   
 *                                                                  
 *                                                  ?
 *                                     ConnectorIdleStateTrigger    
 *                                                   
 *                                                                 
 *
 *                                                ?   
 *                                            ProtocolDecoder
 *                                                    
 *                                                   
 *                                                                  
 *                                                  ?
 *                                         ConnectorHandler         
 *                 ?                    
 *         ProtocolEncoder                                          
 *                
 *                                                                  
 *                                  
 *                                                   ?
 *                 
 *                                              Processor       
 *                 
 *            I/O Request                            
 *
 *
 * jupiter
 * org.jupiter.transport.netty
 *
 * @author jiachun.fjc
 */
public class JNettyTcpConnector extends NettyTcpConnector {

    // handlers
    private final ConnectorIdleStateTrigger idleStateTrigger = new ConnectorIdleStateTrigger();
    private final ProtocolEncoder encoder = new ProtocolEncoder();
    private final ConnectorHandler handler = new ConnectorHandler();

    public JNettyTcpConnector() {
    }

    public JNettyTcpConnector(boolean nativeEt) {
        super(nativeEt);
    }

    public JNettyTcpConnector(int nWorkers) {
        super(nWorkers);
    }

    public JNettyTcpConnector(int nWorkers, boolean nativeEt) {
        super(nWorkers, nativeEt);
    }

    @Override
    protected void doInit() {
        // child options
        config().setOption(JOption.SO_REUSEADDR, true);
        config().setOption(JOption.CONNECT_TIMEOUT_MILLIS, (int) TimeUnit.SECONDS.toMillis(3));
        // channel factory
        if (isNativeEt()) {
            bootstrap().channelFactory(TcpChannelProvider.NATIVE_CONNECTOR);
        } else {
            bootstrap().channelFactory(TcpChannelProvider.NIO_CONNECTOR);
        }
    }

    @Override
    public void withProcessor(ConsumerProcessor processor) {
        handler.processor(checkNotNull(processor, "processor"));
    }

    @Override
    public JConnection connect(UnresolvedAddress address, boolean async) {
        setOptions();

        final Bootstrap boot = bootstrap();
        final SocketAddress socketAddress = InetSocketAddress.createUnresolved(address.getHost(),
                address.getPort());
        final JChannelGroup group = group(address);

        // ?watchdog
        final ConnectionWatchdog watchdog = new ConnectionWatchdog(boot, timer, socketAddress, group) {

            @Override
            public ChannelHandler[] handlers() {
                return new ChannelHandler[] { this,
                        new IdleStateChecker(timer, 0, JConstants.WRITER_IDLE_TIME_SECONDS, 0), idleStateTrigger,
                        new ProtocolDecoder(), encoder, handler };
            }
        };
        watchdog.start();

        ChannelFuture future;
        try {
            synchronized (bootstrapLock()) {
                boot.handler(new ChannelInitializer<Channel>() {

                    @Override
                    protected void initChannel(Channel ch) throws Exception {
                        ch.pipeline().addLast(watchdog.handlers());
                    }
                });

                future = boot.connect(socketAddress);
            }

            // ?synchronized???
            if (!async) {
                future.sync();
            }
        } catch (Throwable t) {
            throw new ConnectFailedException("connects to [" + address + "] fails", t);
        }

        return new JNettyConnection(address, future) {

            @Override
            public void setReconnect(boolean reconnect) {
                if (reconnect) {
                    watchdog.start();
                } else {
                    watchdog.stop();
                }
            }
        };
    }
}