Error code support for ErrorMessage
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / serialization / factories / HelloInputMessageFactory.java
index f75c68c356b246755f11eb4598184b7f8e485f17..0ce34624d380f1d556262c7add6aaa874cd4ebf9 100644 (file)
@@ -1,27 +1,37 @@
 /* Copyright (C)2013 Pantheon Technologies, s.r.o. All rights reserved. */\r
 package org.opendaylight.openflowjava.protocol.impl.serialization.factories;\r
 \r
-import java.util.Iterator;\r
-import java.util.List;\r
-\r
 import io.netty.buffer.ByteBuf;\r
 \r
+import java.util.List;\r
+\r
 import org.opendaylight.openflowjava.protocol.impl.serialization.OFSerializer;\r
 import org.opendaylight.openflowjava.protocol.impl.util.ByteBufUtils;\r
+import org.opendaylight.openflowjava.protocol.impl.util.EncodeConstants;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.HelloElementType;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloInput;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.Elements;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
 \r
 /**\r
+ * Translates Hello messages\r
  * @author michal.polkorab\r
- *\r
+ * @author timotej.kubas\r
  */\r
 public class HelloInputMessageFactory implements OFSerializer<HelloInput>{\r
 \r
     /** Code type of Hello message */\r
-    public static final byte MESSAGE_TYPE = 0;\r
-    private static final int MESSAGE_LENGTH = 8;\r
+    private static final byte MESSAGE_TYPE = 0;\r
+    private static int MESSAGE_LENGTH = 8;\r
+    /** Size of hello element header (in bytes) */\r
+    public static final byte HELLO_ELEMENT_HEADER_SIZE = 4;\r
     private static HelloInputMessageFactory instance;\r
     \r
+    private static final Logger LOGGER = LoggerFactory\r
+            .getLogger(HelloInputMessageFactory.class);\r
+    \r
+    \r
     private HelloInputMessageFactory() {\r
         // do nothing, just singleton\r
     }\r
@@ -29,7 +39,7 @@ public class HelloInputMessageFactory implements OFSerializer<HelloInput>{
     /**\r
      * @return singleton factory\r
      */\r
-    public static HelloInputMessageFactory getInstance() {\r
+    public static synchronized HelloInputMessageFactory getInstance() {\r
         if (instance == null) {\r
             instance = new HelloInputMessageFactory();\r
         }\r
@@ -38,18 +48,66 @@ public class HelloInputMessageFactory implements OFSerializer<HelloInput>{
 \r
     @Override\r
     public void messageToBuffer(short version, ByteBuf out, HelloInput message) {\r
+        int startWriterIndex = out.writerIndex();\r
         ByteBufUtils.writeOFHeader(instance, message, out);\r
-        // TODO - fill list of elements into ByteBuf, check length too\r
+        encodeElementsList(message, out);\r
+        int endWriterIndex = out.writerIndex();\r
+        int writtenBytesDiff = computeLength(message) - (endWriterIndex - startWriterIndex);\r
+        LOGGER.debug("writtenbytes: " + writtenBytesDiff);\r
+        ByteBufUtils.padBuffer(writtenBytesDiff, out);\r
     }\r
 \r
     @Override\r
-    public int computeLength() {\r
-        return MESSAGE_LENGTH;\r
+    public int computeLength(HelloInput message) {\r
+        int length = MESSAGE_LENGTH;\r
+        List<Elements> elements = message.getElements();\r
+        if (elements != null) {\r
+            for (Elements element : elements) {\r
+                if (HelloElementType.VERSIONBITMAP.equals(element.getType())) {\r
+                    int bitmapLength = computeVersionBitmapLength(element);\r
+                    int paddingRemainder = bitmapLength % EncodeConstants.PADDING;\r
+                    if (paddingRemainder != 0) {\r
+                        bitmapLength += EncodeConstants.PADDING - paddingRemainder;\r
+                    }\r
+                    length += bitmapLength;\r
+                }\r
+            }\r
+        }\r
+        return length;\r
     }\r
 \r
     @Override\r
     public byte getMessageType() {\r
         return MESSAGE_TYPE;\r
     }\r
\r
+    \r
+    private static void encodeElementsList(HelloInput message, ByteBuf output) {\r
+        int[] versionBitmap;\r
+        if (message.getElements() != null) {\r
+            for (Elements currElement : message.getElements()) {\r
+                output.writeShort(currElement.getType().getIntValue());\r
+                if (currElement.getType().equals(HelloElementType.VERSIONBITMAP)) {\r
+                    short bitmapLength = computeVersionBitmapLength(currElement);\r
+                    output.writeShort(bitmapLength);\r
+                    versionBitmap = ByteBufUtils.fillBitMaskFromList(currElement.getVersionBitmap());\r
+                    LOGGER.debug("vbs: " + versionBitmap.length);\r
+                    LOGGER.debug("Version bitmap (below):");\r
+                    for (int i = 0; i < versionBitmap.length; i++) {\r
+                        LOGGER.debug(Integer.toBinaryString(versionBitmap[i]));\r
+                        output.writeInt(versionBitmap[i]);\r
+                    }\r
+                    int padding = bitmapLength - versionBitmap.length * 4 - HELLO_ELEMENT_HEADER_SIZE;\r
+                    ByteBufUtils.padBuffer(padding , output);\r
+                }\r
+            } \r
+        }\r
+    }\r
+    \r
+    private static short computeVersionBitmapLength(Elements element) {\r
+        short elementlength = HELLO_ELEMENT_HEADER_SIZE;\r
+        if (!element.getVersionBitmap().isEmpty()) {\r
+            elementlength += ((element.getVersionBitmap().size() - 1) / Integer.SIZE + 1) * (Integer.SIZE / Byte.SIZE);\r
+        }\r
+        return elementlength;\r
+    }\r
 }\r