< prev index next >

src/java.base/share/classes/sun/nio/ch/NativeSocketAddress.java

Print this page
M NativeSocketAddress.java

*** 1,7 **** /* ! * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 23,57 **** * questions. */ package sun.nio.ch; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ProtocolFamily; import java.net.SocketException; import java.net.StandardProtocolFamily; import java.net.UnknownHostException; import java.nio.channels.UnsupportedAddressTypeException; ! import jdk.internal.access.JavaNetInetAddressAccess; import jdk.internal.access.SharedSecrets; ! import jdk.internal.misc.Unsafe; ! import jdk.internal.util.ArraysSupport; /** * A native socket address that is the union of struct sockaddr, struct sockaddr_in, * and struct sockaddr_in6. * * This class is not thread safe. */ class NativeSocketAddress { private static final JavaNetInetAddressAccess JNINA = SharedSecrets.getJavaNetInetAddressAccess(); - private static final Unsafe UNSAFE = Unsafe.getUnsafe(); - private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class); private static final int AF_INET = AFINET(); private static final int AF_INET6 = AFINET6(); private static final int SIZEOF_SOCKADDR4 = sizeofSockAddr4(); --- 23,64 ---- * questions. */ package sun.nio.ch; + import java.lang.invoke.MethodHandle; + import java.lang.invoke.MethodHandles; + import java.lang.invoke.MethodType; + import java.lang.invoke.VarHandle; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ProtocolFamily; import java.net.SocketException; import java.net.StandardProtocolFamily; import java.net.UnknownHostException; + import java.nio.ByteOrder; import java.nio.channels.UnsupportedAddressTypeException; ! import jdk.incubator.foreign.MemoryAddress; ! import jdk.incubator.foreign.MemoryHandles; ! import jdk.incubator.foreign.MemoryLayout; ! import jdk.incubator.foreign.MemoryLayout.PathElement; ! import jdk.incubator.foreign.MemoryLayouts; ! import jdk.incubator.foreign.MemorySegment; import jdk.internal.access.JavaNetInetAddressAccess; import jdk.internal.access.SharedSecrets; ! import static jdk.incubator.foreign.MemoryLayout.PathElement.*; /** * A native socket address that is the union of struct sockaddr, struct sockaddr_in, * and struct sockaddr_in6. * * This class is not thread safe. */ class NativeSocketAddress { private static final JavaNetInetAddressAccess JNINA = SharedSecrets.getJavaNetInetAddressAccess(); private static final int AF_INET = AFINET(); private static final int AF_INET6 = AFINET6(); private static final int SIZEOF_SOCKADDR4 = sizeofSockAddr4();
*** 64,84 **** private static final int OFFSET_SIN6_PORT = offsetSin6Port(); private static final int OFFSET_SIN6_ADDR = offsetSin6Addr(); private static final int OFFSET_SIN6_SCOPE_ID = offsetSin6ScopeId(); private static final int OFFSET_SIN6_FLOWINFO = offsetSin6FlowInfo(); ! // SOCKETADDRESS ! private final long address; long address() { ! return address; } NativeSocketAddress() { ! long base = UNSAFE.allocateMemory(SIZEOF_SOCKETADDRESS); ! UNSAFE.setMemory(base, SIZEOF_SOCKETADDRESS, (byte) 0); ! this.address = base; } /** * Allocate an array of native socket addresses. */ --- 71,245 ---- private static final int OFFSET_SIN6_PORT = offsetSin6Port(); private static final int OFFSET_SIN6_ADDR = offsetSin6Addr(); private static final int OFFSET_SIN6_SCOPE_ID = offsetSin6ScopeId(); private static final int OFFSET_SIN6_FLOWINFO = offsetSin6FlowInfo(); ! private static final ByteOrder NETWORK_BYTE_ORDER = ByteOrder.BIG_ENDIAN; ! private static final ByteOrder HOST_BYTE_ORDER = ByteOrder.nativeOrder(); ! ! private static final MemoryLayout SOCKADDR; ! ! private static final int SOCKADDR_IN_SIZE; ! private static final int SOCKADDR_IN6_SIZE; ! ! private static final VarHandle SA_FAMILY_HANDLE; ! private static final VarHandle SIN_PORT_HANDLE; ! private static final VarHandle SIN_ADDR_HANDLE; ! private static final VarHandle SIN6_PORT_HANDLE; ! private static final VarHandle SIN6_FLOWINFO_HANDLE; ! private static final VarHandle SIN6_ADDR_HANDLE; ! private static final VarHandle SIN6_SCOPE_HANDLE; ! private static final VarHandle BYTEWISE_HANDLE; ! ! // byte/short to/from int adapter handles ! private static final MethodHandle INT_TO_SHORT; ! private static final MethodHandle SHORT_TO_UNSIGNED_INT; ! private static final MethodHandle INT_TO_BYTE; ! private static final MethodHandle BYTE_TO_UNSIGNED_INT; ! ! private static final boolean VERIFY = true; ! private static final boolean DEBUG = true; ! ! static { ! try { ! var lookup = MethodHandles.lookup(); ! BYTE_TO_UNSIGNED_INT = lookup.findStatic(Byte.class, "toUnsignedInt", MethodType.methodType(int.class, byte.class)); ! INT_TO_BYTE = lookup.findStatic(NativeSocketAddress.class, "byteValue", MethodType.methodType(byte.class, int.class)); ! SHORT_TO_UNSIGNED_INT = lookup.findStatic(Short.class, "toUnsignedInt", MethodType.methodType(int.class, short.class)); ! INT_TO_SHORT = lookup.findStatic(NativeSocketAddress.class, "shortValue", MethodType.methodType(short.class, int.class)); ! } catch (Throwable throwable) { ! throw new AssertionError(throwable); ! } ! ! MemoryLayout familyLayout; ! if (OFFSET_FAMILY == 1 && SIZEOF_FAMILY == 1) { ! familyLayout = MemoryLayout.ofStruct(MemoryLayout.ofPaddingBits(8), MemoryLayouts.JAVA_BYTE.withName("sa_family")); ! SA_FAMILY_HANDLE = MemoryHandles.filterValue( ! familyLayout.varHandle(byte.class, groupElement("sa_family")), ! INT_TO_BYTE, ! BYTE_TO_UNSIGNED_INT); ! } else if (OFFSET_FAMILY == 0 && SIZEOF_FAMILY == 2) { ! familyLayout = MemoryLayouts.JAVA_SHORT.withName("sa_family"); ! SA_FAMILY_HANDLE = MemoryHandles.filterValue( ! familyLayout.varHandle(short.class), ! INT_TO_SHORT, ! SHORT_TO_UNSIGNED_INT); ! } else { ! throw new InternalError("unknown family [offset:%d, size:%d]".formatted(OFFSET_FAMILY, SIZEOF_FAMILY)); ! } ! ! SOCKADDR = MemoryLayout.ofUnion( ! MemoryLayout.ofStruct(familyLayout, ! MemoryLayout.ofValueBits(16, NETWORK_BYTE_ORDER).withName("sin_port"), ! //MemoryLayouts.BITS_32_BE.withName("sin_addr")) // #### treat as bits rather than bytes? ! MemoryLayout.ofSequence(4, MemoryLayouts.JAVA_BYTE).withName("sin_addr"), ! MemoryLayout.ofPaddingBits(64)) // pad to size of struct sockaddr ! .withName("sockaddr_in"), ! MemoryLayout.ofStruct(familyLayout, ! MemoryLayout.ofValueBits(16, NETWORK_BYTE_ORDER).withName("sin6_port"), ! MemoryLayout.ofValueBits(32, HOST_BYTE_ORDER).withName("sin6_flowinfo"), ! //MemoryLayout.ofValueBits(128, NETWORK_BYTE_ORDER).withName("sin6_addr"), // #### treat as bits rather than bytes? ! MemoryLayout.ofSequence(16, MemoryLayouts.JAVA_BYTE).withName("sin6_addr"), ! MemoryLayout.ofValueBits(32, HOST_BYTE_ORDER).withName("sin6_scope_id")) ! .withName("sockaddr_in6")) ! .withName("sockaddr"); ! ! PathElement sockaddr_in = groupElement("sockaddr_in"); ! SIN_PORT_HANDLE = MemoryHandles.filterValue( ! SOCKADDR.varHandle(short.class, sockaddr_in, groupElement("sin_port")), ! INT_TO_SHORT, ! SHORT_TO_UNSIGNED_INT); ! SIN_ADDR_HANDLE = SOCKADDR.varHandle(byte.class, sockaddr_in, groupElement("sin_addr"), sequenceElement()); ! PathElement sockaddr_in6 = groupElement("sockaddr_in6"); ! SIN6_PORT_HANDLE = MemoryHandles.filterValue( ! SOCKADDR.varHandle(short.class, sockaddr_in6, groupElement("sin6_port")), ! INT_TO_SHORT, ! SHORT_TO_UNSIGNED_INT); ! SIN6_FLOWINFO_HANDLE = SOCKADDR.varHandle(int.class, sockaddr_in6, groupElement("sin6_flowinfo")); ! SIN6_ADDR_HANDLE = SOCKADDR.varHandle(byte.class, sockaddr_in6, groupElement("sin6_addr"), sequenceElement()); ! SIN6_SCOPE_HANDLE = SOCKADDR.varHandle(int.class, sockaddr_in6, groupElement("sin6_scope_id")); ! ! // byte-wise handle for equality comparison ! MemoryLayout layout = MemoryLayout.ofSequence(SOCKADDR.byteSize(), MemoryLayouts.JAVA_BYTE); ! BYTEWISE_HANDLE = layout.varHandle(byte.class, sequenceElement()); ! ! SOCKADDR_IN_SIZE = (int) SOCKADDR.select(sockaddr_in).byteSize(); ! SOCKADDR_IN6_SIZE = (int) SOCKADDR.select(sockaddr_in6).byteSize(); ! ! debug(); ! // Verifies the handcrafted layout against the natively derived sizes and offsets ! if (VERIFY) ! verify(); ! } ! ! private static void verify() { ! // sockaddr_in ! PathElement sockaddr_in = groupElement("sockaddr_in"); ! assert SIZEOF_SOCKADDR4 == SOCKADDR_IN_SIZE : "SIZEOF_SOCKADDR [%d] != SOCKADDR_IN_SIZE [%d]".formatted(SIZEOF_SOCKADDR4, SOCKADDR_IN_SIZE); ! var offset = bitsToBytes(SOCKADDR.offset(sockaddr_in , groupElement("sin_port"))); ! assert offset == OFFSET_SIN4_PORT : "OFFSET_SIN4_PORT [%d] != layout offset [%d]".formatted(OFFSET_SIN4_PORT, offset); ! offset = bitsToBytes(SOCKADDR.offset(sockaddr_in , groupElement("sin_addr"))); ! assert offset == OFFSET_SIN4_ADDR : "OFFSET_SIN4_ADDR [%d] != layout offset [%d]".formatted(OFFSET_SIN4_ADDR, offset); ! ! //sockaddr_in6 ! PathElement sockaddr_in6 = groupElement("sockaddr_in6"); ! assert SIZEOF_SOCKADDR6 == SOCKADDR_IN6_SIZE : "SIZEOF_SOCKADDR6 [%d] != SOCKADDR_IN6_SIZE [%d]".formatted(SIZEOF_SOCKADDR6, SOCKADDR_IN6_SIZE); ! offset = bitsToBytes(SOCKADDR.offset(sockaddr_in6 , groupElement("sin6_port"))); ! assert offset == OFFSET_SIN6_PORT : "OFFSET_SIN6_PORT [%d] != layout offset [%d]".formatted(OFFSET_SIN6_PORT, offset); ! offset = bitsToBytes(SOCKADDR.offset(sockaddr_in6 , groupElement("sin6_addr"))); ! assert offset == OFFSET_SIN6_ADDR : "OFFSET_SIN6_ADDR [%d] != layout offset [%d]".formatted(OFFSET_SIN6_ADDR, offset); ! offset = bitsToBytes(SOCKADDR.offset(sockaddr_in6 , groupElement("sin6_flowinfo"))); ! assert offset == OFFSET_SIN6_FLOWINFO : "OFFSET_SIN6_FLOWINFO [%d] != layout offset [%d]".formatted(OFFSET_SIN6_FLOWINFO, offset); ! offset = bitsToBytes(SOCKADDR.offset(sockaddr_in6 , groupElement("sin6_scope_id"))); ! assert offset == OFFSET_SIN6_SCOPE_ID : "OFFSET_SIN6_SCOPE_ID [%d] != layout offset [%d]".formatted(OFFSET_SIN6_SCOPE_ID, offset); ! } ! ! private static void debug() { ! if (DEBUG) { ! System.out.println("SIZEOF_SOCKADDR4:" + SIZEOF_SOCKADDR4); ! System.out.println("SIZEOF_SOCKADDR6:" + SIZEOF_SOCKADDR6); ! System.out.println("SIZEOF_SOCKETADDRESS:" + SIZEOF_SOCKETADDRESS); ! System.out.println("SIZEOF_FAMILY:" + SIZEOF_FAMILY); ! System.out.println("OFFSET_FAMILY:" + OFFSET_FAMILY); ! System.out.println("OFFSET_SIN4_PORT:" + OFFSET_SIN4_PORT); ! System.out.println("OFFSET_SIN4_ADDR:" + OFFSET_SIN4_ADDR); ! System.out.println("OFFSET_SIN6_PORT:" + OFFSET_SIN6_PORT); ! System.out.println("OFFSET_SIN6_ADDR:" + OFFSET_SIN6_ADDR); ! System.out.println("OFFSET_SIN6_SCOPE_ID:" + OFFSET_SIN6_SCOPE_ID); ! System.out.println("OFFSET_SIN6_FLOWINFO:" + OFFSET_SIN6_FLOWINFO); ! System.out.println("SOCKADDR layout:" + SOCKADDR); ! System.out.println("SOCKADDR layout byteSize:" + SOCKADDR.byteSize()); ! System.out.println("SOCKADDR layout byteAlignment:" + SOCKADDR.byteAlignment()); ! } ! } ! ! private static long bitsToBytes(long value) { ! return value / 8; ! } ! ! private static byte byteValue(int value) { ! return (byte)value; ! } ! ! private static short shortValue(int value) { ! return (short)value; ! } ! ! private final MemorySegment segment; ! private final MemoryAddress memoryAddress; ! private final long rawAddress; long address() { ! return rawAddress; } NativeSocketAddress() { ! var initialSegment = MemorySegment.allocateNative(SOCKADDR); ! //segment = MemorySegment.ofNativeRestricted(initialSegment.baseAddress(), initialSegment.byteSize(), null, () -> initialSegment.close(), null); // TODO: cannot close from another thread! ! segment = MemorySegment.ofNativeRestricted(initialSegment.baseAddress(), initialSegment.byteSize(), null, null, null); ! memoryAddress = segment.baseAddress(); ! rawAddress = memoryAddress.toRawLongValue(); } /** * Allocate an array of native socket addresses. */
*** 100,110 **** */ static void freeAll(NativeSocketAddress[] array) { for (int i = 0; i < array.length; i++) { NativeSocketAddress sa = array[i]; if (sa != null) { ! UNSAFE.freeMemory(sa.address); } } } /** --- 261,272 ---- */ static void freeAll(NativeSocketAddress[] array) { for (int i = 0; i < array.length; i++) { NativeSocketAddress sa = array[i]; if (sa != null) { ! sa.segment.close(); ! // #### underlying segment is not closed } } } /**
*** 114,138 **** * @return the size of the socket address (sizeof sockaddr or sockaddr6) * @throws UnsupportedAddressTypeException if the address type is not supported */ int encode(ProtocolFamily protocolFamily, InetSocketAddress isa) { if (protocolFamily == StandardProtocolFamily.INET) { ! // struct sockaddr InetAddress ia = isa.getAddress(); if (!(ia instanceof Inet4Address)) throw new UnsupportedAddressTypeException(); putFamily(AF_INET); putAddress(AF_INET, ia); putPort(AF_INET, isa.getPort()); ! return SIZEOF_SOCKADDR4; } else { ! // struct sockaddr6 putFamily(AF_INET6); putAddress(AF_INET6, isa.getAddress()); putPort(AF_INET6, isa.getPort()); ! UNSAFE.putInt(address + OFFSET_SIN6_FLOWINFO, 0); ! return SIZEOF_SOCKADDR6; } } /** * Return an InetSocketAddress to represent the socket address in this buffer. --- 276,300 ---- * @return the size of the socket address (sizeof sockaddr or sockaddr6) * @throws UnsupportedAddressTypeException if the address type is not supported */ int encode(ProtocolFamily protocolFamily, InetSocketAddress isa) { if (protocolFamily == StandardProtocolFamily.INET) { ! // struct sockaddr_in InetAddress ia = isa.getAddress(); if (!(ia instanceof Inet4Address)) throw new UnsupportedAddressTypeException(); putFamily(AF_INET); putAddress(AF_INET, ia); putPort(AF_INET, isa.getPort()); ! return SOCKADDR_IN_SIZE; } else { ! // struct sockaddr_in6 putFamily(AF_INET6); putAddress(AF_INET6, isa.getAddress()); putPort(AF_INET6, isa.getPort()); ! SIN6_FLOWINFO_HANDLE.set(memoryAddress, 0); ! return SOCKADDR_IN6_SIZE; } } /** * Return an InetSocketAddress to represent the socket address in this buffer.
*** 143,188 **** if (family != AF_INET && family != AF_INET6) throw new SocketException("Socket family not recognized"); return new InetSocketAddress(address(family), port(family)); } - /** - * Find a mismatch between this and another socket address - * @return the byte offset of the first mismatch or -1 if no mismatch - */ - private int mismatch(NativeSocketAddress other) { - int i = ArraysSupport.vectorizedMismatch(null, - this.address, - null, - other.address, - SIZEOF_SOCKETADDRESS, - ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE); - if (i >= 0) - return i; - i = SIZEOF_SOCKETADDRESS - ~i; - for (; i < SIZEOF_SOCKETADDRESS; i++) { - if (UNSAFE.getByte(this.address + i) != UNSAFE.getByte(other.address + i)) { - return i; - } - } - return -1; - } - @Override public boolean equals(Object other) { ! if (other instanceof NativeSocketAddress) { ! return mismatch((NativeSocketAddress) other) < 0; ! } else { return false; } } @Override public int hashCode() { int h = 0; ! for (int offset = 0; offset < SIZEOF_SOCKETADDRESS; offset++) { ! h = 31 * h + UNSAFE.getByte(address + offset); } return h; } @Override --- 305,340 ---- if (family != AF_INET && family != AF_INET6) throw new SocketException("Socket family not recognized"); return new InetSocketAddress(address(family), port(family)); } @Override public boolean equals(Object other) { ! if (!(other instanceof NativeSocketAddress)) { ! return false; ! } ! var that = (NativeSocketAddress)other; ! ! // #### this is byte-at-a-time, do we need to compare with a larger stride? ! ! final MemoryAddress thisAddress = this.memoryAddress; ! final MemoryAddress thatAddress = that.memoryAddress; ! for (int i = 0; i < SOCKADDR.byteSize(); i++) { ! byte b1 = (byte) BYTEWISE_HANDLE.get(thisAddress, i); ! byte b2 = (byte) BYTEWISE_HANDLE.get(thatAddress, i); ! if (b1 != b2) return false; } + return true; } @Override public int hashCode() { int h = 0; ! final MemoryAddress address = memoryAddress; ! for (int i = 0; i < SOCKADDR.byteSize(); i++) { ! h = 31 * h + (byte) BYTEWISE_HANDLE.get(address, i); } return h; } @Override
*** 198,281 **** /** * Return the value of the sa_family field. */ private int family() { ! if (SIZEOF_FAMILY == 1) { ! return UNSAFE.getByte(address + OFFSET_FAMILY); ! } else if (SIZEOF_FAMILY == 2) { ! return UNSAFE.getShort(address + OFFSET_FAMILY); ! } else { ! throw new InternalError(); ! } } /** * Stores the given family in the sa_family field. */ private void putFamily(int family) { ! if (SIZEOF_FAMILY == 1) { ! UNSAFE.putByte(address + OFFSET_FAMILY, (byte) family); ! } else if (SIZEOF_FAMILY == 2) { ! UNSAFE.putShort(address + OFFSET_FAMILY, (short) family); ! } else { ! throw new InternalError(); ! } } /** * Return the value of the sin_port or sin6_port field. These fields are * stored in network order. */ private int port(int family) { ! byte b1, b2; ! if (family == AF_INET) { ! b1 = UNSAFE.getByte(address + OFFSET_SIN4_PORT); ! b2 = UNSAFE.getByte(address + OFFSET_SIN4_PORT + 1); ! } else { ! b1 = UNSAFE.getByte(address + OFFSET_SIN6_PORT); ! b2 = UNSAFE.getByte(address + OFFSET_SIN6_PORT + 1); ! } ! return (Byte.toUnsignedInt(b1) << 8) + Byte.toUnsignedInt(b2); } /** * Stores the given port number in the sin_port or sin6_port field. The * port is stored in network order. */ private void putPort(int family, int port) { ! byte b1 = (byte) ((port >> 8) & 0xff); ! byte b2 = (byte) ((port >> 0) & 0xff); ! if (family == AF_INET) { ! UNSAFE.putByte(address + OFFSET_SIN4_PORT, b1); ! UNSAFE.putByte(address + OFFSET_SIN4_PORT + 1, b2); ! } else { ! UNSAFE.putByte(address + OFFSET_SIN6_PORT, b1); ! UNSAFE.putByte(address + OFFSET_SIN6_PORT + 1, b2); ! } } /** * Return an InetAddress to represent the value of the address in the * sin4_addr or sin6_addr fields. For IPv6 addresses, the Inet6Address is * created with the sin6_scope_id in the sockaddr_in6 structure. */ private InetAddress address(int family) { ! int len; ! int offset; int scope_id; if (family == AF_INET) { ! len = 4; ! offset = OFFSET_SIN4_ADDR; scope_id = 0; } else { ! len = 16; ! offset = OFFSET_SIN6_ADDR; ! scope_id = UNSAFE.getInt(address + OFFSET_SIN6_SCOPE_ID); } - byte[] bytes = new byte[len]; - UNSAFE.copyMemory(null, address + offset, bytes, ARRAY_BASE_OFFSET, len); try { if (scope_id == 0) { return InetAddress.getByAddress(bytes); } else { return Inet6Address.getByAddress(null, bytes, scope_id); --- 350,412 ---- /** * Return the value of the sa_family field. */ private int family() { ! return (int) SA_FAMILY_HANDLE.get(memoryAddress); } /** * Stores the given family in the sa_family field. */ private void putFamily(int family) { ! SA_FAMILY_HANDLE.set(memoryAddress, family); } /** * Return the value of the sin_port or sin6_port field. These fields are * stored in network order. */ private int port(int family) { ! if (family == AF_INET) ! return (int) SIN_PORT_HANDLE.get(memoryAddress); ! else ! return (int) SIN6_PORT_HANDLE.get(memoryAddress); } /** * Stores the given port number in the sin_port or sin6_port field. The * port is stored in network order. */ private void putPort(int family, int port) { ! if (family == AF_INET) ! SIN_PORT_HANDLE.set(memoryAddress, port); ! else ! SIN6_PORT_HANDLE.set(memoryAddress, port); } /** * Return an InetAddress to represent the value of the address in the * sin4_addr or sin6_addr fields. For IPv6 addresses, the Inet6Address is * created with the sin6_scope_id in the sockaddr_in6 structure. */ private InetAddress address(int family) { ! final MemoryAddress address = memoryAddress; int scope_id; + byte[] bytes; + if (family == AF_INET) { ! bytes = new byte[4]; ! for (int i = 0; i < 4; i++) ! bytes[i] = (byte) SIN_ADDR_HANDLE.get(address, i); scope_id = 0; } else { ! bytes = new byte[16]; ! for (int i = 0; i < 16; i++) ! bytes[i] = (byte) SIN6_ADDR_HANDLE.get(address, i); ! scope_id = (int) SIN6_SCOPE_HANDLE.get(address); } try { if (scope_id == 0) { return InetAddress.getByAddress(bytes); } else { return Inet6Address.getByAddress(null, bytes, scope_id);
*** 289,332 **** * Stores the given InetAddress in the sin_addr or sin6_addr/sin6_scope_id * fields. For IPv6 addresses, the sin6_addr will be popluated with an * IPv4-mapped IPv6 address when the given InetAddress is an IPv4 address. */ private void putAddress(int family, InetAddress ia) { if (family == AF_INET) { // IPv4 address ! putAddress(address + OFFSET_SIN4_ADDR, (Inet4Address) ia); } else { int scope_id; if (ia instanceof Inet4Address) { // IPv4-mapped IPv6 address ! UNSAFE.setMemory(address + OFFSET_SIN6_ADDR, 10, (byte) 0); ! UNSAFE.putByte(address + OFFSET_SIN6_ADDR + 10, (byte) 0xff); ! UNSAFE.putByte(address + OFFSET_SIN6_ADDR + 11, (byte) 0xff); ! putAddress(address + OFFSET_SIN6_ADDR + 12, (Inet4Address) ia); scope_id = 0; } else { // IPv6 address var inet6Address = (Inet6Address) ia; ! putAddress(address + OFFSET_SIN6_ADDR, inet6Address); scope_id = inet6Address.getScopeId(); } ! UNSAFE.putInt(address + OFFSET_SIN6_SCOPE_ID, scope_id); } } ! private static void putAddress(long address, Inet4Address ia) { int ipAddress = JNINA.addressValue(ia); ! // network order ! UNSAFE.putByte(address + 0, (byte) ((ipAddress >>> 24) & 0xFF)); ! UNSAFE.putByte(address + 1, (byte) ((ipAddress >>> 16) & 0xFF)); ! UNSAFE.putByte(address + 2, (byte) ((ipAddress >>> 8) & 0xFF)); ! UNSAFE.putByte(address + 3, (byte) (ipAddress & 0xFF)); } ! private static void putAddress(long address, Inet6Address ia) { byte[] bytes = JNINA.addressBytes(ia); ! UNSAFE.copyMemory(bytes, ARRAY_BASE_OFFSET, null, address, 16); } private static native int AFINET(); private static native int AFINET6(); private static native int sizeofSockAddr4(); --- 420,474 ---- * Stores the given InetAddress in the sin_addr or sin6_addr/sin6_scope_id * fields. For IPv6 addresses, the sin6_addr will be popluated with an * IPv4-mapped IPv6 address when the given InetAddress is an IPv4 address. */ private void putAddress(int family, InetAddress ia) { + final MemoryAddress address = memoryAddress; if (family == AF_INET) { // IPv4 address ! putIPv4Address(address, (Inet4Address)ia); } else { int scope_id; if (ia instanceof Inet4Address) { // IPv4-mapped IPv6 address ! putMappedAddress(address, (Inet4Address)ia); scope_id = 0; } else { // IPv6 address var inet6Address = (Inet6Address) ia; ! putIPv6Address(address, inet6Address); scope_id = inet6Address.getScopeId(); } ! SIN6_SCOPE_HANDLE.set(address, scope_id); } } ! private static void putIPv4Address(MemoryAddress address, Inet4Address ia) { int ipAddress = JNINA.addressValue(ia); ! SIN_ADDR_HANDLE.set(address, 0, (byte) ((ipAddress >>> 24) & 0xFF)); ! SIN_ADDR_HANDLE.set(address, 1, (byte) ((ipAddress >>> 16) & 0xFF)); ! SIN_ADDR_HANDLE.set(address, 2, (byte) ((ipAddress >>> 8) & 0xFF)); ! SIN_ADDR_HANDLE.set(address, 3, (byte) ((ipAddress >>> 0) & 0xFF)); ! } ! ! private static void putMappedAddress(MemoryAddress address, Inet4Address ia) { ! int ipAddress = JNINA.addressValue(ia); ! for (int i=0; i< 10; i++) ! SIN6_ADDR_HANDLE.set(address, i, (byte) 0x00); ! ! SIN6_ADDR_HANDLE.set(address, 10, (byte) 0xFF); ! SIN6_ADDR_HANDLE.set(address, 11, (byte) 0xFF); ! SIN6_ADDR_HANDLE.set(address, 12, (byte) ((ipAddress >>> 24) & 0xFF)); ! SIN6_ADDR_HANDLE.set(address, 13, (byte) ((ipAddress >>> 16) & 0xFF)); ! SIN6_ADDR_HANDLE.set(address, 14, (byte) ((ipAddress >>> 8) & 0xFF)); ! SIN6_ADDR_HANDLE.set(address, 15, (byte) ((ipAddress >>> 0) & 0xFF)); } ! private static void putIPv6Address(MemoryAddress address, Inet6Address ia) { byte[] bytes = JNINA.addressBytes(ia); ! for (int i = 0; i < 16; i++) ! SIN6_ADDR_HANDLE.set(address, i, bytes[i]); } private static native int AFINET(); private static native int AFINET6(); private static native int sizeofSockAddr4();
< prev index next >