Bump upstreams
[openflowplugin.git] / openflowjava / openflowjava-util / src / main / java / org / opendaylight / openflowjava / util / ByteBufUtils.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 package org.opendaylight.openflowjava.util;
9
10 import com.google.common.base.Splitter;
11 import com.google.common.collect.Lists;
12 import io.netty.buffer.ByteBuf;
13 import io.netty.buffer.UnpooledByteBufAllocator;
14 import java.nio.ByteBuffer;
15 import java.nio.charset.StandardCharsets;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Map.Entry;
19 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.IetfYangUtil;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
26
27 /**
28  *  Class for common operations on ByteBuf.
29  *
30  * @author michal.polkorab
31  * @author timotej.kubas
32  */
33 public abstract class ByteBufUtils {
34     public static final Splitter DOT_SPLITTER = Splitter.on('.');
35     public static final Splitter COLON_SPLITTER = Splitter.on(':');
36     private static final Splitter HEXSTRING_SPLITTER =  Splitter.onPattern("\\s+").omitEmptyStrings();
37     private static final Splitter HEXSTRING_NOSPACE_SPLITTER = Splitter.onPattern("(?<=\\G.{2})").omitEmptyStrings();
38
39     private ByteBufUtils() {
40         //not called
41     }
42
43     /**
44      * Converts ByteBuf into String.
45      *
46      * @param bb input ByteBuf
47      * @return String
48      */
49     public static String byteBufToHexString(final ByteBuf bb) {
50         StringBuilder sb = new StringBuilder();
51         for (int i = bb.readerIndex(); i < bb.readerIndex() + bb.readableBytes(); i++) {
52             sb.append(String.format(" %02x", bb.getUnsignedByte(i)));
53         }
54         return sb.toString().trim();
55     }
56
57     /**
58      * Converts String into byte[].
59      *
60      * @param hexSrc input String
61      * @return byte[] filled with input data
62      */
63     public static byte[] hexStringToBytes(final String hexSrc) {
64         return hexStringToBytes(hexSrc, true);
65     }
66
67     /**
68      * Converts String into byte[].
69      *
70      * @param hexSrc input String
71      * @param withSpaces if there are spaces in string
72      * @return byte[] filled with input data
73      */
74     public static byte[] hexStringToBytes(final String hexSrc, final boolean withSpaces) {
75         final Splitter splitter = withSpaces ? HEXSTRING_SPLITTER : HEXSTRING_NOSPACE_SPLITTER;
76         List<String> byteChips = Lists.newArrayList(splitter.split(hexSrc));
77         byte[] result = new byte[byteChips.size()];
78         int index = 0;
79         for (String chip : byteChips) {
80             result[index] = (byte) Short.parseShort(chip, 16);
81             index++;
82         }
83         return result;
84     }
85
86     /**
87      * Creates ByteBuf filled with specified data.
88      *
89      * @param hexSrc input String of bytes in hex format
90      * @return ByteBuf with specified hexString converted
91      */
92     public static ByteBuf hexStringToByteBuf(final String hexSrc) {
93         ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer();
94         hexStringToByteBuf(hexSrc, out);
95         return out;
96     }
97
98     /**
99      * Creates ByteBuf filled with specified data.
100      *
101      * @param hexSrc input String of bytes in hex format
102      * @param out ByteBuf with specified hexString converted
103      */
104     public static void hexStringToByteBuf(final String hexSrc, final ByteBuf out) {
105         out.writeBytes(hexStringToBytes(hexSrc));
106     }
107
108     /**
109      * Create standard OF header.
110      *
111      * @param msgType message code
112      * @param message POJO
113      * @param out writing buffer
114      * @param length ofheader length
115      */
116     public static <E extends OfHeader> void writeOFHeader(final byte msgType, final E message, final ByteBuf out,
117             final int length) {
118         out.writeByte(message.getVersion().toJava());
119         out.writeByte(msgType);
120         out.writeShort(length);
121         out.writeInt(message.getXid().intValue());
122     }
123
124     /**
125      * Write length standard OF header.
126      *
127      * @param out writing buffer
128      */
129     public static void updateOFHeaderLength(final ByteBuf out) {
130         out.setShort(EncodeConstants.OFHEADER_LENGTH_INDEX, out.readableBytes());
131     }
132
133     /**
134      * Write length OF header.
135      *
136      * @param out writing buffer
137      * @param index writing index
138      */
139     public static void updateOFHeaderLength(final ByteBuf out, final int index) {
140         out.setShort(index + EncodeConstants.OFHEADER_LENGTH_INDEX, out.writerIndex() - index);
141     }
142
143     /**
144      * Fills the bitmask from boolean map where key is bit position.
145      *
146      * @param booleanMap bit to boolean mapping
147      * @return bit mask
148      */
149     public static int fillBitMaskFromMap(final Map<Integer, Boolean> booleanMap) {
150         int bitmask = 0;
151
152         for (Entry<Integer, Boolean> iterator : booleanMap.entrySet()) {
153             if (iterator.getValue() != null && iterator.getValue().booleanValue()) {
154                 bitmask |= 1 << iterator.getKey();
155             }
156         }
157         return bitmask;
158     }
159
160     /**
161      * Fills the bitmask from a set of bit values, starting at specified offset.
162      *
163      * @param offset Bit offset to start at
164      * @param values boolean bit values to fill
165      * @return Filled-in bitmask
166      */
167     public static int fillBitMask(final int offset, final boolean... values) {
168         int bitmask = 0;
169
170         int index = offset;
171         for (boolean v : values) {
172             if (v) {
173                 bitmask |= 1 << index;
174             }
175             ++index;
176         }
177
178         return bitmask;
179     }
180
181     /**
182      * Fills the bitmask from boolean list where key is bit position.
183      *
184      * @param booleanList bit to boolean mapping
185      * @return bit mask
186      */
187     public static int[] fillBitMaskFromList(final List<Boolean> booleanList) {
188         int[] bitmask;
189         int index = 0;
190         int arrayIndex = 0;
191         if (booleanList.size() % Integer.SIZE != 0) {
192             bitmask = new int[booleanList.size() / Integer.SIZE + 1];
193         } else {
194             bitmask = new int[booleanList.size() / Integer.SIZE];
195         }
196         for (Boolean currElement : booleanList) {
197             if (currElement != null && currElement.booleanValue()) {
198                 bitmask[arrayIndex] |= 1 << index;
199             }
200             index++;
201             arrayIndex = index / Integer.SIZE;
202         }
203         return bitmask;
204     }
205
206     /**
207      * Converts byte array into String.
208      *
209      * @param array input byte array
210      * @return String
211      */
212     public static String bytesToHexString(final byte[] array) {
213         StringBuilder sb = new StringBuilder();
214         for (byte element : array) {
215             sb.append(String.format(" %02x", element));
216         }
217         return sb.toString().trim();
218     }
219
220     /**
221      * Reads and parses null-terminated string from ByteBuf.
222      *
223      * @param rawMessage the message to parse
224      * @param length maximal length of String
225      * @return String with name of port
226      */
227     public static String decodeNullTerminatedString(final ByteBuf rawMessage, final int length) {
228         byte[] name = new byte[length];
229         rawMessage.readBytes(name);
230         return new String(name, StandardCharsets.UTF_8).trim();
231     }
232
233     public static Ipv4Address readIetfIpv4Address(final ByteBuf buf) {
234         return IetfInetUtil.ipv4AddressFor(buf.readInt());
235     }
236
237     public static Ipv6Address readIetfIpv6Address(final ByteBuf buf) {
238         final byte[] tmp = new byte[16];
239         buf.readBytes(tmp);
240         return IetfInetUtil.ipv6AddressFor(tmp);
241     }
242
243     public static MacAddress readIetfMacAddress(final ByteBuf buf) {
244         final byte[] tmp = new byte[EncodeConstants.MAC_ADDRESS_LENGTH];
245         buf.readBytes(tmp);
246         return IetfYangUtil.macAddressFor(tmp);
247     }
248
249     public static byte[] serializeList(final List<Short> list) {
250         ByteBuffer byteBuffer = ByteBuffer.allocate(list.size() * 2);
251         for (Short shortValue : list) {
252             byteBuffer.putShort(shortValue);
253         }
254         return byteBuffer.array();
255     }
256 }