diff options
Diffstat (limited to 'wifi/java/android/net/wifi/aware/TlvBufferUtils.java')
-rw-r--r-- | wifi/java/android/net/wifi/aware/TlvBufferUtils.java | 714 |
1 files changed, 0 insertions, 714 deletions
diff --git a/wifi/java/android/net/wifi/aware/TlvBufferUtils.java b/wifi/java/android/net/wifi/aware/TlvBufferUtils.java deleted file mode 100644 index 2d3cc1eda643..000000000000 --- a/wifi/java/android/net/wifi/aware/TlvBufferUtils.java +++ /dev/null @@ -1,714 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.wifi.aware; - -import android.annotation.Nullable; - -import java.nio.BufferOverflowException; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -/** - * Utility class to construct and parse byte arrays using the TLV format - - * Type/Length/Value format. The utilities accept a configuration of the size of - * the Type field and the Length field. A Type field size of 0 is allowed - - * allowing usage for LV (no T) array formats. - * - * @hide - */ -public class TlvBufferUtils { - private TlvBufferUtils() { - // no reason to ever create this class - } - - /** - * Utility class to construct byte arrays using the TLV format - - * Type/Length/Value. - * <p> - * A constructor is created specifying the size of the Type (T) and Length - * (L) fields. A specification of zero size T field is allowed - resulting - * in LV type format. - * <p> - * The byte array is either provided (using - * {@link TlvConstructor#wrap(byte[])}) or allocated (using - * {@link TlvConstructor#allocate(int)}). - * <p> - * Values are added to the structure using the {@code TlvConstructor.put*()} - * methods. - * <p> - * The final byte array is obtained using {@link TlvConstructor#getArray()}. - */ - public static class TlvConstructor { - private int mTypeSize; - private int mLengthSize; - private ByteOrder mByteOrder = ByteOrder.BIG_ENDIAN; - - private byte[] mArray; - private int mArrayLength; - private int mPosition; - - /** - * Define a TLV constructor with the specified size of the Type (T) and - * Length (L) fields. - * - * @param typeSize Number of bytes used for the Type (T) field. Values - * of 0, 1, or 2 bytes are allowed. A specification of 0 - * bytes implies that the field being constructed has the LV - * format rather than the TLV format. - * @param lengthSize Number of bytes used for the Length (L) field. - * Values of 1 or 2 bytes are allowed. - */ - public TlvConstructor(int typeSize, int lengthSize) { - if (typeSize < 0 || typeSize > 2 || lengthSize <= 0 || lengthSize > 2) { - throw new IllegalArgumentException( - "Invalid sizes - typeSize=" + typeSize + ", lengthSize=" + lengthSize); - } - mTypeSize = typeSize; - mLengthSize = lengthSize; - mPosition = 0; - } - - /** - * Configure the TLV constructor to use a particular byte order. Should be - * {@link ByteOrder#BIG_ENDIAN} (the default at construction) or - * {@link ByteOrder#LITTLE_ENDIAN}. - * - * @return The constructor to facilitate chaining - * {@code ctr.putXXX(..).putXXX(..)}. - */ - public TlvConstructor setByteOrder(ByteOrder byteOrder) { - mByteOrder = byteOrder; - return this; - } - - /** - * Set the byte array to be used to construct the TLV. - * - * @param array Byte array to be formatted. - * @return The constructor to facilitate chaining - * {@code ctr.putXXX(..).putXXX(..)}. - */ - public TlvConstructor wrap(@Nullable byte[] array) { - mArray = array; - mArrayLength = (array == null) ? 0 : array.length; - mPosition = 0; - return this; - } - - /** - * Allocates a new byte array to be used ot construct a TLV. - * - * @param capacity The size of the byte array to be allocated. - * @return The constructor to facilitate chaining - * {@code ctr.putXXX(..).putXXX(..)}. - */ - public TlvConstructor allocate(int capacity) { - mArray = new byte[capacity]; - mArrayLength = capacity; - mPosition = 0; - return this; - } - - /** - * Creates a TLV array (of the previously specified Type and Length sizes) from the input - * list. Allocates an array matching the contents (and required Type and Length - * fields), copies the contents, and set the Length fields. The Type field is set to 0. - * - * @param list A list of fields to be added to the TLV buffer. - * @return The constructor of the TLV. - */ - public TlvConstructor allocateAndPut(@Nullable List<byte[]> list) { - if (list != null) { - int size = 0; - for (byte[] field : list) { - size += mTypeSize + mLengthSize; - if (field != null) { - size += field.length; - } - } - allocate(size); - for (byte[] field : list) { - putByteArray(0, field); - } - } - return this; - } - - /** - * Copies a byte into the TLV with the indicated type. For an LV - * formatted structure (i.e. typeLength=0 in {@link TlvConstructor - * TlvConstructor(int, int)} ) the type field is ignored. - * - * @param type The value to be placed into the Type field. - * @param b The byte to be inserted into the structure. - * @return The constructor to facilitate chaining - * {@code ctr.putXXX(..).putXXX(..)}. - */ - public TlvConstructor putByte(int type, byte b) { - checkLength(1); - addHeader(type, 1); - mArray[mPosition++] = b; - return this; - } - - /** - * Copies a raw byte into the TLV buffer - without a type or a length. - * - * @param b The byte to be inserted into the structure. - * @return The constructor to facilitate chaining {@code cts.putXXX(..).putXXX(..)}. - */ - public TlvConstructor putRawByte(byte b) { - checkRawLength(1); - mArray[mPosition++] = b; - return this; - } - - /** - * Copies a byte array into the TLV with the indicated type. For an LV - * formatted structure (i.e. typeLength=0 in {@link TlvConstructor - * TlvConstructor(int, int)} ) the type field is ignored. - * - * @param type The value to be placed into the Type field. - * @param array The array to be copied into the TLV structure. - * @param offset Start copying from the array at the specified offset. - * @param length Copy the specified number (length) of bytes from the - * array. - * @return The constructor to facilitate chaining - * {@code ctr.putXXX(..).putXXX(..)}. - */ - public TlvConstructor putByteArray(int type, @Nullable byte[] array, int offset, - int length) { - checkLength(length); - addHeader(type, length); - if (length != 0) { - System.arraycopy(array, offset, mArray, mPosition, length); - } - mPosition += length; - return this; - } - - /** - * Copies a byte array into the TLV with the indicated type. For an LV - * formatted structure (i.e. typeLength=0 in {@link TlvConstructor - * TlvConstructor(int, int)} ) the type field is ignored. - * - * @param type The value to be placed into the Type field. - * @param array The array to be copied (in full) into the TLV structure. - * @return The constructor to facilitate chaining - * {@code ctr.putXXX(..).putXXX(..)}. - */ - public TlvConstructor putByteArray(int type, @Nullable byte[] array) { - return putByteArray(type, array, 0, (array == null) ? 0 : array.length); - } - - /** - * Copies a byte array into the TLV - without a type or a length. - * - * @param array The array to be copied (in full) into the TLV structure. - * @return The constructor to facilitate chaining - * {@code ctr.putXXX(..).putXXX(..)}. - */ - public TlvConstructor putRawByteArray(@Nullable byte[] array) { - if (array == null) return this; - - checkRawLength(array.length); - System.arraycopy(array, 0, mArray, mPosition, array.length); - mPosition += array.length; - return this; - } - - /** - * Places a zero length element (i.e. Length field = 0) into the TLV. - * For an LV formatted structure (i.e. typeLength=0 in - * {@link TlvConstructor TlvConstructor(int, int)} ) the type field is - * ignored. - * - * @param type The value to be placed into the Type field. - * @return The constructor to facilitate chaining - * {@code ctr.putXXX(..).putXXX(..)}. - */ - public TlvConstructor putZeroLengthElement(int type) { - checkLength(0); - addHeader(type, 0); - return this; - } - - /** - * Copies short into the TLV with the indicated type. For an LV - * formatted structure (i.e. typeLength=0 in {@link TlvConstructor - * TlvConstructor(int, int)} ) the type field is ignored. - * - * @param type The value to be placed into the Type field. - * @param data The short to be inserted into the structure. - * @return The constructor to facilitate chaining - * {@code ctr.putXXX(..).putXXX(..)}. - */ - public TlvConstructor putShort(int type, short data) { - checkLength(2); - addHeader(type, 2); - pokeShort(mArray, mPosition, data, mByteOrder); - mPosition += 2; - return this; - } - - /** - * Copies integer into the TLV with the indicated type. For an LV - * formatted structure (i.e. typeLength=0 in {@link TlvConstructor - * TlvConstructor(int, int)} ) the type field is ignored. - * - * @param type The value to be placed into the Type field. - * @param data The integer to be inserted into the structure. - * @return The constructor to facilitate chaining - * {@code ctr.putXXX(..).putXXX(..)}. - */ - public TlvConstructor putInt(int type, int data) { - checkLength(4); - addHeader(type, 4); - pokeInt(mArray, mPosition, data, mByteOrder); - mPosition += 4; - return this; - } - - /** - * Copies a String's byte representation into the TLV with the indicated - * type. For an LV formatted structure (i.e. typeLength=0 in - * {@link TlvConstructor TlvConstructor(int, int)} ) the type field is - * ignored. - * - * @param type The value to be placed into the Type field. - * @param data The string whose bytes are to be inserted into the - * structure. - * @return The constructor to facilitate chaining - * {@code ctr.putXXX(..).putXXX(..)}. - */ - public TlvConstructor putString(int type, @Nullable String data) { - byte[] bytes = null; - int length = 0; - if (data != null) { - bytes = data.getBytes(); - length = bytes.length; - } - return putByteArray(type, bytes, 0, length); - } - - /** - * Returns the constructed TLV formatted byte-array. This array is a copy of the wrapped - * or allocated array - truncated to just the significant bytes - i.e. those written into - * the (T)LV. - * - * @return The byte array containing the TLV formatted structure. - */ - public byte[] getArray() { - return Arrays.copyOf(mArray, getActualLength()); - } - - /** - * Returns the size of the TLV formatted portion of the wrapped or - * allocated byte array. The array itself is returned with - * {@link TlvConstructor#getArray()}. - * - * @return The size of the TLV formatted portion of the byte array. - */ - private int getActualLength() { - return mPosition; - } - - private void checkLength(int dataLength) { - if (mPosition + mTypeSize + mLengthSize + dataLength > mArrayLength) { - throw new BufferOverflowException(); - } - } - - private void checkRawLength(int dataLength) { - if (mPosition + dataLength > mArrayLength) { - throw new BufferOverflowException(); - } - } - - private void addHeader(int type, int length) { - if (mTypeSize == 1) { - mArray[mPosition] = (byte) type; - } else if (mTypeSize == 2) { - pokeShort(mArray, mPosition, (short) type, mByteOrder); - } - mPosition += mTypeSize; - - if (mLengthSize == 1) { - mArray[mPosition] = (byte) length; - } else if (mLengthSize == 2) { - pokeShort(mArray, mPosition, (short) length, mByteOrder); - } - mPosition += mLengthSize; - } - } - - /** - * Utility class used when iterating over a TLV formatted byte-array. Use - * {@link TlvIterable} to iterate over array. A {@link TlvElement} - * represents each entry in a TLV formatted byte-array. - */ - public static class TlvElement { - /** - * The Type (T) field of the current TLV element. Note that for LV - * formatted byte-arrays (i.e. TLV whose Type/T size is 0) the value of - * this field is undefined. - */ - public int type; - - /** - * The Length (L) field of the current TLV element. - */ - public int length; - - /** - * Control of the endianess of the TLV element - true for big-endian, false for little- - * endian. - */ - public ByteOrder byteOrder = ByteOrder.BIG_ENDIAN; - - /** - * The Value (V) field - a raw byte array representing the current TLV - * element where the entry starts at {@link TlvElement#offset}. - */ - private byte[] mRefArray; - - /** - * The offset to be used into {@link TlvElement#mRefArray} to access the - * raw data representing the current TLV element. - */ - public int offset; - - private TlvElement(int type, int length, @Nullable byte[] refArray, int offset) { - this.type = type; - this.length = length; - mRefArray = refArray; - this.offset = offset; - - if (offset + length > refArray.length) { - throw new BufferOverflowException(); - } - } - - /** - * Return the raw byte array of the Value (V) field. - * - * @return The Value (V) field as a byte array. - */ - public byte[] getRawData() { - return Arrays.copyOfRange(mRefArray, offset, offset + length); - } - - /** - * Utility function to return a byte representation of a TLV element of - * length 1. Note: an attempt to call this function on a TLV item whose - * {@link TlvElement#length} is != 1 will result in an exception. - * - * @return byte representation of current TLV element. - */ - public byte getByte() { - if (length != 1) { - throw new IllegalArgumentException( - "Accesing a byte from a TLV element of length " + length); - } - return mRefArray[offset]; - } - - /** - * Utility function to return a short representation of a TLV element of - * length 2. Note: an attempt to call this function on a TLV item whose - * {@link TlvElement#length} is != 2 will result in an exception. - * - * @return short representation of current TLV element. - */ - public short getShort() { - if (length != 2) { - throw new IllegalArgumentException( - "Accesing a short from a TLV element of length " + length); - } - return peekShort(mRefArray, offset, byteOrder); - } - - /** - * Utility function to return an integer representation of a TLV element - * of length 4. Note: an attempt to call this function on a TLV item - * whose {@link TlvElement#length} is != 4 will result in an exception. - * - * @return integer representation of current TLV element. - */ - public int getInt() { - if (length != 4) { - throw new IllegalArgumentException( - "Accesing an int from a TLV element of length " + length); - } - return peekInt(mRefArray, offset, byteOrder); - } - - /** - * Utility function to return a String representation of a TLV element. - * - * @return String repersentation of the current TLV element. - */ - public String getString() { - return new String(mRefArray, offset, length); - } - } - - /** - * Utility class to iterate over a TLV formatted byte-array. - */ - public static class TlvIterable implements Iterable<TlvElement> { - private int mTypeSize; - private int mLengthSize; - private ByteOrder mByteOrder = ByteOrder.BIG_ENDIAN; - private byte[] mArray; - private int mArrayLength; - - /** - * Constructs a TlvIterable object - specifying the format of the TLV - * (the sizes of the Type and Length fields), and the byte array whose - * data is to be parsed. - * - * @param typeSize Number of bytes used for the Type (T) field. Valid - * values are 0 (i.e. indicating the format is LV rather than - * TLV), 1, and 2 bytes. - * @param lengthSize Number of bytes used for the Length (L) field. - * Values values are 1 or 2 bytes. - * @param array The TLV formatted byte-array to parse. - */ - public TlvIterable(int typeSize, int lengthSize, @Nullable byte[] array) { - if (typeSize < 0 || typeSize > 2 || lengthSize <= 0 || lengthSize > 2) { - throw new IllegalArgumentException( - "Invalid sizes - typeSize=" + typeSize + ", lengthSize=" + lengthSize); - } - mTypeSize = typeSize; - mLengthSize = lengthSize; - mArray = array; - mArrayLength = (array == null) ? 0 : array.length; - } - - /** - * Configure the TLV iterator to use little-endian byte ordering. - */ - public void setByteOrder(ByteOrder byteOrder) { - mByteOrder = byteOrder; - } - - /** - * Prints out a parsed representation of the TLV-formatted byte array. - * Whenever possible bytes, shorts, and integer are printed out (for - * fields whose length is 1, 2, or 4 respectively). - */ - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - - builder.append("["); - boolean first = true; - for (TlvElement tlv : this) { - if (!first) { - builder.append(","); - } - first = false; - builder.append(" ("); - if (mTypeSize != 0) { - builder.append("T=" + tlv.type + ","); - } - builder.append("L=" + tlv.length + ") "); - if (tlv.length == 0) { - builder.append("<null>"); - } else if (tlv.length == 1) { - builder.append(tlv.getByte()); - } else if (tlv.length == 2) { - builder.append(tlv.getShort()); - } else if (tlv.length == 4) { - builder.append(tlv.getInt()); - } else { - builder.append("<bytes>"); - } - if (tlv.length != 0) { - builder.append(" (S='" + tlv.getString() + "')"); - } - } - builder.append("]"); - - return builder.toString(); - } - - /** - * Returns a List with the raw contents (no types) of the iterator. - */ - public List<byte[]> toList() { - List<byte[]> list = new ArrayList<>(); - for (TlvElement tlv : this) { - list.add(Arrays.copyOfRange(tlv.mRefArray, tlv.offset, tlv.offset + tlv.length)); - } - - return list; - } - - /** - * Returns an iterator to step through a TLV formatted byte-array. The - * individual elements returned by the iterator are {@link TlvElement}. - */ - @Override - public Iterator<TlvElement> iterator() { - return new Iterator<TlvElement>() { - private int mOffset = 0; - - @Override - public boolean hasNext() { - return mOffset < mArrayLength; - } - - @Override - public TlvElement next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - - int type = 0; - if (mTypeSize == 1) { - type = mArray[mOffset]; - } else if (mTypeSize == 2) { - type = peekShort(mArray, mOffset, mByteOrder); - } - mOffset += mTypeSize; - - int length = 0; - if (mLengthSize == 1) { - length = mArray[mOffset]; - } else if (mLengthSize == 2) { - length = peekShort(mArray, mOffset, mByteOrder); - } - mOffset += mLengthSize; - - TlvElement tlv = new TlvElement(type, length, mArray, mOffset); - tlv.byteOrder = mByteOrder; - mOffset += length; - return tlv; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - } - - /** - * Validates that a (T)LV array is constructed correctly. I.e. that its specified Length - * fields correctly fill the specified length (and do not overshoot). Uses big-endian - * byte ordering. - * - * @param array The (T)LV array to verify. - * @param typeSize The size (in bytes) of the type field. Valid values are 0, 1, or 2. - * @param lengthSize The size (in bytes) of the length field. Valid values are 1 or 2. - * @return A boolean indicating whether the array is valid (true) or invalid (false). - */ - public static boolean isValid(@Nullable byte[] array, int typeSize, int lengthSize) { - return isValidEndian(array, typeSize, lengthSize, ByteOrder.BIG_ENDIAN); - } - - /** - * Validates that a (T)LV array is constructed correctly. I.e. that its specified Length - * fields correctly fill the specified length (and do not overshoot). - * - * @param array The (T)LV array to verify. - * @param typeSize The size (in bytes) of the type field. Valid values are 0, 1, or 2. - * @param lengthSize The size (in bytes) of the length field. Valid values are 1 or 2. - * @param byteOrder The endianness of the byte array: {@link ByteOrder#BIG_ENDIAN} or - * {@link ByteOrder#LITTLE_ENDIAN}. - * @return A boolean indicating whether the array is valid (true) or invalid (false). - */ - public static boolean isValidEndian(@Nullable byte[] array, int typeSize, int lengthSize, - ByteOrder byteOrder) { - if (typeSize < 0 || typeSize > 2) { - throw new IllegalArgumentException( - "Invalid arguments - typeSize must be 0, 1, or 2: typeSize=" + typeSize); - } - if (lengthSize <= 0 || lengthSize > 2) { - throw new IllegalArgumentException( - "Invalid arguments - lengthSize must be 1 or 2: lengthSize=" + lengthSize); - } - if (array == null) { - return true; - } - - int nextTlvIndex = 0; - while (nextTlvIndex + typeSize + lengthSize <= array.length) { - nextTlvIndex += typeSize; - if (lengthSize == 1) { - nextTlvIndex += lengthSize + array[nextTlvIndex]; - } else { - nextTlvIndex += lengthSize + peekShort(array, nextTlvIndex, byteOrder); - } - } - - return nextTlvIndex == array.length; - } - - private static void pokeShort(byte[] dst, int offset, short value, ByteOrder order) { - if (order == ByteOrder.BIG_ENDIAN) { - dst[offset++] = (byte) ((value >> 8) & 0xff); - dst[offset ] = (byte) ((value >> 0) & 0xff); - } else { - dst[offset++] = (byte) ((value >> 0) & 0xff); - dst[offset ] = (byte) ((value >> 8) & 0xff); - } - } - - private static void pokeInt(byte[] dst, int offset, int value, ByteOrder order) { - if (order == ByteOrder.BIG_ENDIAN) { - dst[offset++] = (byte) ((value >> 24) & 0xff); - dst[offset++] = (byte) ((value >> 16) & 0xff); - dst[offset++] = (byte) ((value >> 8) & 0xff); - dst[offset ] = (byte) ((value >> 0) & 0xff); - } else { - dst[offset++] = (byte) ((value >> 0) & 0xff); - dst[offset++] = (byte) ((value >> 8) & 0xff); - dst[offset++] = (byte) ((value >> 16) & 0xff); - dst[offset ] = (byte) ((value >> 24) & 0xff); - } - } - - private static short peekShort(byte[] src, int offset, ByteOrder order) { - if (order == ByteOrder.BIG_ENDIAN) { - return (short) ((src[offset] << 8) | (src[offset + 1] & 0xff)); - } else { - return (short) ((src[offset + 1] << 8) | (src[offset] & 0xff)); - } - } - - private static int peekInt(byte[] src, int offset, ByteOrder order) { - if (order == ByteOrder.BIG_ENDIAN) { - return ((src[offset++] & 0xff) << 24) - | ((src[offset++] & 0xff) << 16) - | ((src[offset++] & 0xff) << 8) - | ((src[offset ] & 0xff) << 0); - } else { - return ((src[offset++] & 0xff) << 0) - | ((src[offset++] & 0xff) << 8) - | ((src[offset++] & 0xff) << 16) - | ((src[offset ] & 0xff) << 24); - } - } -} |