Renamed packages to org.opendaylight.openflowjava.protocol.impl.*
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / core / TlsDetector.java
1 /* Copyright (C)2013 Pantheon Technologies, s.r.o. All rights reserved. */
2 package org.opendaylight.openflowjava.protocol.impl.core;
3
4 import io.netty.buffer.ByteBuf;
5 import io.netty.channel.ChannelHandlerContext;
6 import io.netty.channel.ChannelPipeline;
7 import io.netty.handler.codec.ByteToMessageDecoder;
8 import io.netty.handler.ssl.SslHandler;
9
10 import java.util.List;
11
12 import javax.net.ssl.SSLEngine;
13
14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory;
16 import org.opendaylight.openflowjava.protocol.impl.core.TcpHandler.COMPONENT_NAMES;
17 import org.opendaylight.openflowjava.protocol.impl.util.ByteBufUtils;
18
19 /**
20  * Class for detecting TLS encrypted connection. If TLS encrypted connection is detected,
21  * TLSDetector engages SSLHandler and OFFrameDecoder into pipeline else it engages only
22  * OFFrameDecoder.
23  *
24  * @author michal.polkorab
25  */
26 public class TlsDetector extends ByteToMessageDecoder {
27
28     private boolean detectSsl;
29     private static final Logger LOGGER = LoggerFactory
30             .getLogger(TlsDetector.class);
31
32     /**
33      * Constructor of class
34      */
35     public TlsDetector() {
36         LOGGER.info("Creating TLS Detector");
37         detectSsl = true;
38     }
39
40     @Override
41     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
42         LOGGER.warn("Unexpected exception from downstream.",
43                 cause);
44         ctx.close();
45     }
46
47     private boolean isSsl(ByteBuf bb) {
48         if (detectSsl) {
49             LOGGER.info("Testing connection for TLS");
50             return SslHandler.isEncrypted(bb);
51         }
52         return false;
53     }
54
55     private static void enableSsl(ChannelHandlerContext ctx) {
56         if (ctx.pipeline().get(COMPONENT_NAMES.SSL_HANDLER.name()) == null) {
57             LOGGER.info("Engaging TLS handler");
58             ChannelPipeline p = ctx.channel().pipeline();
59             SSLEngine engine = SslContextFactory.getServerContext()
60                     .createSSLEngine();
61             engine.setUseClientMode(false);
62             p.addLast(COMPONENT_NAMES.SSL_HANDLER.name(),
63                     new SslHandler(engine));
64         }
65     }
66
67     private static void enableOFFrameDecoder(ChannelHandlerContext ctx) {
68         ChannelPipeline p = ctx.channel().pipeline();
69         if (p.get(COMPONENT_NAMES.OF_FRAME_DECODER.name()) == null) {
70             LOGGER.debug("Engaging OFFrameDecoder");
71             p.addLast(COMPONENT_NAMES.OF_FRAME_DECODER.name(), new OFFrameDecoder());
72         } else {
73             LOGGER.debug("OFFD already in pipeline");
74         }
75     }
76
77     @Override
78     protected void decode(ChannelHandlerContext ctx, ByteBuf bb,
79             List<Object> list) throws Exception {
80         if (bb.readableBytes() < 5) {
81             return;
82         }
83         if (LOGGER.isDebugEnabled()) {
84             LOGGER.debug(ByteBufUtils.byteBufToHexString(bb));
85         }
86         if (isSsl(bb)) {
87             LOGGER.info("Connection is encrypted");
88             enableSsl(ctx);
89         } else {
90             LOGGER.info("Connection is not encrypted");
91         }
92         enableOFFrameDecoder(ctx);
93         ctx.pipeline().remove(COMPONENT_NAMES.TLS_DETECTOR.name());
94     }
95 }