Path: blob/master/src/java.base/windows/classes/java/net/PlainSocketImpl.java
41133 views
/*1* Copyright (c) 2007, 2021, 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 java.security.AccessController;2930import sun.security.action.GetPropertyAction;31import jdk.internal.access.SharedSecrets;32import jdk.internal.access.JavaIOFileDescriptorAccess;3334/**35* On Windows system we simply delegate to native methods.36*37* @author Chris Hegarty38*/3940class PlainSocketImpl extends AbstractPlainSocketImpl {4142private static final JavaIOFileDescriptorAccess fdAccess =43SharedSecrets.getJavaIOFileDescriptorAccess();4445@SuppressWarnings("removal")46private static final boolean preferIPv4Stack =47Boolean.parseBoolean(AccessController.doPrivileged(48new GetPropertyAction("java.net.preferIPv4Stack", "false")));4950/**51* Empty value of sun.net.useExclusiveBind is treated as 'true'.52*/53private static final boolean useExclusiveBind;5455static {56@SuppressWarnings("removal")57String exclBindProp = AccessController.doPrivileged(58new GetPropertyAction("sun.net.useExclusiveBind", ""));59useExclusiveBind = exclBindProp.isEmpty()60|| Boolean.parseBoolean(exclBindProp);61}6263// emulates SO_REUSEADDR when useExclusiveBind is true64private boolean isReuseAddress;6566/**67* Constructs an empty instance.68*/69PlainSocketImpl(boolean isServer) {70super(isServer);71}7273@Override74void socketCreate(boolean stream) throws IOException {75if (fd == null)76throw new SocketException("Socket closed");7778int newfd = socket0(stream);7980fdAccess.set(fd, newfd);81}8283@Override84void socketConnect(InetAddress address, int port, int timeout)85throws IOException {86int nativefd = checkAndReturnNativeFD();8788if (address == null)89throw new NullPointerException("inet address argument is null.");9091if (preferIPv4Stack && !(address instanceof Inet4Address))92throw new SocketException("Protocol family not supported");9394int connectResult;95if (timeout <= 0) {96connectResult = connect0(nativefd, address, port);97} else {98configureBlocking(nativefd, false);99try {100connectResult = connect0(nativefd, address, port);101if (connectResult == WOULDBLOCK) {102waitForConnect(nativefd, timeout);103}104} finally {105configureBlocking(nativefd, true);106}107}108/*109* We need to set the local port field. If bind was called110* previous to the connect (by the client) then localport field111* will already be set.112*/113if (localport == 0)114localport = localPort0(nativefd);115}116117@Override118void socketBind(InetAddress address, int port) throws IOException {119int nativefd = checkAndReturnNativeFD();120121if (address == null)122throw new NullPointerException("inet address argument is null.");123124if (preferIPv4Stack && !(address instanceof Inet4Address))125throw new SocketException("Protocol family not supported");126127bind0(nativefd, address, port, useExclusiveBind);128if (port == 0) {129localport = localPort0(nativefd);130} else {131localport = port;132}133134this.address = address;135}136137@Override138void socketListen(int backlog) throws IOException {139int nativefd = checkAndReturnNativeFD();140141listen0(nativefd, backlog);142}143144@Override145void socketAccept(SocketImpl s) throws IOException {146int nativefd = checkAndReturnNativeFD();147148if (s == null)149throw new NullPointerException("socket is null");150151int newfd = -1;152InetSocketAddress[] isaa = new InetSocketAddress[1];153if (timeout <= 0) {154newfd = accept0(nativefd, isaa);155} else {156configureBlocking(nativefd, false);157try {158waitForNewConnection(nativefd, timeout);159newfd = accept0(nativefd, isaa);160if (newfd != -1) {161configureBlocking(newfd, true);162}163} finally {164configureBlocking(nativefd, true);165}166}167/* Update (SocketImpl)s' fd */168fdAccess.set(s.fd, newfd);169/* Update socketImpls remote port, address and localport */170InetSocketAddress isa = isaa[0];171s.port = isa.getPort();172s.address = isa.getAddress();173s.localport = localport;174if (preferIPv4Stack && !(s.address instanceof Inet4Address))175throw new SocketException("Protocol family not supported");176}177178@Override179int socketAvailable() throws IOException {180int nativefd = checkAndReturnNativeFD();181return available0(nativefd);182}183184@Override185void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {186if (fd == null)187throw new SocketException("Socket closed");188189if (!fd.valid())190return;191192final int nativefd = fdAccess.get(fd);193fdAccess.set(fd, -1);194close0(nativefd);195}196197@Override198void socketShutdown(int howto) throws IOException {199int nativefd = checkAndReturnNativeFD();200shutdown0(nativefd, howto);201}202203// Intentional fallthrough after SO_REUSEADDR204@SuppressWarnings("fallthrough")205@Override206void socketSetOption(int opt, boolean on, Object value)207throws SocketException {208209// SO_REUSEPORT is not supported on Windows.210if (opt == SO_REUSEPORT) {211throw new UnsupportedOperationException("unsupported option");212}213214int nativefd = checkAndReturnNativeFD();215216if (opt == SO_TIMEOUT) {217if (preferIPv4Stack) {218// Don't enable the socket option on ServerSocket as it's219// meaningless (we don't receive on a ServerSocket).220if (!isServer) {221setSoTimeout0(nativefd, ((Integer)value).intValue());222}223} // else timeout is implemented through select.224return;225}226227int optionValue = 0;228229switch(opt) {230case SO_REUSEADDR:231if (useExclusiveBind) {232// SO_REUSEADDR emulated when using exclusive bind233isReuseAddress = on;234return;235}236// intentional fallthrough237case TCP_NODELAY:238case SO_OOBINLINE:239case SO_KEEPALIVE:240optionValue = on ? 1 : 0;241break;242case SO_SNDBUF:243case SO_RCVBUF:244case IP_TOS:245optionValue = ((Integer)value).intValue();246break;247case SO_LINGER:248if (on) {249optionValue = ((Integer)value).intValue();250} else {251optionValue = -1;252}253break;254default :/* shouldn't get here */255throw new SocketException("Option not supported");256}257258setIntOption(nativefd, opt, optionValue);259}260261@Override262int socketGetOption(int opt, Object iaContainerObj)263throws SocketException {264265// SO_REUSEPORT is not supported on Windows.266if (opt == SO_REUSEPORT) {267throw new UnsupportedOperationException("unsupported option");268}269270int nativefd = checkAndReturnNativeFD();271272// SO_BINDADDR is not a socket option.273if (opt == SO_BINDADDR) {274localAddress(nativefd, (InetAddressContainer)iaContainerObj);275return 0; // return value doesn't matter.276}277278// SO_REUSEADDR emulated when using exclusive bind279if (opt == SO_REUSEADDR && useExclusiveBind)280return isReuseAddress ? 1 : -1;281282int value = getIntOption(nativefd, opt);283284switch (opt) {285case TCP_NODELAY:286case SO_OOBINLINE:287case SO_KEEPALIVE:288case SO_REUSEADDR:289return (value == 0) ? -1 : 1;290}291return value;292}293294@Override295void socketSendUrgentData(int data) throws IOException {296int nativefd = checkAndReturnNativeFD();297sendOOB(nativefd, data);298}299300private int checkAndReturnNativeFD() throws SocketException {301if (fd == null || !fd.valid())302throw new SocketException("Socket closed");303304return fdAccess.get(fd);305}306307static final int WOULDBLOCK = -2; // Nothing available (non-blocking)308309static {310initIDs();311}312313/* Native methods */314315static native void initIDs();316317static native int socket0(boolean stream) throws IOException;318319static native void bind0(int fd, InetAddress localAddress, int localport,320boolean exclBind)321throws IOException;322323static native int connect0(int fd, InetAddress remote, int remotePort)324throws IOException;325326static native void waitForConnect(int fd, int timeout) throws IOException;327328static native int localPort0(int fd) throws IOException;329330static native void localAddress(int fd, InetAddressContainer in) throws SocketException;331332static native void listen0(int fd, int backlog) throws IOException;333334static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;335336static native void waitForNewConnection(int fd, int timeout) throws IOException;337338static native int available0(int fd) throws IOException;339340static native void close0(int fd) throws IOException;341342static native void shutdown0(int fd, int howto) throws IOException;343344static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;345346static native void setSoTimeout0(int fd, int timeout) throws SocketException;347348static native int getIntOption(int fd, int cmd) throws SocketException;349350static native void sendOOB(int fd, int data) throws IOException;351352static native void configureBlocking(int fd, boolean blocking) throws IOException;353}354355356