Remove ByteBufUtils.macAddressToBytes()
[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
9 package org.opendaylight.openflowjava.util;
10
11 import com.google.common.base.Preconditions;
12 import com.google.common.base.Splitter;
13 import com.google.common.collect.Lists;
14 import com.google.common.primitives.UnsignedBytes;
15 import io.netty.buffer.ByteBuf;
16 import io.netty.buffer.UnpooledByteBufAllocator;
17 import java.nio.ByteBuffer;
18 import java.nio.charset.StandardCharsets;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Map.Entry;
22 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.IetfYangUtil;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
29
30 /**
31  *  Class for common operations on ByteBuf.
32  *
33  * @author michal.polkorab
34  * @author timotej.kubas
35  */
36 public abstract class ByteBufUtils {
37     public static final Splitter DOT_SPLITTER = Splitter.on('.');
38     public static final Splitter COLON_SPLITTER = Splitter.on(':');
39     private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
40     private static final Splitter HEXSTRING_SPLITTER =  Splitter.onPattern("\\s+").omitEmptyStrings();
41     private static final Splitter HEXSTRING_NOSPACE_SPLITTER = Splitter.onPattern("(?<=\\G.{2})").omitEmptyStrings();
42
43     private ByteBufUtils() {
44         //not called
45     }
46
47     /**
48      * Converts ByteBuf into String.
49      *
50      * @param bb input ByteBuf
51      * @return String
52      */
53     public static String byteBufToHexString(final ByteBuf bb) {
54         StringBuilder sb = new StringBuilder();
55         for (int i = bb.readerIndex(); i < bb.readerIndex() + bb.readableBytes(); i++) {
56             sb.append(String.format(" %02x", bb.getUnsignedByte(i)));
57         }
58         return sb.toString().trim();
59     }
60
61     /**
62      * Converts String into byte[].
63      *
64      * @param hexSrc input String
65      * @return byte[] filled with input data
66      */
67     public static byte[] hexStringToBytes(final String hexSrc) {
68         return hexStringToBytes(hexSrc, true);
69     }
70
71     /**
72      * Converts String into byte[].
73      *
74      * @param hexSrc input String
75      * @param withSpaces if there are spaces in string
76      * @return byte[] filled with input data
77      */
78     public static byte[] hexStringToBytes(final String hexSrc, final boolean withSpaces) {
79         final Splitter splitter = withSpaces ? HEXSTRING_SPLITTER : HEXSTRING_NOSPACE_SPLITTER;
80         List<String> byteChips = Lists.newArrayList(splitter.split(hexSrc));
81         byte[] result = new byte[byteChips.size()];
82         int index = 0;
83         for (String chip : byteChips) {
84             result[index] = (byte) Short.parseShort(chip, 16);
85             index++;
86         }
87         return result;
88     }
89
90     /**
91      * Creates ByteBuf filled with specified data.
92      *
93      * @param hexSrc input String of bytes in hex format
94      * @return ByteBuf with specified hexString converted
95      */
96     public static ByteBuf hexStringToByteBuf(final String hexSrc) {
97         ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer();
98         hexStringToByteBuf(hexSrc, out);
99         return out;
100     }
101
102     /**
103      * Creates ByteBuf filled with specified data.
104      *
105      * @param hexSrc input String of bytes in hex format
106      * @param out ByteBuf with specified hexString converted
107      */
108     public static void hexStringToByteBuf(final String hexSrc, final ByteBuf out) {
109         out.writeBytes(hexStringToBytes(hexSrc));
110     }
111
112     /**
113      * Create standard OF header.
114      *
115      * @param msgType message code
116      * @param message POJO
117      * @param out writing buffer
118      * @param length ofheader length
119      */
120     public static <E extends OfHeader> void writeOFHeader(final byte msgType, final E message, final ByteBuf out,
121             final int length) {
122         out.writeByte(message.getVersion().toJava());
123         out.writeByte(msgType);
124         out.writeShort(length);
125         out.writeInt(message.getXid().intValue());
126     }
127
128     /**
129      * Write length standard OF header.
130      *
131      * @param out writing buffer
132      */
133     public static void updateOFHeaderLength(final ByteBuf out) {
134         out.setShort(EncodeConstants.OFHEADER_LENGTH_INDEX, out.readableBytes());
135     }
136
137     /**
138      * Write length OF header.
139      *
140      * @param out writing buffer
141      * @param index writing index
142      */
143     public static void updateOFHeaderLength(final ByteBuf out, int index) {
144         out.setShort(index + EncodeConstants.OFHEADER_LENGTH_INDEX, out.writerIndex() - index);
145     }
146
147     /**
148      * Fills the bitmask from boolean map where key is bit position.
149      *
150      * @param booleanMap bit to boolean mapping
151      * @return bit mask
152      */
153     public static int fillBitMaskFromMap(final Map<Integer, Boolean> booleanMap) {
154         int bitmask = 0;
155
156         for (Entry<Integer, Boolean> iterator : booleanMap.entrySet()) {
157             if (iterator.getValue() != null && iterator.getValue().booleanValue()) {
158                 bitmask |= 1 << iterator.getKey();
159             }
160         }
161         return bitmask;
162     }
163
164     /**
165      * Fills the bitmask from a set of bit values, starting at specified offset.
166      *
167      * @param offset Bit offset to start at
168      * @param values boolean bit values to fill
169      * @return Filled-in bitmask
170      */
171     public static int fillBitMask(final int offset, final boolean... values) {
172         int bitmask = 0;
173
174         int index = offset;
175         for (boolean v : values) {
176             if (v) {
177                 bitmask |= 1 << index;
178             }
179             ++index;
180         }
181
182         return bitmask;
183     }
184
185     /**
186      * Fills the bitmask from boolean list where key is bit position.
187      *
188      * @param booleanList bit to boolean mapping
189      * @return bit mask
190      */
191     public static int[] fillBitMaskFromList(final List<Boolean> booleanList) {
192         int[] bitmask;
193         int index = 0;
194         int arrayIndex = 0;
195         if (booleanList.size() % Integer.SIZE != 0) {
196             bitmask = new int[booleanList.size() / Integer.SIZE + 1];
197         } else {
198             bitmask = new int[booleanList.size() / Integer.SIZE];
199         }
200         for (Boolean currElement : booleanList) {
201             if (currElement != null && currElement.booleanValue()) {
202                 bitmask[arrayIndex] |= 1 << index;
203             }
204             index++;
205             arrayIndex = index / Integer.SIZE;
206         }
207         return bitmask;
208     }
209
210     /**
211      * Converts byte array into String.
212      *
213      * @param array input byte array
214      * @return String
215      */
216     public static String bytesToHexString(final byte[] array) {
217         StringBuilder sb = new StringBuilder();
218         for (byte element : array) {
219             sb.append(String.format(" %02x", element));
220         }
221         return sb.toString().trim();
222     }
223
224     private static void appendHexByte(final StringBuilder sb, final byte value) {
225         final int v = UnsignedBytes.toInt(value);
226         sb.append(HEX_CHARS[v >>> 4]);
227         sb.append(HEX_CHARS[v &  15]);
228     }
229
230     private static void appendHexUnsignedShort(final StringBuilder sb, final int val) {
231         sb.append(ByteBufUtils.HEX_CHARS[val >>> 12 & 15]);
232         sb.append(ByteBufUtils.HEX_CHARS[val >>>  8 & 15]);
233         sb.append(ByteBufUtils.HEX_CHARS[val >>>  4 & 15]);
234         sb.append(ByteBufUtils.HEX_CHARS[ val         & 15]);
235     }
236
237     /**
238      * Converts a MAC address represented in bytes to String.
239      * See also {@link org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress}.
240      *
241      * @param address the MAC address to convert
242      * @return String representation of a MAC address
243      */
244     public static String macAddressToString(final byte[] address) {
245         Preconditions.checkArgument(address.length == EncodeConstants.MAC_ADDRESS_LENGTH);
246
247         final StringBuilder sb = new StringBuilder(17);
248
249         appendHexByte(sb, address[0]);
250         for (int i = 1; i < EncodeConstants.MAC_ADDRESS_LENGTH; i++) {
251             sb.append(':');
252             appendHexByte(sb, address[i]);
253         }
254
255         return sb.toString();
256     }
257
258     /**
259      * Reads and parses null-terminated string from ByteBuf.
260      *
261      * @param rawMessage the message to parse
262      * @param length maximal length of String
263      * @return String with name of port
264      */
265     public static String decodeNullTerminatedString(final ByteBuf rawMessage, final int length) {
266         byte[] name = new byte[length];
267         rawMessage.readBytes(name);
268         return new String(name, StandardCharsets.UTF_8).trim();
269     }
270
271     /**
272      * Read an IPv4 address from a buffer and format it into dotted-quad string.
273      *
274      * @param buf Input buffer
275      * @return Dotted-quad string
276      */
277     public static String readIpv4Address(final ByteBuf buf) {
278         final StringBuilder sb = new StringBuilder(EncodeConstants.GROUPS_IN_IPV4_ADDRESS * 4 - 1);
279
280         sb.append(buf.readUnsignedByte());
281         for (int i = 1; i < EncodeConstants.GROUPS_IN_IPV4_ADDRESS; i++) {
282             sb.append('.');
283             sb.append(buf.readUnsignedByte());
284         }
285
286         return sb.toString();
287     }
288
289
290     /**
291      * Read an IPv6 address from a buffer and format it into a string of eight groups of four
292      * hexadecimal digits separated by colons.
293      *
294      * @param buf Input buffer
295      * @return IPv6 address in string format
296      */
297     public static String readIpv6Address(final ByteBuf buf) {
298         final StringBuilder sb = new StringBuilder(EncodeConstants.GROUPS_IN_IPV6_ADDRESS * 5 - 1);
299
300         appendHexUnsignedShort(sb, buf.readUnsignedShort());
301         for (int i = 1; i < EncodeConstants.GROUPS_IN_IPV6_ADDRESS; i++) {
302             sb.append(':');
303             appendHexUnsignedShort(sb, buf.readUnsignedShort());
304         }
305
306         return sb.toString();
307     }
308
309     public static Ipv4Address readIetfIpv4Address(final ByteBuf buf) {
310         final byte[] tmp = new byte[4];
311         buf.readBytes(tmp);
312         return IetfInetUtil.INSTANCE.ipv4AddressFor(tmp);
313     }
314
315     public static Ipv6Address readIetfIpv6Address(final ByteBuf buf) {
316         final byte[] tmp = new byte[16];
317         buf.readBytes(tmp);
318         return IetfInetUtil.INSTANCE.ipv6AddressFor(tmp);
319     }
320
321     public static MacAddress readIetfMacAddress(final ByteBuf buf) {
322         final byte[] tmp = new byte[EncodeConstants.MAC_ADDRESS_LENGTH];
323         buf.readBytes(tmp);
324         return IetfYangUtil.INSTANCE.macAddressFor(tmp);
325     }
326
327     public static byte[] serializeList(final List<Short> list) {
328         ByteBuffer byteBuffer = ByteBuffer.allocate(list.size() * 2);
329         for (Short shortValue : list) {
330             byteBuffer.putShort(shortValue);
331         }
332         return byteBuffer.array();
333     }
334 }