1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.ch; 27 28 import java.net.Inet4Address; 29 import java.net.Inet6Address; 30 import java.net.InetAddress; 31 import java.net.InetSocketAddress; 32 import java.net.ProtocolFamily; 33 import java.net.SocketException; 34 import java.net.StandardProtocolFamily; 35 import java.net.UnknownHostException; 36 import java.nio.channels.UnsupportedAddressTypeException; 37 38 import jdk.internal.access.JavaNetInetAddressAccess; 39 import jdk.internal.access.SharedSecrets; 40 import jdk.internal.misc.Unsafe; 41 import jdk.internal.util.ArraysSupport; 42 43 /** 44 * A native socket address that is the union of struct sockaddr, struct sockaddr_in, 45 * and struct sockaddr_in6. 46 * 47 * This class is not thread safe. 48 */ 49 class NativeSocketAddress { 50 private static final JavaNetInetAddressAccess JNINA = SharedSecrets.getJavaNetInetAddressAccess(); 51 private static final Unsafe UNSAFE = Unsafe.getUnsafe(); 52 private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class); 53 54 private static final int AF_INET = AFINET(); 55 private static final int AF_INET6 = AFINET6(); 56 57 private static final int SIZEOF_SOCKADDR4 = sizeofSockAddr4(); 58 private static final int SIZEOF_SOCKADDR6 = sizeofSockAddr6(); 59 private static final int SIZEOF_SOCKETADDRESS = Math.max(SIZEOF_SOCKADDR4, SIZEOF_SOCKADDR6); 60 private static final int SIZEOF_FAMILY = sizeofFamily(); 61 private static final int OFFSET_FAMILY = offsetFamily(); 62 private static final int OFFSET_SIN4_PORT = offsetSin4Port(); 63 private static final int OFFSET_SIN4_ADDR = offsetSin4Addr(); 64 private static final int OFFSET_SIN6_PORT = offsetSin6Port(); 65 private static final int OFFSET_SIN6_ADDR = offsetSin6Addr(); 66 private static final int OFFSET_SIN6_SCOPE_ID = offsetSin6ScopeId(); 67 private static final int OFFSET_SIN6_FLOWINFO = offsetSin6FlowInfo(); 68 69 // SOCKETADDRESS 70 private final long address; 71 72 long address() { 73 return address; 74 } 75 76 NativeSocketAddress() { 77 long base = UNSAFE.allocateMemory(SIZEOF_SOCKETADDRESS); 78 UNSAFE.setMemory(base, SIZEOF_SOCKETADDRESS, (byte) 0); 79 this.address = base; 80 } 81 82 /** 83 * Allocate an array of native socket addresses. 84 */ 85 static NativeSocketAddress[] allocate(int count) { 86 NativeSocketAddress[] array = new NativeSocketAddress[count]; 87 for (int i = 0; i < count; i++) { 88 try { 89 array[i] = new NativeSocketAddress(); 90 } catch (OutOfMemoryError e) { 91 freeAll(array); 92 throw e; 93 } 94 } 95 return array; 96 } 97 98 /** 99 * Free all non-null native socket addresses in the given array. 100 */ 101 static void freeAll(NativeSocketAddress[] array) { 102 for (int i = 0; i < array.length; i++) { 103 NativeSocketAddress sa = array[i]; 104 if (sa != null) { 105 UNSAFE.freeMemory(sa.address); 106 } 107 } 108 } 109 110 /** 111 * Encodes the given InetSocketAddress into this socket address. 112 * @param protocolFamily protocol family 113 * @param isa the InetSocketAddress to encode 114 * @return the size of the socket address (sizeof sockaddr or sockaddr6) 115 * @throws UnsupportedAddressTypeException if the address type is not supported 116 */ 117 int encode(ProtocolFamily protocolFamily, InetSocketAddress isa) { 118 if (protocolFamily == StandardProtocolFamily.INET) { 119 // struct sockaddr 120 InetAddress ia = isa.getAddress(); 121 if (!(ia instanceof Inet4Address)) 122 throw new UnsupportedAddressTypeException(); 123 putFamily(AF_INET); 124 putAddress(AF_INET, ia); 125 putPort(AF_INET, isa.getPort()); 126 return SIZEOF_SOCKADDR4; 127 } else { 128 // struct sockaddr6 129 putFamily(AF_INET6); 130 putAddress(AF_INET6, isa.getAddress()); 131 putPort(AF_INET6, isa.getPort()); 132 UNSAFE.putInt(address + OFFSET_SIN6_FLOWINFO, 0); 133 return SIZEOF_SOCKADDR6; 134 } 135 } 136 137 /** 138 * Return an InetSocketAddress to represent the socket address in this buffer. 139 * @throws SocketException if the socket address is not AF_INET or AF_INET6 140 */ 141 InetSocketAddress decode() throws SocketException { 142 int family = family(); 143 if (family != AF_INET && family != AF_INET6) 144 throw new SocketException("Socket family not recognized"); 145 return new InetSocketAddress(address(family), port(family)); 146 } 147 148 /** 149 * Find a mismatch between this and another socket address 150 * @return the byte offset of the first mismatch or -1 if no mismatch 151 */ 152 private int mismatch(NativeSocketAddress other) { 153 int i = ArraysSupport.vectorizedMismatch(null, 154 this.address, 155 null, 156 other.address, 157 SIZEOF_SOCKETADDRESS, 158 ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE); 159 if (i >= 0) 160 return i; 161 i = SIZEOF_SOCKETADDRESS - ~i; 162 for (; i < SIZEOF_SOCKETADDRESS; i++) { 163 if (UNSAFE.getByte(this.address + i) != UNSAFE.getByte(other.address + i)) { 164 return i; 165 } 166 } 167 return -1; 168 } 169 170 @Override 171 public boolean equals(Object other) { 172 if (other instanceof NativeSocketAddress) { 173 return mismatch((NativeSocketAddress) other) < 0; 174 } else { 175 return false; 176 } 177 } 178 179 @Override 180 public int hashCode() { 181 int h = 0; 182 for (int offset = 0; offset < SIZEOF_SOCKETADDRESS; offset++) { 183 h = 31 * h + UNSAFE.getByte(address + offset); 184 } 185 return h; 186 } 187 188 @Override 189 public String toString() { 190 int family = family(); 191 if (family == AF_INET || family == AF_INET6) { 192 return ((family == AF_INET) ? "AF_INET" : "AF_INET6") 193 + ", address=" + address(family) + ", port=" + port(family); 194 } else { 195 return "<unknown>"; 196 } 197 } 198 199 /** 200 * Return the value of the sa_family field. 201 */ 202 private int family() { 203 if (SIZEOF_FAMILY == 1) { 204 return UNSAFE.getByte(address + OFFSET_FAMILY); 205 } else if (SIZEOF_FAMILY == 2) { 206 return UNSAFE.getShort(address + OFFSET_FAMILY); 207 } else { 208 throw new InternalError(); 209 } 210 } 211 212 /** 213 * Stores the given family in the sa_family field. 214 */ 215 private void putFamily(int family) { 216 if (SIZEOF_FAMILY == 1) { 217 UNSAFE.putByte(address + OFFSET_FAMILY, (byte) family); 218 } else if (SIZEOF_FAMILY == 2) { 219 UNSAFE.putShort(address + OFFSET_FAMILY, (short) family); 220 } else { 221 throw new InternalError(); 222 } 223 } 224 225 /** 226 * Return the value of the sin_port or sin6_port field. These fields are 227 * stored in network order. 228 */ 229 private int port(int family) { 230 byte b1, b2; 231 if (family == AF_INET) { 232 b1 = UNSAFE.getByte(address + OFFSET_SIN4_PORT); 233 b2 = UNSAFE.getByte(address + OFFSET_SIN4_PORT + 1); 234 } else { 235 b1 = UNSAFE.getByte(address + OFFSET_SIN6_PORT); 236 b2 = UNSAFE.getByte(address + OFFSET_SIN6_PORT + 1); 237 } 238 return (Byte.toUnsignedInt(b1) << 8) + Byte.toUnsignedInt(b2); 239 } 240 241 /** 242 * Stores the given port number in the sin_port or sin6_port field. The 243 * port is stored in network order. 244 */ 245 private void putPort(int family, int port) { 246 byte b1 = (byte) ((port >> 8) & 0xff); 247 byte b2 = (byte) ((port >> 0) & 0xff); 248 if (family == AF_INET) { 249 UNSAFE.putByte(address + OFFSET_SIN4_PORT, b1); 250 UNSAFE.putByte(address + OFFSET_SIN4_PORT + 1, b2); 251 } else { 252 UNSAFE.putByte(address + OFFSET_SIN6_PORT, b1); 253 UNSAFE.putByte(address + OFFSET_SIN6_PORT + 1, b2); 254 } 255 } 256 257 /** 258 * Return an InetAddress to represent the value of the address in the 259 * sin4_addr or sin6_addr fields. For IPv6 addresses, the Inet6Address is 260 * created with the sin6_scope_id in the sockaddr_in6 structure. 261 */ 262 private InetAddress address(int family) { 263 int len; 264 int offset; 265 int scope_id; 266 if (family == AF_INET) { 267 len = 4; 268 offset = OFFSET_SIN4_ADDR; 269 scope_id = 0; 270 } else { 271 len = 16; 272 offset = OFFSET_SIN6_ADDR; 273 scope_id = UNSAFE.getInt(address + OFFSET_SIN6_SCOPE_ID); 274 } 275 byte[] bytes = new byte[len]; 276 UNSAFE.copyMemory(null, address + offset, bytes, ARRAY_BASE_OFFSET, len); 277 try { 278 if (scope_id == 0) { 279 return InetAddress.getByAddress(bytes); 280 } else { 281 return Inet6Address.getByAddress(null, bytes, scope_id); 282 } 283 } catch (UnknownHostException e) { 284 throw new InternalError(e); 285 } 286 } 287 288 /** 289 * Stores the given InetAddress in the sin_addr or sin6_addr/sin6_scope_id 290 * fields. For IPv6 addresses, the sin6_addr will be popluated with an 291 * IPv4-mapped IPv6 address when the given InetAddress is an IPv4 address. 292 */ 293 private void putAddress(int family, InetAddress ia) { 294 if (family == AF_INET) { 295 // IPv4 address 296 putAddress(address + OFFSET_SIN4_ADDR, (Inet4Address) ia); 297 } else { 298 int scope_id; 299 if (ia instanceof Inet4Address) { 300 // IPv4-mapped IPv6 address 301 UNSAFE.setMemory(address + OFFSET_SIN6_ADDR, 10, (byte) 0); 302 UNSAFE.putByte(address + OFFSET_SIN6_ADDR + 10, (byte) 0xff); 303 UNSAFE.putByte(address + OFFSET_SIN6_ADDR + 11, (byte) 0xff); 304 putAddress(address + OFFSET_SIN6_ADDR + 12, (Inet4Address) ia); 305 scope_id = 0; 306 } else { 307 // IPv6 address 308 var inet6Address = (Inet6Address) ia; 309 putAddress(address + OFFSET_SIN6_ADDR, inet6Address); 310 scope_id = inet6Address.getScopeId(); 311 } 312 UNSAFE.putInt(address + OFFSET_SIN6_SCOPE_ID, scope_id); 313 } 314 } 315 316 private static void putAddress(long address, Inet4Address ia) { 317 int ipAddress = JNINA.addressValue(ia); 318 // network order 319 UNSAFE.putByte(address + 0, (byte) ((ipAddress >>> 24) & 0xFF)); 320 UNSAFE.putByte(address + 1, (byte) ((ipAddress >>> 16) & 0xFF)); 321 UNSAFE.putByte(address + 2, (byte) ((ipAddress >>> 8) & 0xFF)); 322 UNSAFE.putByte(address + 3, (byte) (ipAddress & 0xFF)); 323 } 324 325 private static void putAddress(long address, Inet6Address ia) { 326 byte[] bytes = JNINA.addressBytes(ia); 327 UNSAFE.copyMemory(bytes, ARRAY_BASE_OFFSET, null, address, 16); 328 } 329 330 private static native int AFINET(); 331 private static native int AFINET6(); 332 private static native int sizeofSockAddr4(); 333 private static native int sizeofSockAddr6(); 334 private static native int sizeofFamily(); 335 private static native int offsetFamily(); 336 private static native int offsetSin4Port(); 337 private static native int offsetSin4Addr(); 338 private static native int offsetSin6Port(); 339 private static native int offsetSin6Addr(); 340 private static native int offsetSin6ScopeId(); 341 private static native int offsetSin6FlowInfo(); 342 343 static { 344 IOUtil.load(); 345 } 346 }