< prev index next > src/java.base/share/classes/sun/nio/ch/NativeSocketAddress.java
Print this page
* questions.
*/
package sun.nio.ch;
+ 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.channels.UnsupportedAddressTypeException;
-
+ import jdk.incubator.foreign.MemoryAddress;
+ import jdk.incubator.foreign.MemoryHandles;
+ import jdk.incubator.foreign.MemoryLayouts;
+ import jdk.incubator.foreign.MemorySegment;
import jdk.internal.access.JavaNetInetAddressAccess;
import jdk.internal.access.SharedSecrets;
- import jdk.internal.misc.Unsafe;
- import jdk.internal.util.ArraysSupport;
+ import jdk.internal.sys.in6_h;
+ import jdk.internal.sys.in_h;
/**
* 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 {
+ final 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();
- private static final int SIZEOF_SOCKADDR6 = sizeofSockAddr6();
- private static final int SIZEOF_SOCKETADDRESS = Math.max(SIZEOF_SOCKADDR4, SIZEOF_SOCKADDR6);
- private static final int SIZEOF_FAMILY = sizeofFamily();
- private static final int OFFSET_FAMILY = offsetFamily();
- private static final int OFFSET_SIN4_PORT = offsetSin4Port();
- private static final int OFFSET_SIN4_ADDR = offsetSin4Addr();
- 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;
+ final long address() {
+ return address.toRawLongValue();
}
- NativeSocketAddress() {
- long base = UNSAFE.allocateMemory(SIZEOF_SOCKETADDRESS);
- UNSAFE.setMemory(base, SIZEOF_SOCKETADDRESS, (byte) 0);
- this.address = base;
+ private final MemorySegment segment;
+ private final MemoryAddress address;
+
+ private NativeSocketAddress() {
+ segment = allocateNative(in6_h.Csockaddr_in6.sizeof());
+ segment.fill((byte) 0x00);
+ address = segment.baseAddress();
}
/**
* Allocate an array of native socket addresses.
*/
- static NativeSocketAddress[] allocate(int count) {
+ static final NativeSocketAddress[] allocate(int count) {
NativeSocketAddress[] array = new NativeSocketAddress[count];
for (int i = 0; i < count; i++) {
try {
array[i] = new NativeSocketAddress();
} catch (OutOfMemoryError e) {
}
/**
* Free all non-null native socket addresses in the given array.
*/
- static void freeAll(NativeSocketAddress[] array) {
+ static final void freeAll(NativeSocketAddress[] array) {
for (int i = 0; i < array.length; i++) {
NativeSocketAddress sa = array[i];
if (sa != null) {
- UNSAFE.freeMemory(sa.address);
+ sa.segment.close();
}
}
}
+ private static final VarHandle sin_family = MemoryHandles.asUnsigned(in_h.Csockaddr_in.sin_family$VH(), int.class);
+ private static final VarHandle sin6_family = MemoryHandles.asUnsigned(in6_h.Csockaddr_in6.sin6_family$VH(), int.class);
+
/**
* Encodes the given InetSocketAddress into this socket address.
* @param protocolFamily protocol family
* @param isa the InetSocketAddress to encode
* @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) {
+ final 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;
+ sin_family.set(address, AF_INET);
+ in_h.Csockaddr_in.sin_port$set(address, (short) isa.getPort());
+ in_h.Cin_addr.s_addr$set(in_h.Csockaddr_in.sin_addr$addr(address),
+ JNINA.addressValue((Inet4Address) ia));
+ return (int) in_h.Csockaddr_in.sizeof();
} 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;
+ sin6_family.set(address, AF_INET6);
+ in6_h.Csockaddr_in6.sin6_port$set(address, (short) isa.getPort());
+ in6_h.Csockaddr_in6.sin6_flowinfo$set(address, 0);
+ setSin6Address(in6_h.Csockaddr_in6.sin6_addr$addr(address).segment(), isa.getAddress());
+ in6_h.Csockaddr_in6.sin6_scope_id$set(address, scopeidFromAddress(isa.getAddress()));
+ return (int) in6_h.Csockaddr_in6.sizeof();
}
}
/**
* Return an InetSocketAddress to represent the socket address in this buffer.
* @throws SocketException if the socket address is not AF_INET or AF_INET6
*/
- InetSocketAddress decode() throws SocketException {
- int family = family();
+ final InetSocketAddress decode() throws SocketException {
+ int family = (int) sin_family.get(address);
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 {
+ if (!(other instanceof NativeSocketAddress))
return false;
- }
+ NativeSocketAddress that = (NativeSocketAddress) other;
+ return this.segment.mismatch(that.segment) == -1;
}
+ private static final VarHandle BYTE_HANDLE = MemoryLayouts.JAVA_BYTE.varHandle(byte.class);
+
@Override
public int hashCode() {
int h = 0;
- for (int offset = 0; offset < SIZEOF_SOCKETADDRESS; offset++) {
- h = 31 * h + UNSAFE.getByte(address + offset);
+ final MemoryAddress addr = segment.baseAddress();
+ for (int i = 0 ; i < segment.byteSize() ; i++) {
+ h = 31 * h + (byte) BYTE_HANDLE.get(addr.addOffset(i));
}
return h;
}
@Override
public String toString() {
- int family = family();
+ int family = in_h.Csockaddr_in.sin_family$get(address);
if (family == AF_INET || family == AF_INET6) {
return ((family == AF_INET) ? "AF_INET" : "AF_INET6")
+ ", address=" + address(family) + ", port=" + port(family);
} else {
return "<unknown>";
}
}
- /**
- * 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();
- }
- }
+ private static final VarHandle sin_port = MemoryHandles.asUnsigned(in_h.Csockaddr_in.sin_port$VH(), int.class);
+ private static final VarHandle sin6_port = MemoryHandles.asUnsigned(in6_h.Csockaddr_in6.sin6_port$VH(), int.class);
/**
* 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);
+ private final int port(int family) {
if (family == AF_INET) {
- UNSAFE.putByte(address + OFFSET_SIN4_PORT, b1);
- UNSAFE.putByte(address + OFFSET_SIN4_PORT + 1, b2);
+ return (int) sin_port.get(address);
} else {
- UNSAFE.putByte(address + OFFSET_SIN6_PORT, b1);
- UNSAFE.putByte(address + OFFSET_SIN6_PORT + 1, b2);
+ return (int) sin6_port.get(address);
}
}
/**
* 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;
+ private final InetAddress address(int family) {
if (family == AF_INET) {
- len = 4;
- offset = OFFSET_SIN4_ADDR;
- scope_id = 0;
+ return JNINA.getByAddress(
+ in_h.Cin_addr.s_addr$get(in_h.Csockaddr_in.sin_addr$addr(address)));
} 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);
- }
- } catch (UnknownHostException e) {
- throw new InternalError(e);
+ return JNINA.getByAddress(
+ in6_h.Cin6_addr.__u6_addr$addr(in6_h.Csockaddr_in6.sin6_addr$addr(address)).segment().toByteArray(),
+ in6_h.Csockaddr_in6.sin6_scope_id$get(address)
+ );
}
}
- /**
- * 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);
+ private static final VarHandle ADDR_HANDLE = MemoryHandles.withOffset(MemoryLayouts.BITS_32_BE.varHandle(int.class), 12);
+ private static final void setSin6Address(MemorySegment seg, InetAddress ia) {
+ if (ia instanceof Inet4Address) { // IPv4-mapped IPv6 address
+ seg.fill((byte) 0x00).asSlice(10, 2).fill((byte) 0xFF);
+ ADDR_HANDLE.set(seg.baseAddress(), JNINA.addressValue((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);
+ seg.copyFrom(MemorySegment.ofArray(JNINA.addressBytes((Inet6Address) ia)));
}
}
- 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 final int scopeidFromAddress(InetAddress ia) {
+ if (ia instanceof Inet4Address)
+ return 0;
+ return ((Inet6Address) ia).getScopeId();
}
- private static void putAddress(long address, Inet6Address ia) {
- byte[] bytes = JNINA.addressBytes(ia);
- UNSAFE.copyMemory(bytes, ARRAY_BASE_OFFSET, null, address, 16);
+ private static final jdk.internal.misc.Unsafe UNSAFE = jdk.internal.misc.Unsafe.getUnsafe();
+ private static final MemorySegment allocateNative(long byteSize) {
+ long base = UNSAFE.allocateMemory(byteSize);
+ return jdk.internal.foreign.NativeMemorySegmentImpl.makeNativeSegmentUnchecked(
+ MemoryAddress.ofLong(base),
+ byteSize,
+ null,
+ () -> UNSAFE.freeMemory(base),
+ null);
}
private static native int AFINET();
private static native int AFINET6();
- private static native int sizeofSockAddr4();
- private static native int sizeofSockAddr6();
- private static native int sizeofFamily();
- private static native int offsetFamily();
- private static native int offsetSin4Port();
- private static native int offsetSin4Addr();
- private static native int offsetSin6Port();
- private static native int offsetSin6Addr();
- private static native int offsetSin6ScopeId();
- private static native int offsetSin6FlowInfo();
static {
IOUtil.load();
}
}
< prev index next >