Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/classes/java/net/DualStackPlainSocketImpl.java
32287 views
/*1* Copyright (c) 2007, 2013, 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*/24package java.net;2526import java.io.IOException;27import java.io.FileDescriptor;28import sun.misc.SharedSecrets;29import sun.misc.JavaIOFileDescriptorAccess;3031/**32* This class defines the plain SocketImpl that is used on Windows platforms33* greater or equal to Windows Vista. These platforms have a dual34* layer TCP/IP stack and can handle both IPv4 and IPV6 through a35* single file descriptor.36*37* @author Chris Hegarty38*/3940class DualStackPlainSocketImpl extends AbstractPlainSocketImpl41{42static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess();434445// true if this socket is exclusively bound46private final boolean exclusiveBind;4748// emulates SO_REUSEADDR when exclusiveBind is true49private boolean isReuseAddress;5051public DualStackPlainSocketImpl(boolean exclBind) {52exclusiveBind = exclBind;53}5455public DualStackPlainSocketImpl(FileDescriptor fd, boolean exclBind) {56this.fd = fd;57exclusiveBind = exclBind;58}5960void socketCreate(boolean stream) throws IOException {61if (fd == null)62throw new SocketException("Socket closed");6364int newfd = socket0(stream, false /*v6 Only*/);6566fdAccess.set(fd, newfd);67}6869void socketConnect(InetAddress address, int port, int timeout)70throws IOException {71int nativefd = checkAndReturnNativeFD();7273if (address == null)74throw new NullPointerException("inet address argument is null.");7576int connectResult;77if (timeout <= 0) {78connectResult = connect0(nativefd, address, port);79} else {80configureBlocking(nativefd, false);81try {82connectResult = connect0(nativefd, address, port);83if (connectResult == WOULDBLOCK) {84waitForConnect(nativefd, timeout);85}86} finally {87configureBlocking(nativefd, true);88}89}90/*91* We need to set the local port field. If bind was called92* previous to the connect (by the client) then localport field93* will already be set.94*/95if (localport == 0)96localport = localPort0(nativefd);97}9899void socketBind(InetAddress address, int port) throws IOException {100int nativefd = checkAndReturnNativeFD();101102if (address == null)103throw new NullPointerException("inet address argument is null.");104105bind0(nativefd, address, port, exclusiveBind);106if (port == 0) {107localport = localPort0(nativefd);108} else {109localport = port;110}111112this.address = address;113}114115void socketListen(int backlog) throws IOException {116int nativefd = checkAndReturnNativeFD();117118listen0(nativefd, backlog);119}120121void socketAccept(SocketImpl s) throws IOException {122int nativefd = checkAndReturnNativeFD();123124if (s == null)125throw new NullPointerException("socket is null");126127int newfd = -1;128InetSocketAddress[] isaa = new InetSocketAddress[1];129if (timeout <= 0) {130newfd = accept0(nativefd, isaa);131} else {132configureBlocking(nativefd, false);133try {134waitForNewConnection(nativefd, timeout);135newfd = accept0(nativefd, isaa);136if (newfd != -1) {137configureBlocking(newfd, true);138}139} finally {140configureBlocking(nativefd, true);141}142}143/* Update (SocketImpl)s' fd */144fdAccess.set(s.fd, newfd);145/* Update socketImpls remote port, address and localport */146InetSocketAddress isa = isaa[0];147s.port = isa.getPort();148s.address = isa.getAddress();149s.localport = localport;150}151152int socketAvailable() throws IOException {153int nativefd = checkAndReturnNativeFD();154return available0(nativefd);155}156157void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {158if (fd == null)159throw new SocketException("Socket closed");160161if (!fd.valid())162return;163164final int nativefd = fdAccess.get(fd);165fdAccess.set(fd, -1);166close0(nativefd);167}168169void socketShutdown(int howto) throws IOException {170int nativefd = checkAndReturnNativeFD();171shutdown0(nativefd, howto);172}173174// Intentional fallthrough after SO_REUSEADDR175@SuppressWarnings("fallthrough")176void socketSetOption(int opt, boolean on, Object value)177throws SocketException {178int nativefd = checkAndReturnNativeFD();179180if (opt == SO_TIMEOUT) { // timeout implemented through select.181return;182}183184int optionValue = 0;185186switch(opt) {187case SO_REUSEADDR :188if (exclusiveBind) {189// SO_REUSEADDR emulated when using exclusive bind190isReuseAddress = on;191return;192}193// intentional fallthrough194case TCP_NODELAY :195case SO_OOBINLINE :196case SO_KEEPALIVE :197optionValue = on ? 1 : 0;198break;199case SO_SNDBUF :200case SO_RCVBUF :201case IP_TOS :202optionValue = ((Integer)value).intValue();203break;204case SO_LINGER :205if (on) {206optionValue = ((Integer)value).intValue();207} else {208optionValue = -1;209}210break;211default :/* shouldn't get here */212throw new SocketException("Option not supported");213}214215setIntOption(nativefd, opt, optionValue);216}217218int socketGetOption(int opt, Object iaContainerObj) throws SocketException {219int nativefd = checkAndReturnNativeFD();220221// SO_BINDADDR is not a socket option.222if (opt == SO_BINDADDR) {223localAddress(nativefd, (InetAddressContainer)iaContainerObj);224return 0; // return value doesn't matter.225}226227// SO_REUSEADDR emulated when using exclusive bind228if (opt == SO_REUSEADDR && exclusiveBind)229return isReuseAddress? 1 : -1;230231int value = getIntOption(nativefd, opt);232233switch (opt) {234case TCP_NODELAY :235case SO_OOBINLINE :236case SO_KEEPALIVE :237case SO_REUSEADDR :238return (value == 0) ? -1 : 1;239}240return value;241}242243void socketSendUrgentData(int data) throws IOException {244int nativefd = checkAndReturnNativeFD();245sendOOB(nativefd, data);246}247248private int checkAndReturnNativeFD() throws SocketException {249if (fd == null || !fd.valid())250throw new SocketException("Socket closed");251252return fdAccess.get(fd);253}254255static final int WOULDBLOCK = -2; // Nothing available (non-blocking)256257static {258initIDs();259}260261/* Native methods */262263static native void initIDs();264265static native int socket0(boolean stream, boolean v6Only) throws IOException;266267static native void bind0(int fd, InetAddress localAddress, int localport,268boolean exclBind)269throws IOException;270271static native int connect0(int fd, InetAddress remote, int remotePort)272throws IOException;273274static native void waitForConnect(int fd, int timeout) throws IOException;275276static native int localPort0(int fd) throws IOException;277278static native void localAddress(int fd, InetAddressContainer in) throws SocketException;279280static native void listen0(int fd, int backlog) throws IOException;281282static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;283284static native void waitForNewConnection(int fd, int timeout) throws IOException;285286static native int available0(int fd) throws IOException;287288static native void close0(int fd) throws IOException;289290static native void shutdown0(int fd, int howto) throws IOException;291292static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;293294static native int getIntOption(int fd, int cmd) throws SocketException;295296static native void sendOOB(int fd, int data) throws IOException;297298static native void configureBlocking(int fd, boolean blocking) throws IOException;299}300301302