Copyright update
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / serialization / factories / HelloInputMessageFactory.java
1 /*
2  * Copyright (c) 2013 Pantheon Technologies s.r.o. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.openflowjava.protocol.impl.serialization.factories;
10
11 import io.netty.buffer.ByteBuf;
12
13 import java.util.List;
14
15 import org.opendaylight.openflowjava.protocol.impl.serialization.OFSerializer;
16 import org.opendaylight.openflowjava.protocol.impl.util.ByteBufUtils;
17 import org.opendaylight.openflowjava.protocol.impl.util.EncodeConstants;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.HelloElementType;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloInput;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.Elements;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 /**
25  * Translates Hello messages
26  * @author michal.polkorab
27  * @author timotej.kubas
28  */
29 public class HelloInputMessageFactory implements OFSerializer<HelloInput>{
30
31     /** Code type of Hello message */
32     private static final byte MESSAGE_TYPE = 0;
33     private static int MESSAGE_LENGTH = 8;
34     /** Size of hello element header (in bytes) */
35     public static final byte HELLO_ELEMENT_HEADER_SIZE = 4;
36     private static HelloInputMessageFactory instance;
37     
38     private static final Logger LOGGER = LoggerFactory
39             .getLogger(HelloInputMessageFactory.class);
40     
41     
42     private HelloInputMessageFactory() {
43         // do nothing, just singleton
44     }
45     
46     /**
47      * @return singleton factory
48      */
49     public static synchronized HelloInputMessageFactory getInstance() {
50         if (instance == null) {
51             instance = new HelloInputMessageFactory();
52         }
53         return instance;
54     }
55
56     @Override
57     public void messageToBuffer(short version, ByteBuf out, HelloInput message) {
58         int startWriterIndex = out.writerIndex();
59         ByteBufUtils.writeOFHeader(instance, message, out);
60         encodeElementsList(message, out);
61         int endWriterIndex = out.writerIndex();
62         int writtenBytesDiff = computeLength(message) - (endWriterIndex - startWriterIndex);
63         LOGGER.debug("writtenbytes: " + writtenBytesDiff);
64         ByteBufUtils.padBuffer(writtenBytesDiff, out);
65     }
66
67     @Override
68     public int computeLength(HelloInput message) {
69         int length = MESSAGE_LENGTH;
70         List<Elements> elements = message.getElements();
71         if (elements != null) {
72             for (Elements element : elements) {
73                 if (HelloElementType.VERSIONBITMAP.equals(element.getType())) {
74                     int bitmapLength = computeVersionBitmapLength(element);
75                     int paddingRemainder = bitmapLength % EncodeConstants.PADDING;
76                     if (paddingRemainder != 0) {
77                         bitmapLength += EncodeConstants.PADDING - paddingRemainder;
78                     }
79                     length += bitmapLength;
80                 }
81             }
82         }
83         return length;
84     }
85
86     @Override
87     public byte getMessageType() {
88         return MESSAGE_TYPE;
89     }
90     
91     private static void encodeElementsList(HelloInput message, ByteBuf output) {
92         int[] versionBitmap;
93         if (message.getElements() != null) {
94             for (Elements currElement : message.getElements()) {
95                 output.writeShort(currElement.getType().getIntValue());
96                 if (currElement.getType().equals(HelloElementType.VERSIONBITMAP)) {
97                     short bitmapLength = computeVersionBitmapLength(currElement);
98                     output.writeShort(bitmapLength);
99                     versionBitmap = ByteBufUtils.fillBitMaskFromList(currElement.getVersionBitmap());
100                     LOGGER.debug("vbs: " + versionBitmap.length);
101                     LOGGER.debug("Version bitmap (below):");
102                     for (int i = 0; i < versionBitmap.length; i++) {
103                         LOGGER.debug(Integer.toBinaryString(versionBitmap[i]));
104                         output.writeInt(versionBitmap[i]);
105                     }
106                     int padding = bitmapLength - versionBitmap.length * 4 - HELLO_ELEMENT_HEADER_SIZE;
107                     ByteBufUtils.padBuffer(padding , output);
108                 }
109             } 
110         }
111     }
112     
113     private static short computeVersionBitmapLength(Elements element) {
114         short elementlength = HELLO_ELEMENT_HEADER_SIZE;
115         if (!element.getVersionBitmap().isEmpty()) {
116             elementlength += ((element.getVersionBitmap().size() - 1) / Integer.SIZE + 1) * (EncodeConstants.SIZE_OF_INT_IN_BYTES);
117         }
118         return elementlength;
119     }
120 }