1 /* 2 * Copyright (c) 2007, 2018, 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 package java.net; 26 27 import java.io.IOException; 28 import java.io.FileDescriptor; 29 import jdk.internal.misc.SharedSecrets; 30 import jdk.internal.misc.JavaIOFileDescriptorAccess; 31 32 /** 33 * This class defines the plain SocketImpl that is used on Windows platforms 34 * greater or equal to Windows Vista. These platforms have a dual 35 * layer TCP/IP stack and can handle both IPv4 and IPV6 through a 36 * single file descriptor. 37 * 38 * @author Chris Hegarty 39 */ 40 41 class DualStackPlainSocketImpl extends AbstractPlainSocketImpl 42 { 43 static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); 44 45 46 // true if this socket is exclusively bound 47 private final boolean exclusiveBind; 48 49 // emulates SO_REUSEADDR when exclusiveBind is true 50 private boolean isReuseAddress; 51 52 static { 53 initProto(); 54 } 55 56 public DualStackPlainSocketImpl(boolean exclBind) { 57 exclusiveBind = exclBind; 58 } 59 60 public DualStackPlainSocketImpl(FileDescriptor fd, boolean exclBind) { 61 this.fd = fd; 62 exclusiveBind = exclBind; 63 } 64 65 @Override 66 void socketBind(InetAddress address, int port) throws IOException { 67 socketBind(address, port, exclusiveBind); 68 } 69 70 @Override 71 void socketSetOption(int opt, boolean on, Object value) 72 throws SocketException 73 { 74 if (opt == SO_REUSEADDR && exclusiveBind) { 75 // SO_REUSEADDR emulated when using exclusive bind 76 isReuseAddress = on; 77 } else if (opt == SO_REUSEPORT) { 78 // SO_REUSEPORT is not supported on Windows. 79 throw new UnsupportedOperationException("unsupported option"); 80 } else { 81 socketNativeSetOption(opt, on, value); 82 } 83 } 84 85 @Override 86 int socketGetOption(int opt, Object iaContainerObj) throws SocketException { 87 int nativefd = checkAndReturnNativeFD(); 88 89 // SO_BINDADDR is not a socket option. 90 if (opt == SO_BINDADDR) { 91 localAddress(nativefd, (InetAddressContainer)iaContainerObj); 92 return 0; // return value doesn't matter. 93 } 94 // SO_REUSEPORT is not supported on Windows. 95 if (opt == SO_REUSEPORT) { 96 throw new UnsupportedOperationException("unsupported option"); 97 } 98 99 // SO_REUSEADDR emulated when using exclusive bind 100 if (opt == SO_REUSEADDR && exclusiveBind) 101 return isReuseAddress? 1 : -1; 102 103 int value = getIntOption(nativefd, opt); 104 105 switch (opt) { 106 case TCP_NODELAY : 107 case SO_OOBINLINE : 108 case SO_KEEPALIVE : 109 case SO_REUSEADDR : 110 return (value == 0) ? -1 : 1; 111 } 112 return value; 113 } 114 115 /* Native methods */ 116 117 static native void initProto(); 118 119 native void socketCreate(boolean stream) throws IOException; 120 121 native void socketConnect(InetAddress address, int port, int timeout) 122 throws IOException; 123 124 native void socketBind(InetAddress address, int port, boolean exclBind) 125 throws IOException; 126 127 native void socketListen(int count) throws IOException; 128 129 native void socketAccept(SocketImpl s) throws IOException; 130 131 native int socketAvailable() throws IOException; 132 133 native void socketClose0(boolean useDeferredClose) throws IOException; 134 135 native void socketShutdown(int howto) throws IOException; 136 137 static native int getIntOption(int fd, int cmd) throws SocketException; 138 static native void localAddress(int fd, InetAddressContainer in) throws SocketException; 139 140 native void socketNativeSetOption(int cmd, boolean on, Object value) 141 throws SocketException; 142 143 native int socketNativeGetOption(int opt, Object iaContainerObj) 144 throws SocketException; 145 146 native void socketSendUrgentData(int data) throws IOException; 147 148 private int checkAndReturnNativeFD() throws SocketException { 149 if (fd == null || !fd.valid()) 150 throw new SocketException("Socket closed"); 151 152 return fdAccess.get(fd); 153 } 154 }