Path: blob/master/src/java.base/share/classes/sun/nio/ch/NativeSocketAddress.java
41159 views
/*1* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.ch;2627import java.net.Inet4Address;28import java.net.Inet6Address;29import java.net.InetAddress;30import java.net.InetSocketAddress;31import java.net.ProtocolFamily;32import java.net.SocketException;33import java.net.StandardProtocolFamily;34import java.net.UnknownHostException;35import java.nio.channels.UnsupportedAddressTypeException;3637import jdk.internal.access.JavaNetInetAddressAccess;38import jdk.internal.access.SharedSecrets;39import jdk.internal.misc.Unsafe;40import jdk.internal.util.ArraysSupport;4142/**43* A native socket address that is the union of struct sockaddr, struct sockaddr_in,44* and struct sockaddr_in6.45*46* This class is not thread safe.47*/48class NativeSocketAddress {49private static final JavaNetInetAddressAccess JNINA = SharedSecrets.getJavaNetInetAddressAccess();50private static final Unsafe UNSAFE = Unsafe.getUnsafe();51private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);5253private static final int AF_INET = AFINET();54private static final int AF_INET6 = AFINET6();5556private static final int SIZEOF_SOCKADDR4 = sizeofSockAddr4();57private static final int SIZEOF_SOCKADDR6 = sizeofSockAddr6();58private static final int SIZEOF_SOCKETADDRESS = Math.max(SIZEOF_SOCKADDR4, SIZEOF_SOCKADDR6);59private static final int SIZEOF_FAMILY = sizeofFamily();60private static final int OFFSET_FAMILY = offsetFamily();61private static final int OFFSET_SIN4_PORT = offsetSin4Port();62private static final int OFFSET_SIN4_ADDR = offsetSin4Addr();63private static final int OFFSET_SIN6_PORT = offsetSin6Port();64private static final int OFFSET_SIN6_ADDR = offsetSin6Addr();65private static final int OFFSET_SIN6_SCOPE_ID = offsetSin6ScopeId();66private static final int OFFSET_SIN6_FLOWINFO = offsetSin6FlowInfo();6768// SOCKETADDRESS69private final long address;7071long address() {72return address;73}7475NativeSocketAddress() {76long base = UNSAFE.allocateMemory(SIZEOF_SOCKETADDRESS);77UNSAFE.setMemory(base, SIZEOF_SOCKETADDRESS, (byte) 0);78this.address = base;79}8081/**82* Allocate an array of native socket addresses.83*/84static NativeSocketAddress[] allocate(int count) {85NativeSocketAddress[] array = new NativeSocketAddress[count];86for (int i = 0; i < count; i++) {87try {88array[i] = new NativeSocketAddress();89} catch (OutOfMemoryError e) {90freeAll(array);91throw e;92}93}94return array;95}9697/**98* Free all non-null native socket addresses in the given array.99*/100static void freeAll(NativeSocketAddress[] array) {101for (int i = 0; i < array.length; i++) {102NativeSocketAddress sa = array[i];103if (sa != null) {104UNSAFE.freeMemory(sa.address);105}106}107}108109/**110* Encodes the given InetSocketAddress into this socket address.111* @param protocolFamily protocol family112* @param isa the InetSocketAddress to encode113* @return the size of the socket address (sizeof sockaddr or sockaddr6)114* @throws UnsupportedAddressTypeException if the address type is not supported115*/116int encode(ProtocolFamily protocolFamily, InetSocketAddress isa) {117if (protocolFamily == StandardProtocolFamily.INET) {118// struct sockaddr119InetAddress ia = isa.getAddress();120if (!(ia instanceof Inet4Address))121throw new UnsupportedAddressTypeException();122putFamily(AF_INET);123putAddress(AF_INET, ia);124putPort(AF_INET, isa.getPort());125return SIZEOF_SOCKADDR4;126} else {127// struct sockaddr6128putFamily(AF_INET6);129putAddress(AF_INET6, isa.getAddress());130putPort(AF_INET6, isa.getPort());131UNSAFE.putInt(address + OFFSET_SIN6_FLOWINFO, 0);132return SIZEOF_SOCKADDR6;133}134}135136/**137* Return an InetSocketAddress to represent the socket address in this buffer.138* @throws SocketException if the socket address is not AF_INET or AF_INET6139*/140InetSocketAddress decode() throws SocketException {141int family = family();142if (family != AF_INET && family != AF_INET6)143throw new SocketException("Socket family not recognized");144return new InetSocketAddress(address(family), port(family));145}146147/**148* Find a mismatch between this and another socket address149* @return the byte offset of the first mismatch or -1 if no mismatch150*/151private int mismatch(NativeSocketAddress other) {152int i = ArraysSupport.vectorizedMismatch(null,153this.address,154null,155other.address,156SIZEOF_SOCKETADDRESS,157ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE);158if (i >= 0)159return i;160i = SIZEOF_SOCKETADDRESS - ~i;161for (; i < SIZEOF_SOCKETADDRESS; i++) {162if (UNSAFE.getByte(this.address + i) != UNSAFE.getByte(other.address + i)) {163return i;164}165}166return -1;167}168169@Override170public boolean equals(Object other) {171if (other instanceof NativeSocketAddress) {172return mismatch((NativeSocketAddress) other) < 0;173} else {174return false;175}176}177178@Override179public int hashCode() {180int h = 0;181for (int offset = 0; offset < SIZEOF_SOCKETADDRESS; offset++) {182h = 31 * h + UNSAFE.getByte(address + offset);183}184return h;185}186187@Override188public String toString() {189int family = family();190if (family == AF_INET || family == AF_INET6) {191return ((family == AF_INET) ? "AF_INET" : "AF_INET6")192+ ", address=" + address(family) + ", port=" + port(family);193} else {194return "<unknown>";195}196}197198/**199* Return the value of the sa_family field.200*/201private int family() {202if (SIZEOF_FAMILY == 1) {203return UNSAFE.getByte(address + OFFSET_FAMILY);204} else if (SIZEOF_FAMILY == 2) {205return UNSAFE.getShort(address + OFFSET_FAMILY);206} else {207throw new InternalError();208}209}210211/**212* Stores the given family in the sa_family field.213*/214private void putFamily(int family) {215if (SIZEOF_FAMILY == 1) {216UNSAFE.putByte(address + OFFSET_FAMILY, (byte) family);217} else if (SIZEOF_FAMILY == 2) {218UNSAFE.putShort(address + OFFSET_FAMILY, (short) family);219} else {220throw new InternalError();221}222}223224/**225* Return the value of the sin_port or sin6_port field. These fields are226* stored in network order.227*/228private int port(int family) {229byte b1, b2;230if (family == AF_INET) {231b1 = UNSAFE.getByte(address + OFFSET_SIN4_PORT);232b2 = UNSAFE.getByte(address + OFFSET_SIN4_PORT + 1);233} else {234b1 = UNSAFE.getByte(address + OFFSET_SIN6_PORT);235b2 = UNSAFE.getByte(address + OFFSET_SIN6_PORT + 1);236}237return (Byte.toUnsignedInt(b1) << 8) + Byte.toUnsignedInt(b2);238}239240/**241* Stores the given port number in the sin_port or sin6_port field. The242* port is stored in network order.243*/244private void putPort(int family, int port) {245byte b1 = (byte) ((port >> 8) & 0xff);246byte b2 = (byte) ((port >> 0) & 0xff);247if (family == AF_INET) {248UNSAFE.putByte(address + OFFSET_SIN4_PORT, b1);249UNSAFE.putByte(address + OFFSET_SIN4_PORT + 1, b2);250} else {251UNSAFE.putByte(address + OFFSET_SIN6_PORT, b1);252UNSAFE.putByte(address + OFFSET_SIN6_PORT + 1, b2);253}254}255256/**257* Return an InetAddress to represent the value of the address in the258* sin4_addr or sin6_addr fields. For IPv6 addresses, the Inet6Address is259* created with the sin6_scope_id in the sockaddr_in6 structure.260*/261private InetAddress address(int family) {262int len;263int offset;264int scope_id;265if (family == AF_INET) {266len = 4;267offset = OFFSET_SIN4_ADDR;268scope_id = 0;269} else {270len = 16;271offset = OFFSET_SIN6_ADDR;272scope_id = UNSAFE.getInt(address + OFFSET_SIN6_SCOPE_ID);273}274byte[] bytes = new byte[len];275UNSAFE.copyMemory(null, address + offset, bytes, ARRAY_BASE_OFFSET, len);276try {277if (scope_id == 0) {278return InetAddress.getByAddress(bytes);279} else {280return Inet6Address.getByAddress(null, bytes, scope_id);281}282} catch (UnknownHostException e) {283throw new InternalError(e);284}285}286287/**288* Stores the given InetAddress in the sin_addr or sin6_addr/sin6_scope_id289* fields. For IPv6 addresses, the sin6_addr will be popluated with an290* IPv4-mapped IPv6 address when the given InetAddress is an IPv4 address.291*/292private void putAddress(int family, InetAddress ia) {293if (family == AF_INET) {294// IPv4 address295putAddress(address + OFFSET_SIN4_ADDR, (Inet4Address) ia);296} else {297int scope_id;298if (ia instanceof Inet4Address) {299// IPv4-mapped IPv6 address300UNSAFE.setMemory(address + OFFSET_SIN6_ADDR, 10, (byte) 0);301UNSAFE.putByte(address + OFFSET_SIN6_ADDR + 10, (byte) 0xff);302UNSAFE.putByte(address + OFFSET_SIN6_ADDR + 11, (byte) 0xff);303putAddress(address + OFFSET_SIN6_ADDR + 12, (Inet4Address) ia);304scope_id = 0;305} else {306// IPv6 address307var inet6Address = (Inet6Address) ia;308putAddress(address + OFFSET_SIN6_ADDR, inet6Address);309scope_id = inet6Address.getScopeId();310}311UNSAFE.putInt(address + OFFSET_SIN6_SCOPE_ID, scope_id);312}313}314315private static void putAddress(long address, Inet4Address ia) {316int ipAddress = JNINA.addressValue(ia);317// network order318UNSAFE.putByte(address + 0, (byte) ((ipAddress >>> 24) & 0xFF));319UNSAFE.putByte(address + 1, (byte) ((ipAddress >>> 16) & 0xFF));320UNSAFE.putByte(address + 2, (byte) ((ipAddress >>> 8) & 0xFF));321UNSAFE.putByte(address + 3, (byte) (ipAddress & 0xFF));322}323324private static void putAddress(long address, Inet6Address ia) {325byte[] bytes = JNINA.addressBytes(ia);326UNSAFE.copyMemory(bytes, ARRAY_BASE_OFFSET, null, address, 16);327}328329private static native int AFINET();330private static native int AFINET6();331private static native int sizeofSockAddr4();332private static native int sizeofSockAddr6();333private static native int sizeofFamily();334private static native int offsetFamily();335private static native int offsetSin4Port();336private static native int offsetSin4Addr();337private static native int offsetSin6Port();338private static native int offsetSin6Addr();339private static native int offsetSin6ScopeId();340private static native int offsetSin6FlowInfo();341342static {343IOUtil.load();344}345}346347348