Support IPv4/6 address type in Struct.

Bug: 163492391
Test: atest NetworkStaticLibTests
Change-Id: I17a753ea495f24d186b69083923a71a7ebccdc7b
This commit is contained in:
Xiao Ma
2020-12-28 14:11:04 +00:00
parent 79c8682381
commit 229b17ac0c
4 changed files with 149 additions and 33 deletions

View File

@@ -20,9 +20,6 @@ import android.annotation.Nullable;
/**
* Hex utility functions.
*
* A copy from frameworks/base/core/java/com/android/internal/util/HexDump.java, to be shared
* by multiple modules.
*/
public class HexDump {
private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',

View File

@@ -27,6 +27,10 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -114,6 +118,8 @@ public class Struct {
UBE64, // unsigned long in network order, size = 8 bytes
ByteArray, // byte array with predefined length
EUI48, // IEEE Extended Unique Identifier, a 48-bits long MAC address in network order
Ipv4Address, // IPv4 address in network order
Ipv6Address, // IPv6 address in network order
}
/**
@@ -186,6 +192,12 @@ public class Struct {
case EUI48:
if (fieldType == MacAddress.class) return;
break;
case Ipv4Address:
if (fieldType == Inet4Address.class) return;
break;
case Ipv6Address:
if (fieldType == Inet6Address.class) return;
break;
default:
throw new IllegalArgumentException("Unknown type" + annotation.type());
}
@@ -223,6 +235,12 @@ public class Struct {
case EUI48:
length = 6;
break;
case Ipv4Address:
length = 4;
break;
case Ipv6Address:
length = 16;
break;
default:
throw new IllegalArgumentException("Unknown type" + annotation.type());
}
@@ -388,6 +406,17 @@ public class Struct {
buf.get(macAddress);
value = MacAddress.fromBytes(macAddress);
break;
case Ipv4Address:
case Ipv6Address:
final boolean isIpv6 = (fieldInfo.annotation.type() == Type.Ipv6Address);
final byte[] address = new byte[isIpv6 ? 16 : 4];
buf.get(address);
try {
value = InetAddress.getByAddress(address);
} catch (UnknownHostException e) {
throw new IllegalArgumentException("illegal length of IP address", e);
}
break;
default:
throw new IllegalArgumentException("Unknown type:" + fieldInfo.annotation.type());
}
@@ -461,6 +490,11 @@ public class Struct {
final byte[] macAddress = ((MacAddress) value).toByteArray();
output.put(macAddress);
break;
case Ipv4Address:
case Ipv6Address:
final byte[] address = ((InetAddress) value).getAddress();
output.put(address);
break;
default:
throw new IllegalArgumentException("Unknown type:" + fieldInfo.annotation.type());
}
@@ -671,8 +705,11 @@ public class Struct {
}
if (value == null) {
sb.append("null");
} else if (fieldInfos[i].field.getType() == byte[].class) {
} else if (fieldInfos[i].annotation.type() == Type.ByteArray) {
sb.append("0x").append(HexDump.toHexString((byte[]) value));
} else if (fieldInfos[i].annotation.type() == Type.Ipv4Address
|| fieldInfos[i].annotation.type() == Type.Ipv6Address) {
sb.append(((InetAddress) value).getHostAddress());
} else {
sb.append(value.toString());
}

View File

@@ -42,7 +42,7 @@ public class HexDumpTest {
}
@Test
public void testHexStringToBytes() {
public void testHexStringToByteArray() {
assertArrayEquals(new byte[]{(byte) 0xab, (byte) 0xcd, (byte) 0xef},
HexDump.hexStringToByteArray("abcdef"));
assertArrayEquals(new byte[]{(byte) 0xAB, (byte) 0xCD, (byte) 0xEF},
@@ -50,13 +50,13 @@ public class HexDumpTest {
}
@Test
public void testIntegerToBytes() {
public void testIntegerToByteArray() {
assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x04},
HexDump.toByteArray((int) 0xff000004));
}
@Test
public void testByteToBytes() {
public void testByteToByteArray() {
assertArrayEquals(new byte[]{(byte) 0x7f}, HexDump.toByteArray((byte) 0x7f));
}

View File

@@ -24,6 +24,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.MacAddress;
@@ -38,6 +39,8 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
@@ -74,6 +77,11 @@ public class StructTest {
(byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x06,
};
private static final Inet4Address TEST_IPV4_ADDRESS =
(Inet4Address) InetAddresses.parseNumericAddress("192.168.100.1");
private static final Inet6Address TEST_IPV6_ADDRESS =
(Inet6Address) InetAddresses.parseNumericAddress("2001:db8:3:4:5:6:7:8");
private <T> T doParsingMessageTest(final String hexString, final Class<T> clazz,
final ByteOrder order) {
final ByteBuffer buf = toByteBuffer(hexString);
@@ -733,6 +741,41 @@ public class StructTest {
assertArrayEquals(toByteBuffer(hexString).array(), msg.writeToBytes());
}
static class IpAddressMessage extends Struct {
@Field(order = 0, type = Type.Ipv4Address) public final Inet4Address ipv4Address;
@Field(order = 1, type = Type.Ipv6Address) public final Inet6Address ipv6Address;
IpAddressMessage(final Inet4Address ipv4Address, final Inet6Address ipv6Address) {
this.ipv4Address = ipv4Address;
this.ipv6Address = ipv6Address;
}
}
@Test
public void testIpAddressType() {
final IpAddressMessage msg = doParsingMessageTest("c0a86401"
+ "20010db8000300040005000600070008", IpAddressMessage.class, ByteOrder.BIG_ENDIAN);
assertEquals(TEST_IPV4_ADDRESS, msg.ipv4Address);
assertEquals(TEST_IPV6_ADDRESS, msg.ipv6Address);
assertEquals(20, Struct.getSize(IpAddressMessage.class));
assertArrayEquals(toByteBuffer("c0a86401" + "20010db8000300040005000600070008").array(),
msg.writeToBytes(ByteOrder.BIG_ENDIAN));
}
static class WrongIpAddressType extends Struct {
@Field(order = 0, type = Type.Ipv4Address) public byte[] ipv4Address;
@Field(order = 1, type = Type.Ipv6Address) public byte[] ipv6Address;
}
@Test
public void testIncorrectType_IpAddressWithByteArray() {
assertThrows(IllegalArgumentException.class,
() -> Struct.parse(WrongIpAddressType.class,
toByteBuffer("c0a86401" + "20010db8000300040005000600070008")));
}
static class FullTypeMessage extends Struct {
@Field(order = 0, type = Type.U8) public final short u8;
@Field(order = 1, type = Type.U16) public final int u16;
@@ -749,11 +792,14 @@ public class StructTest {
@Field(order = 12, type = Type.UBE64) public final BigInteger ube64;
@Field(order = 13, type = Type.ByteArray, arraysize = 12) public final byte[] bytes;
@Field(order = 14, type = Type.EUI48) public final MacAddress eui48;
@Field(order = 15, type = Type.Ipv4Address) public final Inet4Address ipv4Address;
@Field(order = 16, type = Type.Ipv6Address) public final Inet6Address ipv6Address;
FullTypeMessage(final short u8, final int u16, final long u32, final long u63,
final BigInteger u64, final byte s8, final short s16, final int s32, final long s64,
final int ube16, final long ube32, final long ube63, final BigInteger ube64,
final byte[] bytes, final MacAddress eui48) {
final byte[] bytes, final MacAddress eui48, final Inet4Address ipv4Address,
final Inet6Address ipv6Address) {
this.u8 = u8;
this.u16 = u16;
this.u32 = u32;
@@ -769,25 +815,40 @@ public class StructTest {
this.ube64 = ube64;
this.bytes = bytes;
this.eui48 = eui48;
this.ipv4Address = ipv4Address;
this.ipv6Address = ipv6Address;
}
}
private static final String FULL_TYPE_DATA = "ff" + "ffff" + "ffffffff" + "7fffffffffffffff"
+ "ffffffffffffffff" + "7f" + "7fff" + "7fffffff" + "7fffffffffffffff" + "7fff"
+ "7fffffff" + "7fffffffffffffff" + "ffffffffffffffff" + "20010db80003000400050006"
+ "001122334455";
+ "001122334455" + "c0a86401" + "20010db8000300040005000600070008";
private static final String FULL_TYPE_DATA_DIFF_MAC = "ff" + "ffff" + "ffffffff"
+ "7fffffffffffffff" + "ffffffffffffffff" + "7f" + "7fff" + "7fffffff"
+ "7fffffffffffffff" + "7fff" + "7fffffff" + "7fffffffffffffff" + "ffffffffffffffff"
+ "20010db80003000400050006" + "112233445566";
+ "20010db80003000400050006" + "112233445566"
+ "c0a86401" + "20010db8000300040005000600070008";
private static final String FULL_TYPE_DATA_DIFF_LONG = "ff" + "ffff" + "ffffffff"
+ "7ffffffffffffffe" + "ffffffffffffffff" + "7f" + "7fff" + "7fffffff"
+ "7fffffffffffffff" + "7fff" + "7fffffff" + "7fffffffffffffff" + "ffffffffffffffff"
+ "20010db80003000400050006" + "001122334455";
+ "20010db80003000400050006" + "001122334455"
+ "c0a86401" + "20010db8000300040005000600070008";
private static final String FULL_TYPE_DATA_DIFF_INTEGER = "ff" + "ffff" + "ffffffff"
+ "7fffffffffffffff" + "ffffffffffffffff" + "7f" + "7fff" + "7fffffff"
+ "7fffffffffffffff" + "7fff" + "ffffff7f" + "7fffffffffffffff" + "ffffffffffffffff"
+ "20010db80003000400050006" + "001122334455";
+ "20010db80003000400050006" + "001122334455"
+ "c0a86401" + "20010db8000300040005000600070008";
private static final String FULL_TYPE_DATA_DIFF_IPV4 = "ff" + "ffff" + "ffffffff"
+ "7fffffffffffffff" + "ffffffffffffffff" + "7f" + "7fff" + "7fffffff"
+ "7fffffffffffffff" + "7fff" + "ffffff7f" + "7fffffffffffffff" + "ffffffffffffffff"
+ "20010db80003000400050006" + "001122334455"
+ "c0a81010" + "20010db8000300040005000600070008";
private static final String FULL_TYPE_DATA_DIFF_IPV6 = "ff" + "ffff" + "ffffffff"
+ "7fffffffffffffff" + "ffffffffffffffff" + "7f" + "7fff" + "7fffffff"
+ "7fffffffffffffff" + "7fff" + "ffffff7f" + "7fffffffffffffff" + "ffffffffffffffff"
+ "20010db80003000400050006" + "001122334455"
+ "c0a86401" + "20010db800030004000500060007000a";
@Test
public void testStructClass_equals() {
final FullTypeMessage msg = doParsingMessageTest(FULL_TYPE_DATA, FullTypeMessage.class,
@@ -808,8 +869,10 @@ public class StructTest {
assertEquals(new BigInteger("18446744073709551615"), msg.ube64);
assertArrayEquals(TEST_PREFIX64, msg.bytes);
assertEquals(MacAddress.fromString("00:11:22:33:44:55"), msg.eui48);
assertEquals(TEST_IPV4_ADDRESS, msg.ipv4Address);
assertEquals(TEST_IPV6_ADDRESS, msg.ipv6Address);
assertEquals(78, msg.getSize(FullTypeMessage.class));
assertEquals(98, msg.getSize(FullTypeMessage.class));
assertArrayEquals(toByteBuffer(FULL_TYPE_DATA).array(),
msg.writeToBytes(ByteOrder.BIG_ENDIAN));
@@ -818,7 +881,7 @@ public class StructTest {
new BigInteger("18446744073709551615"), (byte) 0x7f, (short) 0x7fff,
(int) 0x7fffffff, (long) 0x7fffffffffffffffL, (int) 0x7fff, (long) 0x7fffffffL,
(long) 0x7fffffffffffffffL, new BigInteger("18446744073709551615"), TEST_PREFIX64,
MacAddress.fromString("00:11:22:33:44:55"));
MacAddress.fromString("00:11:22:33:44:55"), TEST_IPV4_ADDRESS, TEST_IPV6_ADDRESS);
assertTrue(msg.equals(msg1));
}
@@ -838,11 +901,14 @@ public class StructTest {
@Field(order = 12, type = Type.UBE64) public final BigInteger ube64;
@Field(order = 13, type = Type.ByteArray, arraysize = 12) public final byte[] bytes;
@Field(order = 14, type = Type.EUI48) public final MacAddress eui48;
@Field(order = 15, type = Type.Ipv4Address) public final Inet4Address ipv4Address;
@Field(order = 16, type = Type.Ipv6Address) public final Inet6Address ipv6Address;
FullTypeMessageWithDupType(final short u8, final int u16, final long u32, final long u63,
final BigInteger u64, final byte s8, final short s16, final int s32, final long s64,
final int ube16, final long ube32, final long ube63, final BigInteger ube64,
final byte[] bytes, final MacAddress eui48) {
final byte[] bytes, final MacAddress eui48, final Inet4Address ipv4Address,
final Inet6Address ipv6Address) {
this.u8 = u8;
this.u16 = u16;
this.u32 = u32;
@@ -858,6 +924,8 @@ public class StructTest {
this.ube64 = ube64;
this.bytes = bytes;
this.eui48 = eui48;
this.ipv4Address = ipv4Address;
this.ipv6Address = ipv6Address;
}
}
@@ -900,6 +968,17 @@ public class StructTest {
assertNotEquals(msg.ube32, msg4.ube32);
assertFalse(msg.equals(msg4));
// With different IPv4 address.
final FullTypeMessage msg5 = doParsingMessageTest(FULL_TYPE_DATA_DIFF_IPV4,
FullTypeMessage.class, ByteOrder.BIG_ENDIAN);
assertNotEquals(msg.ipv4Address, msg5.ipv4Address);
assertFalse(msg.equals(msg5));
// With different IPv6 address.
final FullTypeMessage msg6 = doParsingMessageTest(FULL_TYPE_DATA_DIFF_IPV6,
FullTypeMessage.class, ByteOrder.BIG_ENDIAN);
assertNotEquals(msg.ipv6Address, msg6.ipv6Address);
assertFalse(msg.equals(msg6));
}
@Test
@@ -909,7 +988,9 @@ public class StructTest {
+ " s32: 2147483647, s64: 9223372036854775807, ube16: 32767, ube32: 2147483647,"
+ " ube63: 9223372036854775807, ube64: 18446744073709551615,"
+ " bytes: 0x20010DB80003000400050006,"
+ " eui48: 00:11:22:33:44:55";
+ " eui48: 00:11:22:33:44:55,"
+ " ipv4Address: 192.168.100.1,"
+ " ipv6Address: 2001:db8:3:4:5:6:7:8";
final FullTypeMessage msg = doParsingMessageTest(FULL_TYPE_DATA, FullTypeMessage.class,
ByteOrder.BIG_ENDIAN);
@@ -922,14 +1003,15 @@ public class StructTest {
+ " u63: 9223372036854775807, u64: null, s8: 127, s16: 32767,"
+ " s32: 2147483647, s64: 9223372036854775807, ube16: 32767, ube32: 2147483647,"
+ " ube63: 9223372036854775807, ube64: 18446744073709551615,"
+ " bytes: null, eui48: null";
+ " bytes: null, eui48: null, ipv4Address: 192.168.100.1,"
+ " ipv6Address: null";
final FullTypeMessage msg = new FullTypeMessage((short) 0xff, (int) 0xffff,
(long) 0xffffffffL, (long) 0x7fffffffffffffffL,
null /* u64 */, (byte) 0x7f, (short) 0x7fff,
(int) 0x7fffffff, (long) 0x7fffffffffffffffL, (int) 0x7fff, (long) 0x7fffffffL,
(long) 0x7fffffffffffffffL, new BigInteger("18446744073709551615"),
null /* bytes */, null /* eui48 */);
null /* bytes */, null /* eui48 */, TEST_IPV4_ADDRESS, null /* ipv6Address */);
assertEquals(expected, msg.toString());
}