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