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