nss.delta.agentmanager.dummycon.OFChannelInitializer.java Source code

Java tutorial

Introduction

Here is the source code for nss.delta.agentmanager.dummycon.OFChannelInitializer.java

Source

package nss.delta.agentmanager.dummycon;

/**
 *    Copyright 2011, Big Switch Networks, Inc.
 *    Originally created by David Erickson, Stanford University
 *
 *    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.
 **/

import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.types.U32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.util.Timer;
import nss.delta.agentmanager.utils.OFMessageDecoder;
import nss.delta.agentmanager.utils.OFMessageEncoder;

/**
 * Creates a ChannelPipeline for a server-side openflow channel
 * 
 * @author readams, sovietaced, rizard, andi-bigswitch
 */
public class OFChannelInitializer extends ChannelInitializer<Channel> {
    private static final Logger log = LoggerFactory.getLogger(OFChannelInitializer.class);

    // private IOFSwitchManager switchManager;
    // private INewOFConnectionListener connectionListener;
    // private IDebugCounterService debugCounters;

    private Timer timer;

    private String keyStore;
    private String keyStorePassword;
    private OFFactory defaultFactory;
    private List<U32> ofBitmaps;

    private ArrayList<OFChannelHandler> handlerlist;
    private OFChannelHandler handler;

    private int testHandShake;

    public OFChannelInitializer(Timer timer, List<U32> ofBitmaps, OFFactory defaultFactory, int handshake) {
        super();
        // this.switchManager = switchManager;
        // this.connectionListener = connectionListener;
        this.timer = timer;
        // this.debugCounters = debugCounters;
        this.defaultFactory = defaultFactory;
        this.ofBitmaps = ofBitmaps;

        this.handlerlist = new ArrayList<OFChannelHandler>();
        log.info("OFChannel Initialization");

        testHandShake = handshake;
    }

    public OFChannelHandler getHandler() {
        if (this.handler != null)
            return this.handler;
        else
            return null;
    }

    @Override
    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        OFChannelHandler newhandler = new OFChannelHandler(pipeline, timer, ofBitmaps, defaultFactory,
                testHandShake);

        if (this.handler == null)
            this.handler = newhandler;

        // for Multiple Switches
        // handlerlist.add(handler);

        if (keyStore != null && keyStorePassword != null) {
            try {
                /* Set up factories and stores. */
                TrustManagerFactory tmFactory = TrustManagerFactory
                        .getInstance(TrustManagerFactory.getDefaultAlgorithm());
                KeyStore tmpKS = null;
                tmFactory.init(tmpKS);

                /* Use keystore/pass defined in properties file. */
                KeyStore ks = KeyStore.getInstance("JKS");
                ks.load(new FileInputStream(keyStore), keyStorePassword.toCharArray());

                KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
                kmf.init(ks, keyStorePassword.toCharArray());

                KeyManager[] km = kmf.getKeyManagers();
                TrustManager[] tm = tmFactory.getTrustManagers();

                /* Set up SSL prereqs for Netty. */
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(km, tm, null);
                SSLEngine sslEngine = sslContext.createSSLEngine();

                /* We are the server and we will create secure sessions. */
                sslEngine.setUseClientMode(false);
                sslEngine.setEnableSessionCreation(true);

                /* These are redundant (default), but for clarity... */
                sslEngine.setEnabledProtocols(sslEngine.getSupportedProtocols());
                sslEngine.setEnabledCipherSuites(sslEngine.getSupportedCipherSuites());

                /*
                 * First, decrypt w/handler+engine; then, proceed with rest of
                 * handlers.
                 */
                pipeline.addLast(PipelineHandler.SSL_TLS_ENCODER_DECODER, new SslHandler(sslEngine));
                log.info("SSL OpenFlow socket initialized and handler ready for switch.");
            } catch (Exception e) { /*
                                    * There are lots of possible exceptions to
                                    * catch, so this should get them all.
                                    */
                log.error("Exception initializing SSL OpenFlow socket: {}", e.getMessage());
                throw e; /*
                          * If we wanted secure but didn't get it, we should
                          * bail.
                          */
            }
        }

        pipeline.addLast(PipelineHandler.OF_MESSAGE_DECODER, new OFMessageDecoder());
        pipeline.addLast(PipelineHandler.OF_MESSAGE_ENCODER, new OFMessageEncoder());
        pipeline.addLast(PipelineHandler.MAIN_IDLE,
                new IdleStateHandler(PipelineIdleReadTimeout.MAIN, PipelineIdleWriteTimeout.MAIN, 0));
        pipeline.addLast(PipelineHandler.READ_TIMEOUT, new ReadTimeoutHandler(30));
        pipeline.addLast(PipelineHandler.CHANNEL_HANDSHAKE_TIMEOUT,
                new HandshakeTimeoutHandler(newhandler, timer, PipelineHandshakeTimeout.CHANNEL));

        pipeline.addLast(PipelineHandler.CHANNEL_HANDLER, newhandler);
    }

    public static class PipelineHandler {
        public final static String CHANNEL_HANDSHAKE_TIMEOUT = "channelhandshaketimeout";
        public final static String SWITCH_HANDSHAKE_TIMEOUT = "switchhandshaketimeout";
        public final static String CHANNEL_HANDLER = "channelhandler";
        public final static String MAIN_IDLE = "mainidle";
        public final static String AUX_IDLE = "auxidle";
        public final static String OF_MESSAGE_DECODER = "ofmessagedecoder";
        public final static String OF_MESSAGE_ENCODER = "ofmessageencoder";
        public final static String READ_TIMEOUT = "readtimeout";
        public final static String SSL_TLS_ENCODER_DECODER = "ofsecurechannelencoderdecoder";
    }

    /**
     * Timeouts for parts of the handshake, in seconds
     */
    public static class PipelineHandshakeTimeout {
        final static int CHANNEL = 10;
        public final static int SWITCH = 30;
    }

    /**
     * Timeouts for writes on connections, in seconds
     */
    public static class PipelineIdleWriteTimeout {
        final static int MAIN = 2;
        public final static int AUX = 15;
    }

    /**
     * Timeouts for reads on connections, in seconds
     */
    public static class PipelineIdleReadTimeout {
        final static int MAIN = 3 * PipelineIdleWriteTimeout.MAIN;
        public final static int AUX = 3 * PipelineIdleWriteTimeout.AUX;
    }
}