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