1/* 2 * Copyright (c) 2007, 2016, 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 */ 25package java.net; 26 27import java.io.*; 28import java.security.AccessController; 29import java.security.PrivilegedAction; 30import sun.security.action.GetPropertyAction; 31 32/* 33 * This class PlainSocketImpl simply delegates to the appropriate real 34 * SocketImpl. We do this because PlainSocketImpl is already extended 35 * by SocksSocketImpl. 36 * <p> 37 * There are two possibilities for the real SocketImpl, 38 * TwoStacksPlainSocketImpl or DualStackPlainSocketImpl. We use 39 * DualStackPlainSocketImpl on systems that have a dual stack 40 * TCP implementation. Otherwise we create an instance of 41 * TwoStacksPlainSocketImpl and delegate to it. 42 * 43 * @author Chris Hegarty 44 */ 45 46class PlainSocketImpl extends AbstractPlainSocketImpl 47{ 48 private AbstractPlainSocketImpl impl; 49 50 /* java.net.preferIPv4Stack */ 51 private static final boolean preferIPv4Stack; 52 53 /* True if exclusive binding is on for Windows */ 54 private static final boolean exclusiveBind; 55 56 static { 57 preferIPv4Stack = Boolean.parseBoolean( 58 AccessController.doPrivileged( 59 new GetPropertyAction("java.net.preferIPv4Stack"))); 60 61 String exclBindProp = AccessController.doPrivileged( 62 new GetPropertyAction("sun.net.useExclusiveBind", "")); 63 exclusiveBind = (exclBindProp.isEmpty()) 64 ? true 65 : Boolean.parseBoolean(exclBindProp); 66 } 67 68 /** 69 * Constructs an empty instance. 70 */ 71 PlainSocketImpl() { 72 if (!preferIPv4Stack) { 73 impl = new DualStackPlainSocketImpl(exclusiveBind); 74 } else { 75 impl = new TwoStacksPlainSocketImpl(exclusiveBind); 76 } 77 } 78 79 /** 80 * Constructs an instance with the given file descriptor. 81 */ 82 PlainSocketImpl(FileDescriptor fd) { 83 if (!preferIPv4Stack) { 84 impl = new DualStackPlainSocketImpl(fd, exclusiveBind); 85 } else { 86 impl = new TwoStacksPlainSocketImpl(fd, exclusiveBind); 87 } 88 } 89 90 // Override methods in SocketImpl that access impl's fields. 91 92 protected FileDescriptor getFileDescriptor() { 93 return impl.getFileDescriptor(); 94 } 95 96 protected InetAddress getInetAddress() { 97 return impl.getInetAddress(); 98 } 99 100 protected int getPort() { 101 return impl.getPort(); 102 } 103 104 protected int getLocalPort() { 105 return impl.getLocalPort(); 106 } 107 108 void setSocket(Socket soc) { 109 impl.setSocket(soc); 110 } 111 112 Socket getSocket() { 113 return impl.getSocket(); 114 } 115 116 void setServerSocket(ServerSocket soc) { 117 impl.setServerSocket(soc); 118 } 119 120 ServerSocket getServerSocket() { 121 return impl.getServerSocket(); 122 } 123 124 public String toString() { 125 return impl.toString(); 126 } 127 128 // Override methods in AbstractPlainSocketImpl that access impl's fields. 129 130 protected synchronized void create(boolean stream) throws IOException { 131 impl.create(stream); 132 133 // set fd to delegate's fd to be compatible with older releases 134 this.fd = impl.fd; 135 } 136 137 protected void connect(String host, int port) 138 throws UnknownHostException, IOException 139 { 140 impl.connect(host, port); 141 } 142 143 protected void connect(InetAddress address, int port) throws IOException { 144 impl.connect(address, port); 145 } 146 147 protected void connect(SocketAddress address, int timeout) throws IOException { 148 impl.connect(address, timeout); 149 } 150 151 public void setOption(int opt, Object val) throws SocketException { 152 if (opt == SocketOptions.SO_REUSEPORT) { 153 // SO_REUSEPORT is not supported on Windows. 154 throw new UnsupportedOperationException("unsupported option"); 155 } 156 impl.setOption(opt, val); 157 } 158 159 public Object getOption(int opt) throws SocketException { 160 if (opt == SocketOptions.SO_REUSEPORT) { 161 // SO_REUSEPORT is not supported on Windows. 162 throw new UnsupportedOperationException("unsupported option"); 163 } 164 return impl.getOption(opt); 165 } 166 167 synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException { 168 impl.doConnect(address, port, timeout); 169 } 170 171 protected synchronized void bind(InetAddress address, int lport) 172 throws IOException 173 { 174 impl.bind(address, lport); 175 } 176 177 protected synchronized void accept(SocketImpl s) throws IOException { 178 if (s instanceof PlainSocketImpl) { 179 // pass in the real impl not the wrapper. 180 SocketImpl delegate = ((PlainSocketImpl)s).impl; 181 delegate.address = new InetAddress(); 182 delegate.fd = new FileDescriptor(); 183 impl.accept(delegate); 184 // set fd to delegate's fd to be compatible with older releases 185 s.fd = delegate.fd; 186 } else { 187 impl.accept(s); 188 } 189 } 190 191 void setFileDescriptor(FileDescriptor fd) { 192 impl.setFileDescriptor(fd); 193 } 194 195 void setAddress(InetAddress address) { 196 impl.setAddress(address); 197 } 198 199 void setPort(int port) { 200 impl.setPort(port); 201 } 202 203 void setLocalPort(int localPort) { 204 impl.setLocalPort(localPort); 205 } 206 207 protected synchronized InputStream getInputStream() throws IOException { 208 return impl.getInputStream(); 209 } 210 211 void setInputStream(SocketInputStream in) { 212 impl.setInputStream(in); 213 } 214 215 protected synchronized OutputStream getOutputStream() throws IOException { 216 return impl.getOutputStream(); 217 } 218 219 protected void close() throws IOException { 220 try { 221 impl.close(); 222 } finally { 223 // set fd to delegate's fd to be compatible with older releases 224 this.fd = null; 225 } 226 } 227 228 void reset() throws IOException { 229 try { 230 impl.reset(); 231 } finally { 232 // set fd to delegate's fd to be compatible with older releases 233 this.fd = null; 234 } 235 } 236 237 protected void shutdownInput() throws IOException { 238 impl.shutdownInput(); 239 } 240 241 protected void shutdownOutput() throws IOException { 242 impl.shutdownOutput(); 243 } 244 245 protected void sendUrgentData(int data) throws IOException { 246 impl.sendUrgentData(data); 247 } 248 249 FileDescriptor acquireFD() { 250 return impl.acquireFD(); 251 } 252 253 void releaseFD() { 254 impl.releaseFD(); 255 } 256 257 public boolean isConnectionReset() { 258 return impl.isConnectionReset(); 259 } 260 261 public boolean isConnectionResetPending() { 262 return impl.isConnectionResetPending(); 263 } 264 265 public void setConnectionReset() { 266 impl.setConnectionReset(); 267 } 268 269 public void setConnectionResetPending() { 270 impl.setConnectionResetPending(); 271 } 272 273 public boolean isClosedOrPending() { 274 return impl.isClosedOrPending(); 275 } 276 277 public int getTimeout() { 278 return impl.getTimeout(); 279 } 280 281 // Override methods in AbstractPlainSocketImpl that need to be implemented. 282 283 void socketCreate(boolean isServer) throws IOException { 284 impl.socketCreate(isServer); 285 } 286 287 void socketConnect(InetAddress address, int port, int timeout) 288 throws IOException { 289 impl.socketConnect(address, port, timeout); 290 } 291 292 void socketBind(InetAddress address, int port) 293 throws IOException { 294 impl.socketBind(address, port); 295 } 296 297 void socketListen(int count) throws IOException { 298 impl.socketListen(count); 299 } 300 301 void socketAccept(SocketImpl s) throws IOException { 302 impl.socketAccept(s); 303 } 304 305 int socketAvailable() throws IOException { 306 return impl.socketAvailable(); 307 } 308 309 void socketClose0(boolean useDeferredClose) throws IOException { 310 impl.socketClose0(useDeferredClose); 311 } 312 313 void socketShutdown(int howto) throws IOException { 314 impl.socketShutdown(howto); 315 } 316 317 void socketSetOption(int cmd, boolean on, Object value) 318 throws SocketException { 319 if (cmd == SocketOptions.SO_REUSEPORT) { 320 // SO_REUSEPORT is not supported on Windows. 321 throw new UnsupportedOperationException("unsupported option"); 322 } 323 impl.socketSetOption(cmd, on, value); 324 } 325 326 int socketGetOption(int opt, Object iaContainerObj) throws SocketException { 327 if (opt == SocketOptions.SO_REUSEPORT) { 328 // SO_REUSEPORT is not supported on Windows. 329 throw new UnsupportedOperationException("unsupported option"); 330 } 331 return impl.socketGetOption(opt, iaContainerObj); 332 } 333 334 void socketSendUrgentData(int data) throws IOException { 335 impl.socketSendUrgentData(data); 336 } 337 338 static boolean isReusePortAvailable() { 339 // SO_REUSEPORT is not supported on Windows. 340 return false; 341 } 342} 343