Showing the changes to java/pkg/sun/nio/ch/Net.java (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,515 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2000, 2011, 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.io.*; | ||
| 29 | import java.net.*; | ||
| 30 | import java.nio.channels.*; | ||
| 31 | import java.util.*; | ||
| 32 | import java.security.AccessController; | ||
| 33 | import java.security.PrivilegedAction; | ||
| 34 | |||
| 35 | |||
| 36 | class Net { // package-private | ||
| 37 | |||
| 38 | private Net() { } | ||
| 39 | |||
| 40 | // unspecified protocol family | ||
| 41 | static final ProtocolFamily UNSPEC = new ProtocolFamily() { | ||
| 42 | public String name() { | ||
| 43 | return "UNSPEC"; | ||
| 44 | } | ||
| 45 | }; | ||
| 46 | |||
| 47 | // -- Miscellaneous utilities -- | ||
| 48 | |||
| 49 | private static volatile boolean checkedIPv6 = false; | ||
| 50 | private static volatile boolean isIPv6Available; | ||
| 51 | |||
| 52 | /** | ||
| 53 | * Tells whether dual-IPv4/IPv6 sockets should be used. | ||
| 54 | */ | ||
| 55 | static boolean isIPv6Available() { | ||
| 56 | if (!checkedIPv6) { | ||
| 57 | isIPv6Available = isIPv6Available0(); | ||
| 58 | checkedIPv6 = true; | ||
| 59 | } | ||
| 60 | return isIPv6Available; | ||
| 61 | } | ||
| 62 | |||
| 63 | /** | ||
| 64 | * Tells whether IPv6 sockets can join IPv4 multicast groups | ||
| 65 | */ | ||
| 66 | static boolean canIPv6SocketJoinIPv4Group() { | ||
| 67 | return canIPv6SocketJoinIPv4Group0(); | ||
| 68 | } | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Tells whether {@link #join6} can be used to join an IPv4 | ||
| 72 | * multicast group (IPv4 group as IPv4-mapped IPv6 address) | ||
| 73 | */ | ||
| 74 | static boolean canJoin6WithIPv4Group() { | ||
| 75 | return canJoin6WithIPv4Group0(); | ||
| 76 | } | ||
| 77 | |||
| 78 | static InetSocketAddress checkAddress(SocketAddress sa) { | ||
| 79 | if (sa == null) | ||
| 80 | throw new NullPointerException(); | ||
| 81 | if (!(sa instanceof InetSocketAddress)) | ||
| 82 | throw new UnsupportedAddressTypeException(); // ## needs arg | ||
| 83 | InetSocketAddress isa = (InetSocketAddress)sa; | ||
| 84 | if (isa.isUnresolved()) | ||
| 85 | throw new UnresolvedAddressException(); // ## needs arg | ||
| 86 | InetAddress addr = isa.getAddress(); | ||
| 87 | if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) | ||
| 88 | throw new IllegalArgumentException("Invalid address type"); | ||
| 89 | return isa; | ||
| 90 | } | ||
| 91 | |||
| 92 | static InetSocketAddress asInetSocketAddress(SocketAddress sa) { | ||
| 93 | if (!(sa instanceof InetSocketAddress)) | ||
| 94 | throw new UnsupportedAddressTypeException(); | ||
| 95 | return (InetSocketAddress)sa; | ||
| 96 | } | ||
| 97 | |||
| 98 | static void translateToSocketException(Exception x) | ||
| 99 | throws SocketException | ||
| 100 | { | ||
| 101 | if (x instanceof SocketException) | ||
| 102 | throw (SocketException)x; | ||
| 103 | Exception nx = x; | ||
| 104 | if (x instanceof ClosedChannelException) | ||
| 105 | nx = new SocketException("Socket is closed"); | ||
| 106 | else if (x instanceof NotYetConnectedException) | ||
| 107 | nx = new SocketException("Socket is not connected"); | ||
| 108 | else if (x instanceof AlreadyBoundException) | ||
| 109 | nx = new SocketException("Already bound"); | ||
| 110 | else if (x instanceof NotYetBoundException) | ||
| 111 | nx = new SocketException("Socket is not bound yet"); | ||
| 112 | else if (x instanceof UnsupportedAddressTypeException) | ||
| 113 | nx = new SocketException("Unsupported address type"); | ||
| 114 | else if (x instanceof UnresolvedAddressException) { | ||
| 115 | nx = new SocketException("Unresolved address"); | ||
| 116 | } | ||
| 117 | if (nx != x) | ||
| 118 | nx.initCause(x); | ||
| 119 | |||
| 120 | if (nx instanceof SocketException) | ||
| 121 | throw (SocketException)nx; | ||
| 122 | else if (nx instanceof RuntimeException) | ||
| 123 | throw (RuntimeException)nx; | ||
| 124 | else | ||
| 125 | throw new Error("Untranslated exception", nx); | ||
| 126 | } | ||
| 127 | |||
| 128 | static void translateException(Exception x, | ||
| 129 | boolean unknownHostForUnresolved) | ||
| 130 | throws IOException | ||
| 131 | { | ||
| 132 | if (x instanceof IOException) | ||
| 133 | throw (IOException)x; | ||
| 134 | // Throw UnknownHostException from here since it cannot | ||
| 135 | // be thrown as a SocketException | ||
| 136 | if (unknownHostForUnresolved && | ||
| 137 | (x instanceof UnresolvedAddressException)) | ||
| 138 | { | ||
| 139 | throw new UnknownHostException(); | ||
| 140 | } | ||
| 141 | translateToSocketException(x); | ||
| 142 | } | ||
| 143 | |||
| 144 | static void translateException(Exception x) | ||
| 145 | throws IOException | ||
| 146 | { | ||
| 147 | translateException(x, false); | ||
| 148 | } | ||
| 149 | |||
| 150 | /** | ||
| 151 | * Returns any IPv4 address of the given network interface, or | ||
| 152 | * null if the interface does not have any IPv4 addresses. | ||
| 153 | */ | ||
| 154 | static Inet4Address anyInet4Address(final NetworkInterface interf) { | ||
| 155 | return AccessController.doPrivileged(new PrivilegedAction<Inet4Address>() { | ||
| 156 | public Inet4Address run() { | ||
| 157 | Enumeration<InetAddress> addrs = interf.getInetAddresses(); | ||
| 158 | while (addrs.hasMoreElements()) { | ||
| 159 | InetAddress addr = addrs.nextElement(); | ||
| 160 | if (addr instanceof Inet4Address) { | ||
| 161 | return (Inet4Address)addr; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | return null; | ||
| 165 | } | ||
| 166 | }); | ||
| 167 | } | ||
| 168 | |||
| 169 | /** | ||
| 170 | * Returns an IPv4 address as an int. | ||
| 171 | */ | ||
| 172 | static int inet4AsInt(InetAddress ia) { | ||
| 173 | if (ia instanceof Inet4Address) { | ||
| 174 | byte[] addr = ia.getAddress(); | ||
| 175 | int address = addr[3] & 0xFF; | ||
| 176 | address |= ((addr[2] << 8) & 0xFF00); | ||
| 177 | address |= ((addr[1] << 16) & 0xFF0000); | ||
| 178 | address |= ((addr[0] << 24) & 0xFF000000); | ||
| 179 | return address; | ||
| 180 | } | ||
| 181 | throw new AssertionError("Should not reach here"); | ||
| 182 | } | ||
| 183 | |||
| 184 | /** | ||
| 185 | * Returns an InetAddress from the given IPv4 address | ||
| 186 | * represented as an int. | ||
| 187 | */ | ||
| 188 | static InetAddress inet4FromInt(int address) { | ||
| 189 | byte[] addr = new byte[4]; | ||
| 190 | addr[0] = (byte) ((address >>> 24) & 0xFF); | ||
| 191 | addr[1] = (byte) ((address >>> 16) & 0xFF); | ||
| 192 | addr[2] = (byte) ((address >>> 8) & 0xFF); | ||
| 193 | addr[3] = (byte) (address & 0xFF); | ||
| 194 | try { | ||
| 195 | return InetAddress.getByAddress(addr); | ||
| 196 | } catch (UnknownHostException uhe) { | ||
| 197 | throw new AssertionError("Should not reach here"); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | /** | ||
| 202 | * Returns an IPv6 address as a byte array | ||
| 203 | */ | ||
| 204 | static byte[] inet6AsByteArray(InetAddress ia) { | ||
| 205 | if (ia instanceof Inet6Address) { | ||
| 206 | return ia.getAddress(); | ||
| 207 | } | ||
| 208 | |||
| 209 | // need to construct IPv4-mapped address | ||
| 210 | if (ia instanceof Inet4Address) { | ||
| 211 | byte[] ip4address = ia.getAddress(); | ||
| 212 | byte[] address = new byte[16]; | ||
| 213 | address[10] = (byte)0xff; | ||
| 214 | address[11] = (byte)0xff; | ||
| 215 | address[12] = ip4address[0]; | ||
| 216 | address[13] = ip4address[1]; | ||
| 217 | address[14] = ip4address[2]; | ||
| 218 | address[15] = ip4address[3]; | ||
| 219 | return address; | ||
| 220 | } | ||
| 221 | |||
| 222 | throw new AssertionError("Should not reach here"); | ||
| 223 | } | ||
| 224 | |||
| 225 | // -- Socket options | ||
| 226 | |||
| 227 | static void setSocketOption(FileDescriptor fd, ProtocolFamily family, | ||
| 228 | SocketOption<?> name, Object value) | ||
| 229 | throws IOException | ||
| 230 | { | ||
| 231 | if (value == null) | ||
| 232 | throw new IllegalArgumentException("Invalid option value"); | ||
| 233 | |||
| 234 | // only simple values supported by this method | ||
| 235 | Class<?> type = name.type(); | ||
| 236 | if (type != Integer.class && type != Boolean.class) | ||
| 237 | throw new AssertionError("Should not reach here"); | ||
| 238 | |||
| 239 | // special handling | ||
| 240 | if (name == StandardSocketOptions.SO_RCVBUF || | ||
| 241 | name == StandardSocketOptions.SO_SNDBUF) | ||
| 242 | { | ||
| 243 | int i = ((Integer)value).intValue(); | ||
| 244 | if (i < 0) | ||
| 245 | throw new IllegalArgumentException("Invalid send/receive buffer size"); | ||
| 246 | } | ||
| 247 | if (name == StandardSocketOptions.SO_LINGER) { | ||
| 248 | int i = ((Integer)value).intValue(); | ||
| 249 | if (i < 0) | ||
| 250 | value = Integer.valueOf(-1); | ||
| 251 | if (i > 65535) | ||
| 252 | value = Integer.valueOf(65535); | ||
| 253 | } | ||
| 254 | if (name == StandardSocketOptions.IP_TOS) { | ||
| 255 | int i = ((Integer)value).intValue(); | ||
| 256 | if (i < 0 || i > 255) | ||
| 257 | throw new IllegalArgumentException("Invalid IP_TOS value"); | ||
| 258 | } | ||
| 259 | if (name == StandardSocketOptions.IP_MULTICAST_TTL) { | ||
| 260 | int i = ((Integer)value).intValue(); | ||
| 261 | if (i < 0 || i > 255) | ||
| 262 | throw new IllegalArgumentException("Invalid TTL/hop value"); | ||
| 263 | } | ||
| 264 | |||
| 265 | // map option name to platform level/name | ||
| 266 | OptionKey key = SocketOptionRegistry.findOption(name, family); | ||
| 267 | if (key == null) | ||
| 268 | throw new AssertionError("Option not found"); | ||
| 269 | |||
| 270 | int arg; | ||
| 271 | if (type == Integer.class) { | ||
| 272 | arg = ((Integer)value).intValue(); | ||
| 273 | } else { | ||
| 274 | boolean b = ((Boolean)value).booleanValue(); | ||
| 275 | arg = (b) ? 1 : 0; | ||
| 276 | } | ||
| 277 | |||
| 278 | boolean mayNeedConversion = (family == UNSPEC); | ||
| 279 | setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg); | ||
| 280 | } | ||
| 281 | |||
| 282 | static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, | ||
| 283 | SocketOption<?> name) | ||
| 284 | throws IOException | ||
| 285 | { | ||
| 286 | Class<?> type = name.type(); | ||
| 287 | |||
| 288 | // only simple values supported by this method | ||
| 289 | if (type != Integer.class && type != Boolean.class) | ||
| 290 | throw new AssertionError("Should not reach here"); | ||
| 291 | |||
| 292 | // map option name to platform level/name | ||
| 293 | OptionKey key = SocketOptionRegistry.findOption(name, family); | ||
| 294 | if (key == null) | ||
| 295 | throw new AssertionError("Option not found"); | ||
| 296 | |||
| 297 | boolean mayNeedConversion = (family == UNSPEC); | ||
| 298 | int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name()); | ||
| 299 | |||
| 300 | if (type == Integer.class) { | ||
| 301 | return Integer.valueOf(value); | ||
| 302 | } else { | ||
| 303 | return (value == 0) ? Boolean.FALSE : Boolean.TRUE; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | // -- Socket operations -- | ||
| 308 | |||
| 309 | private static native boolean isIPv6Available0(); | ||
| 310 | |||
| 311 | private static native boolean canIPv6SocketJoinIPv4Group0(); | ||
| 312 | |||
| 313 | private static native boolean canJoin6WithIPv4Group0(); | ||
| 314 | |||
| 315 | static FileDescriptor socket(boolean stream) throws IOException { | ||
| 316 | return socket(UNSPEC, stream); | ||
| 317 | } | ||
| 318 | |||
| 319 | static FileDescriptor socket(ProtocolFamily family, boolean stream) | ||
| 320 | throws IOException { | ||
| 321 | boolean preferIPv6 = isIPv6Available() && | ||
| 322 | (family != StandardProtocolFamily.INET); | ||
| 323 | return IOUtil.newFD(socket0(preferIPv6, stream, false)); | ||
| 324 | } | ||
| 325 | |||
| 326 | static FileDescriptor serverSocket(boolean stream) { | ||
| 327 | return IOUtil.newFD(socket0(isIPv6Available(), stream, true)); | ||
| 328 | } | ||
| 329 | |||
| 330 | // Due to oddities SO_REUSEADDR on windows reuse is ignored | ||
| 331 | private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse); | ||
| 332 | |||
| 333 | static void bind(FileDescriptor fd, InetAddress addr, int port) | ||
| 334 | throws IOException | ||
| 335 | { | ||
| 336 | bind(UNSPEC, fd, addr, port); | ||
| 337 | } | ||
| 338 | |||
| 339 | static void bind(ProtocolFamily family, FileDescriptor fd, | ||
| 340 | InetAddress addr, int port) throws IOException | ||
| 341 | { | ||
| 342 | boolean preferIPv6 = isIPv6Available() && | ||
| 343 | (family != StandardProtocolFamily.INET); | ||
| 344 | bind0(preferIPv6, fd, addr, port); | ||
| 345 | } | ||
| 346 | |||
| 347 | private static native void bind0(boolean preferIPv6, FileDescriptor fd, | ||
| 348 | InetAddress addr, int port) | ||
| 349 | throws IOException; | ||
| 350 | |||
| 351 | static native void listen(FileDescriptor fd, int backlog) throws IOException; | ||
| 352 | |||
| 353 | static int connect(FileDescriptor fd, InetAddress remote, int remotePort) | ||
| 354 | throws IOException | ||
| 355 | { | ||
| 356 | return connect(UNSPEC, fd, remote, remotePort); | ||
| 357 | } | ||
| 358 | |||
| 359 | static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort) | ||
| 360 | throws IOException | ||
| 361 | { | ||
| 362 | boolean preferIPv6 = isIPv6Available() && | ||
| 363 | (family != StandardProtocolFamily.INET); | ||
| 364 | return connect0(preferIPv6, fd, remote, remotePort); | ||
| 365 | } | ||
| 366 | |||
| 367 | private static native int connect0(boolean preferIPv6, | ||
| 368 | FileDescriptor fd, | ||
| 369 | InetAddress remote, | ||
| 370 | int remotePort) | ||
| 371 | throws IOException; | ||
| 372 | |||
| 373 | |||
| 374 | public final static int SHUT_RD = 0; | ||
| 375 | public final static int SHUT_WR = 1; | ||
| 376 | public final static int SHUT_RDWR = 2; | ||
| 377 | |||
| 378 | static native void shutdown(FileDescriptor fd, int how) throws IOException; | ||
| 379 | |||
| 380 | private static native int localPort(FileDescriptor fd) | ||
| 381 | throws IOException; | ||
| 382 | |||
| 383 | private static native InetAddress localInetAddress(FileDescriptor fd) | ||
| 384 | throws IOException; | ||
| 385 | |||
| 386 | static InetSocketAddress localAddress(FileDescriptor fd) | ||
| 387 | throws IOException | ||
| 388 | { | ||
| 389 | return new InetSocketAddress(localInetAddress(fd), localPort(fd)); | ||
| 390 | } | ||
| 391 | |||
| 392 | private static native int remotePort(FileDescriptor fd) | ||
| 393 | throws IOException; | ||
| 394 | |||
| 395 | private static native InetAddress remoteInetAddress(FileDescriptor fd) | ||
| 396 | throws IOException; | ||
| 397 | |||
| 398 | static InetSocketAddress remoteAddress(FileDescriptor fd) | ||
| 399 | throws IOException | ||
| 400 | { | ||
| 401 | return new InetSocketAddress(remoteInetAddress(fd), remotePort(fd)); | ||
| 402 | } | ||
| 403 | |||
| 404 | private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion, | ||
| 405 | int level, int opt) | ||
| 406 | throws IOException; | ||
| 407 | |||
| 408 | private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion, | ||
| 409 | int level, int opt, int arg) | ||
| 410 | throws IOException; | ||
| 411 | |||
| 412 | // -- Multicast support -- | ||
| 413 | |||
| 414 | |||
| 415 | /** | ||
| 416 | * Join IPv4 multicast group | ||
| 417 | */ | ||
| 418 | static int join4(FileDescriptor fd, int group, int interf, int source) | ||
| 419 | throws IOException | ||
| 420 | { | ||
| 421 | return joinOrDrop4(true, fd, group, interf, source); | ||
| 422 | } | ||
| 423 | |||
| 424 | /** | ||
| 425 | * Drop membership of IPv4 multicast group | ||
| 426 | */ | ||
| 427 | static void drop4(FileDescriptor fd, int group, int interf, int source) | ||
| 428 | throws IOException | ||
| 429 | { | ||
| 430 | joinOrDrop4(false, fd, group, interf, source); | ||
| 431 | } | ||
| 432 | |||
| 433 | private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source) | ||
| 434 | throws IOException; | ||
| 435 | |||
| 436 | /** | ||
| 437 | * Block IPv4 source | ||
| 438 | */ | ||
| 439 | static int block4(FileDescriptor fd, int group, int interf, int source) | ||
| 440 | throws IOException | ||
| 441 | { | ||
| 442 | return blockOrUnblock4(true, fd, group, interf, source); | ||
| 443 | } | ||
| 444 | |||
| 445 | /** | ||
| 446 | * Unblock IPv6 source | ||
| 447 | */ | ||
| 448 | static void unblock4(FileDescriptor fd, int group, int interf, int source) | ||
| 449 | throws IOException | ||
| 450 | { | ||
| 451 | blockOrUnblock4(false, fd, group, interf, source); | ||
| 452 | } | ||
| 453 | |||
| 454 | private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group, | ||
| 455 | int interf, int source) | ||
| 456 | throws IOException; | ||
| 457 | |||
| 458 | /** | ||
| 459 | * Join IPv6 multicast group | ||
| 460 | */ | ||
| 461 | static int join6(FileDescriptor fd, byte[] group, int index, byte[] source) | ||
| 462 | throws IOException | ||
| 463 | { | ||
| 464 | return joinOrDrop6(true, fd, group, index, source); | ||
| 465 | } | ||
| 466 | |||
| 467 | /** | ||
| 468 | * Drop membership of IPv6 multicast group | ||
| 469 | */ | ||
| 470 | static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source) | ||
| 471 | throws IOException | ||
| 472 | { | ||
| 473 | joinOrDrop6(false, fd, group, index, source); | ||
| 474 | } | ||
| 475 | |||
| 476 | private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source) | ||
| 477 | throws IOException; | ||
| 478 | |||
| 479 | /** | ||
| 480 | * Block IPv6 source | ||
| 481 | */ | ||
| 482 | static int block6(FileDescriptor fd, byte[] group, int index, byte[] source) | ||
| 483 | throws IOException | ||
| 484 | { | ||
| 485 | return blockOrUnblock6(true, fd, group, index, source); | ||
| 486 | } | ||
| 487 | |||
| 488 | /** | ||
| 489 | * Unblock IPv6 source | ||
| 490 | */ | ||
| 491 | static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source) | ||
| 492 | throws IOException | ||
| 493 | { | ||
| 494 | blockOrUnblock6(false, fd, group, index, source); | ||
| 495 | } | ||
| 496 | |||
| 497 | static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source) | ||
| 498 | throws IOException; | ||
| 499 | |||
| 500 | static native void setInterface4(FileDescriptor fd, int interf) throws IOException; | ||
| 501 | |||
| 502 | static native int getInterface4(FileDescriptor fd) throws IOException; | ||
| 503 | |||
| 504 | static native void setInterface6(FileDescriptor fd, int index) throws IOException; | ||
| 505 | |||
| 506 | static native int getInterface6(FileDescriptor fd) throws IOException; | ||
| 507 | |||
| 508 | private static native void initIDs(); | ||
| 509 | |||
| 510 | static { | ||
| 511 | Util.load(); | ||
| 512 | initIDs(); | ||
| 513 | } | ||
| 514 | |||
| 515 | } | ||