1 /* 2 * Copyright (c) 1995, 2019, 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 java.net; 27 28 import java.io.FileDescriptor; 29 import java.io.IOException; 30 import java.io.InputStream; 31 import java.io.OutputStream; 32 import java.security.AccessController; 33 import java.security.PrivilegedAction; 34 import java.util.Objects; 35 import java.util.Set; 36 37 import sun.net.NetProperties; 38 import sun.net.PlatformSocketImpl; 39 import sun.nio.ch.NioSocketImpl; 40 41 /** 42 * The abstract class {@code SocketImpl} is a common superclass 43 * of all classes that actually implement sockets. It is used to 44 * create both client and server sockets. 45 * 46 * @implNote Client and server sockets created with the {@code Socket} and 47 * {@code SocketServer} public constructors create a system-default 48 * {@code SocketImpl}. The JDK historically used a {@code SocketImpl} 49 * implementation type named "PlainSocketImpl" that has since been replaced by a 50 * newer implementation. The JDK continues to ship with the older implementation 51 * to allow code to run that depends on unspecified behavior that differs between 52 * the old and new implementations. The old implementation will be used if the 53 * Java virtual machine is started with the system property {@systemProperty 54 * jdk.net.usePlainSocketImpl} set to use the old implementation. It may also be 55 * set in the JDK's network configuration file, located in {@code 56 * ${java.home}/conf/net.properties}. The value of the property is the string 57 * representation of a boolean. If set without a value then it defaults to {@code 58 * true}, hence running with {@code -Djdk.net.usePlainSocketImpl} or {@code 59 * -Djdk.net.usePlainSocketImpl=true} will configure the Java virtual machine 60 * to use the old implementation. The property and old implementation will be 61 * removed in a future version. 62 * 63 * @author unascribed 64 * @since 1.0 65 */ 66 public abstract class SocketImpl implements SocketOptions { 67 private static final boolean USE_PLAINSOCKETIMPL = usePlainSocketImpl(); 68 69 private static boolean usePlainSocketImpl() { 70 PrivilegedAction<String> pa = () -> NetProperties.get("jdk.net.usePlainSocketImpl"); 71 String s = AccessController.doPrivileged(pa); 72 return (s != null) && !s.equalsIgnoreCase("false"); 73 } 74 75 /** 76 * Creates an instance of platform's SocketImpl 77 */ 78 @SuppressWarnings("unchecked") 79 static <S extends SocketImpl & PlatformSocketImpl> S createPlatformSocketImpl(boolean server) { 80 if (USE_PLAINSOCKETIMPL) { 81 return (S) new PlainSocketImpl(server); 82 } else { 83 return (S) new NioSocketImpl(server); 84 } 85 } 86 87 /** 88 * The file descriptor object for this socket. 89 */ 90 protected FileDescriptor fd; 91 92 /** 93 * The IP address of the remote end of this socket. 94 */ 95 protected InetAddress address; 96 97 /** 98 * The port number on the remote host to which this socket is connected. 99 */ 100 protected int port; 101 102 /** 103 * The local port number to which this socket is connected. 104 */ 105 protected int localport; 106 107 /** 108 * Initialize a new instance of this class 109 */ 110 public SocketImpl() { } 111 112 /** 113 * Creates either a stream or a datagram socket. 114 * 115 * @param stream if {@code true}, create a stream socket; 116 * otherwise, create a datagram socket. 117 * @throws IOException if an I/O error occurs while creating the 118 * socket. 119 */ 120 protected abstract void create(boolean stream) throws IOException; 121 122 /** 123 * Connects this socket to the specified port on the named host. 124 * 125 * @param host the name of the remote host. 126 * @param port the port number. 127 * @throws IOException if an I/O error occurs when connecting to the 128 * remote host. 129 */ 130 protected abstract void connect(String host, int port) throws IOException; 131 132 /** 133 * Connects this socket to the specified port number on the specified host. 134 * 135 * @param address the IP address of the remote host. 136 * @param port the port number. 137 * @throws IOException if an I/O error occurs when attempting a 138 * connection. 139 */ 140 protected abstract void connect(InetAddress address, int port) throws IOException; 141 142 /** 143 * Connects this socket to the specified port number on the specified host. 144 * A timeout of zero is interpreted as an infinite timeout. The connection 145 * will then block until established or an error occurs. 146 * 147 * @param address the Socket address of the remote host. 148 * @param timeout the timeout value, in milliseconds, or zero for no timeout. 149 * @throws IOException if an I/O error occurs when attempting a 150 * connection. 151 * @since 1.4 152 */ 153 protected abstract void connect(SocketAddress address, int timeout) throws IOException; 154 155 /** 156 * Binds this socket to the specified local IP address and port number. 157 * 158 * @param host an IP address that belongs to a local interface. 159 * @param port the port number. 160 * @throws IOException if an I/O error occurs when binding this socket. 161 */ 162 protected abstract void bind(InetAddress host, int port) throws IOException; 163 164 /** 165 * Sets the maximum queue length for incoming connection indications 166 * (a request to connect) to the {@code count} argument. If a 167 * connection indication arrives when the queue is full, the 168 * connection is refused. 169 * 170 * @param backlog the maximum length of the queue. 171 * @throws IOException if an I/O error occurs when creating the queue. 172 */ 173 protected abstract void listen(int backlog) throws IOException; 174 175 /** 176 * Accepts a connection. 177 * 178 * @param s the accepted connection. 179 * @throws IOException if an I/O error occurs when accepting the 180 * connection. 181 */ 182 protected abstract void accept(SocketImpl s) throws IOException; 183 184 /** 185 * Returns an input stream for this socket. 186 * 187 * @return a stream for reading from this socket. 188 * @throws IOException if an I/O error occurs when creating the 189 * input stream. 190 */ 191 protected abstract InputStream getInputStream() throws IOException; 192 193 /** 194 * Returns an output stream for this socket. 195 * 196 * @return an output stream for writing to this socket. 197 * @throws IOException if an I/O error occurs when creating the 198 * output stream. 199 */ 200 protected abstract OutputStream getOutputStream() throws IOException; 201 202 /** 203 * Returns the number of bytes that can be read from this socket 204 * without blocking. 205 * 206 * @return the number of bytes that can be read from this socket 207 * without blocking. 208 * @throws IOException if an I/O error occurs when determining the 209 * number of bytes available. 210 */ 211 protected abstract int available() throws IOException; 212 213 /** 214 * Closes this socket. 215 * 216 * @throws IOException if an I/O error occurs when closing this socket. 217 */ 218 protected abstract void close() throws IOException; 219 220 /** 221 * Closes this socket, ignoring any IOException that is thrown by close. 222 */ 223 void closeQuietly() { 224 try { 225 close(); 226 } catch (IOException ignore) { } 227 } 228 229 /** 230 * Places the input stream for this socket at "end of stream". 231 * Any data sent to this socket is acknowledged and then 232 * silently discarded. 233 * 234 * If you read from a socket input stream after invoking this method on the 235 * socket, the stream's {@code available} method will return 0, and its 236 * {@code read} methods will return {@code -1} (end of stream). 237 * 238 * @throws IOException if an I/O error occurs when shutting down this 239 * socket. 240 * @see java.net.Socket#shutdownOutput() 241 * @see java.net.Socket#close() 242 * @see java.net.Socket#setSoLinger(boolean, int) 243 * @since 1.3 244 */ 245 protected void shutdownInput() throws IOException { 246 throw new IOException("Method not implemented!"); 247 } 248 249 /** 250 * Disables the output stream for this socket. 251 * For a TCP socket, any previously written data will be sent 252 * followed by TCP's normal connection termination sequence. 253 * 254 * If you write to a socket output stream after invoking 255 * shutdownOutput() on the socket, the stream will throw 256 * an IOException. 257 * 258 * @throws IOException if an I/O error occurs when shutting down this 259 * socket. 260 * @see java.net.Socket#shutdownInput() 261 * @see java.net.Socket#close() 262 * @see java.net.Socket#setSoLinger(boolean, int) 263 * @since 1.3 264 */ 265 protected void shutdownOutput() throws IOException { 266 throw new IOException("Method not implemented!"); 267 } 268 269 /** 270 * Returns the value of this socket's {@code fd} field. 271 * 272 * @return the value of this socket's {@code fd} field. 273 * @see java.net.SocketImpl#fd 274 */ 275 protected FileDescriptor getFileDescriptor() { 276 return fd; 277 } 278 279 /** 280 * Returns the value of this socket's {@code address} field. 281 * 282 * @return the value of this socket's {@code address} field. 283 * @see java.net.SocketImpl#address 284 */ 285 protected InetAddress getInetAddress() { 286 return address; 287 } 288 289 /** 290 * Returns the value of this socket's {@code port} field. 291 * 292 * @return the value of this socket's {@code port} field. 293 * @see java.net.SocketImpl#port 294 */ 295 protected int getPort() { 296 return port; 297 } 298 299 /** 300 * Returns whether or not this SocketImpl supports sending 301 * urgent data. By default, false is returned 302 * unless the method is overridden in a sub-class 303 * 304 * @return true if urgent data supported 305 * @see java.net.SocketImpl#address 306 * @since 1.4 307 */ 308 protected boolean supportsUrgentData () { 309 return false; // must be overridden in sub-class 310 } 311 312 /** 313 * Send one byte of urgent data on the socket. 314 * The byte to be sent is the low eight bits of the parameter 315 * @param data The byte of data to send 316 * @throws IOException if there is an error 317 * sending the data. 318 * @since 1.4 319 */ 320 protected abstract void sendUrgentData (int data) throws IOException; 321 322 /** 323 * Returns the value of this socket's {@code localport} field. 324 * 325 * @return the value of this socket's {@code localport} field. 326 * @see java.net.SocketImpl#localport 327 */ 328 protected int getLocalPort() { 329 return localport; 330 } 331 332 /** 333 * Returns the address and port of this socket as a {@code String}. 334 * 335 * @return a string representation of this socket. 336 */ 337 public String toString() { 338 return "Socket[addr=" + getInetAddress() + 339 ",port=" + getPort() + ",localport=" + getLocalPort() + "]"; 340 } 341 342 void reset() { 343 fd = null; 344 address = null; 345 port = 0; 346 localport = 0; 347 } 348 349 /** 350 * Sets performance preferences for this socket. 351 * 352 * <p> Sockets use the TCP/IP protocol by default. Some implementations 353 * may offer alternative protocols which have different performance 354 * characteristics than TCP/IP. This method allows the application to 355 * express its own preferences as to how these tradeoffs should be made 356 * when the implementation chooses from the available protocols. 357 * 358 * <p> Performance preferences are described by three integers 359 * whose values indicate the relative importance of short connection time, 360 * low latency, and high bandwidth. The absolute values of the integers 361 * are irrelevant; in order to choose a protocol the values are simply 362 * compared, with larger values indicating stronger preferences. Negative 363 * values represent a lower priority than positive values. If the 364 * application prefers short connection time over both low latency and high 365 * bandwidth, for example, then it could invoke this method with the values 366 * {@code (1, 0, 0)}. If the application prefers high bandwidth above low 367 * latency, and low latency above short connection time, then it could 368 * invoke this method with the values {@code (0, 1, 2)}. 369 * 370 * By default, this method does nothing, unless it is overridden in 371 * a sub-class. 372 * 373 * @param connectionTime 374 * An {@code int} expressing the relative importance of a short 375 * connection time 376 * 377 * @param latency 378 * An {@code int} expressing the relative importance of low 379 * latency 380 * 381 * @param bandwidth 382 * An {@code int} expressing the relative importance of high 383 * bandwidth 384 * 385 * @since 1.5 386 */ 387 protected void setPerformancePreferences(int connectionTime, 388 int latency, 389 int bandwidth) 390 { 391 /* Not implemented yet */ 392 } 393 394 /** 395 * Called to set a socket option. 396 * 397 * @implSpec 398 * The default implementation of this method first checks that the given 399 * socket option {@code name} is not null, then throws {@code 400 * UnsupportedOperationException}. Subclasses should override this method 401 * with an appropriate implementation. 402 * 403 * @param <T> The type of the socket option value 404 * @param name The socket option 405 * @param value The value of the socket option. A value of {@code null} 406 * may be valid for some options. 407 * 408 * @throws UnsupportedOperationException if the SocketImpl does not 409 * support the option 410 * @throws IllegalArgumentException if the value is not valid for 411 * the option 412 * @throws IOException if an I/O error occurs, or if the socket is closed 413 * @throws NullPointerException if name is {@code null} 414 * 415 * @since 9 416 */ 417 protected <T> void setOption(SocketOption<T> name, T value) throws IOException { 418 Objects.requireNonNull(name); 419 throw new UnsupportedOperationException("'" + name + "' not supported"); 420 } 421 422 /** 423 * Called to get a socket option. 424 * 425 * @implSpec 426 * The default implementation of this method first checks that the given 427 * socket option {@code name} is not null, then throws {@code 428 * UnsupportedOperationException}. Subclasses should override this method 429 * with an appropriate implementation. 430 * 431 * @param <T> The type of the socket option value 432 * @param name The socket option 433 * @return the value of the named option 434 * 435 * @throws UnsupportedOperationException if the SocketImpl does not 436 * support the option 437 * @throws IOException if an I/O error occurs, or if the socket is closed 438 * @throws NullPointerException if name is {@code null} 439 * 440 * @since 9 441 */ 442 protected <T> T getOption(SocketOption<T> name) throws IOException { 443 Objects.requireNonNull(name); 444 throw new UnsupportedOperationException("'" + name + "' not supported"); 445 } 446 447 /** 448 * Attempts to copy socket options from this SocketImpl to a target SocketImpl. 449 * At this time, only the SO_TIMEOUT make sense to copy. 450 */ 451 void copyOptionsTo(SocketImpl target) { 452 try { 453 Object timeout = getOption(SocketOptions.SO_TIMEOUT); 454 if (timeout instanceof Integer) { 455 target.setOption(SocketOptions.SO_TIMEOUT, timeout); 456 } 457 } catch (IOException ignore) { } 458 } 459 460 /** 461 * Returns a set of SocketOptions supported by this impl 462 * and by this impl's socket (Socket or ServerSocket) 463 * 464 * @implSpec 465 * The default implementation of this method returns an empty set. 466 * Subclasses should override this method with an appropriate implementation. 467 * 468 * @return a Set of SocketOptions 469 * 470 * @since 9 471 */ 472 protected Set<SocketOption<?>> supportedOptions() { 473 return Set.of(); 474 } 475 }