/* * Copyright (c) 2013 Pantheon Technologies s.r.o. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.openflowjava.protocol.impl.util; import io.netty.buffer.ByteBuf; import io.netty.buffer.UnpooledByteBufAllocator; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.collect.Lists; /** Class for common operations on ByteBuf * @author michal.polkorab * @author timotej.kubas */ public abstract class ByteBufUtils { /** * Converts ByteBuf into String * @param bb input ByteBuf * @return String */ public static String byteBufToHexString(ByteBuf bb) { StringBuffer sb = new StringBuffer(); for (int i = bb.readerIndex(); i < (bb.readerIndex() + bb.readableBytes()); i++) { sb.append(String.format(" %02x", bb.getUnsignedByte(i))); } return sb.toString().trim(); } /** * Converts String into byte[] * @param hexSrc input String * @return byte[] filled with input data */ public static byte[] hexStringToBytes(String hexSrc) { return hexStringToBytes(hexSrc, true); } /** * Converts String into byte[] * @param hexSrc input String * @param withSpaces if there are spaces in string * @return byte[] filled with input data */ public static byte[] hexStringToBytes(String hexSrc, boolean withSpaces ) { String splitPattern = "\\s+"; if (!withSpaces) { splitPattern = "(?<=\\G.{2})"; } Iterable tmp = Splitter.onPattern(splitPattern) .omitEmptyStrings().split(hexSrc); ArrayList byteChips = Lists.newArrayList(tmp); byte[] result = new byte[byteChips.size()]; int i = 0; for (String chip : byteChips) { result[i] = (byte) Short.parseShort(chip, 16); i++; } return result; } /** * Creates ByteBuf filled with specified data * @param hexSrc input String of bytes in hex format * @return ByteBuf with specified hexString converted */ public static ByteBuf hexStringToByteBuf(String hexSrc) { ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer(); hexStringToByteBuf(hexSrc, out); return out; } /** * Creates ByteBuf filled with specified data * @param hexSrc input String of bytes in hex format * @param out ByteBuf with specified hexString converted */ public static void hexStringToByteBuf(String hexSrc, ByteBuf out) { out.writeBytes(hexStringToBytes(hexSrc)); } /** * Fills specified ByteBuf with 0 (zeros) of desired length, used for padding * @param length * @param out ByteBuf to be padded */ public static void padBuffer(int length, ByteBuf out) { for (int i = 0; i < length; i++) { out.writeByte(0); } } /** * Create standard OF header * @param msgType message code * @param message POJO * @param out writing buffer * @param length ofheader length */ public static void writeOFHeader(byte msgType, E message, ByteBuf out, int length) { out.writeByte(message.getVersion()); out.writeByte(msgType); out.writeShort(length); out.writeInt(message.getXid().intValue()); } /** * Write length standard OF header * @param out writing buffer */ public static void updateOFHeaderLength(ByteBuf out) { out.setShort(EncodeConstants.OFHEADER_LENGTH_INDEX, out.readableBytes()); } /** * Fills the bitmask from boolean map where key is bit position * @param booleanMap bit to boolean mapping * @return bit mask */ public static int fillBitMaskFromMap(Map booleanMap) { int bitmask = 0; for (Entry iterator : booleanMap.entrySet()) { if (iterator.getValue() != null && iterator.getValue().booleanValue()) { bitmask |= 1 << iterator.getKey(); } } return bitmask; } /** * Fills the bitmask from boolean list where key is bit position * @param booleanList bit to boolean mapping * @return bit mask */ public static int[] fillBitMaskFromList(List booleanList) { int[] bitmask; int index = 0; int arrayIndex = 0; if ((booleanList.size() % Integer.SIZE) != 0) { bitmask = new int[booleanList.size() / Integer.SIZE + 1]; } else { bitmask = new int[booleanList.size() / Integer.SIZE]; } for (Boolean currElement : booleanList) { if (currElement != null && currElement.booleanValue()) { bitmask[arrayIndex] |= 1 << index; } index++; arrayIndex = index / Integer.SIZE; } return bitmask; } /** * Converts byte array into String * @param array input byte array * @return String */ public static String bytesToHexString(byte[] array) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < array.length; i++) { sb.append(String.format(" %02x", array[i])); } return sb.toString().trim(); } /** * Converts macAddress to byte array * @param macAddress * @return byte representation of mac address * @see {@link MacAddress} */ public static byte[] macAddressToBytes(String macAddress) { Iterable addressGroups = Splitter.on(":").split(macAddress); byte[] result = new byte[EncodeConstants.MAC_ADDRESS_LENGTH]; int i = 0; for (String group : addressGroups) { result[i] = (byte) Short.parseShort(group, 16); i++; } return result; } /** * Converts mac address represented in bytes to String * @param address * @return String representation of mac address * @see {@link MacAddress} */ public static String macAddressToString(byte[] address) { List groups = new ArrayList<>(); for(int i=0; i < EncodeConstants.MAC_ADDRESS_LENGTH; i++){ groups.add(String.format("%02X", address[i])); } Joiner joiner = Joiner.on(":"); return joiner.join(groups); } /** * Reads and parses null-terminated string from ByteBuf * @param rawMessage * @param length maximal length of String * @return String with name of port */ public static String decodeNullTerminatedString(ByteBuf rawMessage, int length) { byte[] name = new byte[length]; rawMessage.readBytes(name); return new String(name).trim(); } }