3bda7b211725e0d09650355232f3d27c27c94559
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / core / OFDatagramPacketHandler.java
1 /*\r
2  * Copyright (c) 2014 Pantheon Technologies s.r.o. and others. All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.openflowjava.protocol.impl.core;\r
10 \r
11 import io.netty.buffer.ByteBuf;\r
12 import io.netty.channel.ChannelHandlerContext;\r
13 import io.netty.channel.socket.DatagramPacket;\r
14 import io.netty.handler.codec.MessageToMessageDecoder;\r
15 \r
16 import java.util.List;\r
17 \r
18 import org.opendaylight.openflowjava.protocol.api.connection.SwitchConnectionHandler;\r
19 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;\r
20 import org.opendaylight.openflowjava.protocol.impl.core.connection.ConnectionAdapterFactory;\r
21 import org.opendaylight.openflowjava.protocol.impl.core.connection.ConnectionAdapterFactoryImpl;\r
22 import org.opendaylight.openflowjava.protocol.impl.core.connection.ConnectionFacade;\r
23 import org.opendaylight.openflowjava.protocol.impl.core.connection.MessageConsumer;\r
24 import org.opendaylight.openflowjava.util.ByteBufUtils;\r
25 import org.slf4j.Logger;\r
26 import org.slf4j.LoggerFactory;\r
27 \r
28 /**\r
29  * @author michal.polkorab\r
30  *\r
31  */\r
32 public class OFDatagramPacketHandler extends MessageToMessageDecoder<DatagramPacket> {\r
33 \r
34     private static final Logger LOGGER = LoggerFactory.getLogger(OFDatagramPacketHandler.class);\r
35 \r
36     /** Length of OpenFlow 1.3 header */\r
37     public static final byte LENGTH_OF_HEADER = 8;\r
38     private static final byte LENGTH_INDEX_IN_HEADER = 2;\r
39     private ConnectionAdapterFactory adapterFactory = new ConnectionAdapterFactoryImpl();\r
40     private SwitchConnectionHandler connectionHandler;\r
41 \r
42     /**\r
43      * Default constructor\r
44      * @param sch the switchConnectionHandler that decides\r
45      * what to do with incomming message / channel\r
46      */\r
47     public OFDatagramPacketHandler(SwitchConnectionHandler sch) {\r
48         this.connectionHandler = sch;\r
49     }\r
50 \r
51     @Override\r
52     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {\r
53         LOGGER.warn("Unexpected exception from downstream.", cause);\r
54         LOGGER.warn("Closing connection.");\r
55         ctx.close();\r
56     }\r
57 \r
58     @Override\r
59     protected void decode(ChannelHandlerContext ctx, DatagramPacket msg,\r
60             List<Object> out) throws Exception {\r
61         LOGGER.debug("OFDatagramPacketFramer");\r
62         MessageConsumer consumer = UdpConnectionMap.getMessageConsumer(msg.sender());\r
63         if (consumer == null) {\r
64             ConnectionFacade connectionFacade =\r
65                     adapterFactory.createConnectionFacade(ctx.channel(), msg.sender());\r
66             connectionHandler.onSwitchConnected(connectionFacade);\r
67             connectionFacade.checkListeners();\r
68             UdpConnectionMap.addConnection(msg.sender(), connectionFacade);\r
69         }\r
70         ByteBuf bb = msg.content();\r
71         int readableBytes = bb.readableBytes();\r
72         if (readableBytes < LENGTH_OF_HEADER) {\r
73             if (LOGGER.isDebugEnabled()) {\r
74                 LOGGER.debug("skipping bytebuf - too few bytes for header: " + readableBytes + " < " + LENGTH_OF_HEADER );\r
75                 LOGGER.debug("bb: " + ByteBufUtils.byteBufToHexString(bb));\r
76             }\r
77             return;\r
78         }\r
79 \r
80         int length = bb.getUnsignedShort(bb.readerIndex() + LENGTH_INDEX_IN_HEADER);\r
81         LOGGER.debug("length of actual message: {}", length);\r
82         \r
83         if (readableBytes < length) {\r
84             if (LOGGER.isDebugEnabled()) {\r
85                 LOGGER.debug("skipping bytebuf - too few bytes for msg: " +\r
86                         readableBytes + " < " + length);\r
87                 LOGGER.debug("bytebuffer: " + ByteBufUtils.byteBufToHexString(bb));\r
88             }\r
89             return;\r
90         }\r
91         LOGGER.debug("OF Protocol message received, type:{}", bb.getByte(bb.readerIndex() + 1));\r
92 \r
93         \r
94         byte version = bb.readByte();\r
95         if ((version == EncodeConstants.OF13_VERSION_ID) || (version == EncodeConstants.OF10_VERSION_ID)) {\r
96             LOGGER.debug("detected version: " + version);\r
97             ByteBuf messageBuffer = bb.slice();\r
98             out.add(new VersionMessageUdpWrapper(version, messageBuffer, msg.sender()));\r
99             messageBuffer.retain();\r
100         } else {\r
101             LOGGER.warn("detected version: " + version + " - currently not supported");\r
102         }\r
103         bb.skipBytes(bb.readableBytes());\r
104     }\r
105 }