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     /**
 284      * Set the Socket object
 285      * @param soc the socket
 286      */
 287     protected void setSocket(Socket soc) {
 288         this.socket = soc;
 289     }
 290 
 291     Socket getSocket() {
 292         return socket;
 293     }
 294 
 295     /**
 296      * Set the ServerSocket object
 297      * @param soc the socket
 298      */
 299     protected void setServerSocket(ServerSocket soc) {
 300         this.serverSocket = soc;
 301     }
 302 
 303     ServerSocket getServerSocket() {
 304         return serverSocket;
 305     }
 306 
 307     /**
 308      * Returns the address and port of this socket as a {@code String}.
 309      *
 310      * @return  a string representation of this socket.
 311      */
 312     public String toString() {
 313         return "Socket[addr=" + getInetAddress() +
 314             ",port=" + getPort() + ",localport=" + getLocalPort()  + "]";
 315     }
 316 
 317     void reset() throws IOException {
 318         address = null;
 319         port = 0;
 320         localport = 0;
 321     }
 322 
 323     /**
 324      * Sets performance preferences for this socket.
 325      *
 326      * <p> Sockets use the TCP/IP protocol by default.  Some implementations
 327      * may offer alternative protocols which have different performance
 328      * characteristics than TCP/IP.  This method allows the application to
 329      * express its own preferences as to how these tradeoffs should be made
 330      * when the implementation chooses from the available protocols.
 331      *
 332      * <p> Performance preferences are described by three integers
 333      * whose values indicate the relative importance of short connection time,
 334      * low latency, and high bandwidth.  The absolute values of the integers
 335      * are irrelevant; in order to choose a protocol the values are simply
 336      * compared, with larger values indicating stronger preferences. Negative
 337      * values represent a lower priority than positive values. If the
 338      * application prefers short connection time over both low latency and high
 339      * bandwidth, for example, then it could invoke this method with the values
 340      * {@code (1, 0, 0)}.  If the application prefers high bandwidth above low
 341      * latency, and low latency above short connection time, then it could
 342      * invoke this method with the values {@code (0, 1, 2)}.
 343      *
 344      * By default, this method does nothing, unless it is overridden in
 345      * a sub-class.
 346      *
 347      * @param  connectionTime
 348      *         An {@code int} expressing the relative importance of a short
 349      *         connection time
 350      *
 351      * @param  latency
 352      *         An {@code int} expressing the relative importance of low
 353      *         latency
 354      *
 355      * @param  bandwidth
 356      *         An {@code int} expressing the relative importance of high
 357      *         bandwidth
 358      *
 359      * @since 1.5
 360      */
 361     protected void setPerformancePreferences(int connectionTime,
 362                                           int latency,
 363                                           int bandwidth)
 364     {
 365         /* Not implemented yet */
 366     }
 367 
 368     /**
 369      * Called to set a socket option.
 370      *
 371      * @param <T> The type of the socket option value
 372      * @param name The socket option
 373      *
 374      * @param value The value of the socket option. A value of {@code null}
 375      *              may be valid for some options.
 376      *
 377      * @throws UnsupportedOperationException if the SocketImpl does not
 378      *         support the option
 379      *
 380      * @throws IOException if an I/O error occurs, or if the socket is closed.
 381      *
 382      * @since 9
 383      */
 384     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
 385         if (name == StandardSocketOptions.SO_KEEPALIVE &&
 386                 (getSocket() != null)) {
 387             setOption(SocketOptions.SO_KEEPALIVE, value);
 388         } else if (name == StandardSocketOptions.SO_SNDBUF &&
 389                 (getSocket() != null)) {
 390             setOption(SocketOptions.SO_SNDBUF, value);
 391         } else if (name == StandardSocketOptions.SO_RCVBUF) {
 392             setOption(SocketOptions.SO_RCVBUF, value);
 393         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
 394             setOption(SocketOptions.SO_REUSEADDR, value);
 395         } else if (name == StandardSocketOptions.SO_REUSEPORT &&
 396             supportedOptions().contains(name)) {
 397             setOption(SocketOptions.SO_REUSEPORT, value);
 398         } else if (name == StandardSocketOptions.SO_LINGER &&
 399                 (getSocket() != null)) {
 400             setOption(SocketOptions.SO_LINGER, value);
 401         } else if (name == StandardSocketOptions.IP_TOS) {
 402             setOption(SocketOptions.IP_TOS, value);
 403         } else if (name == StandardSocketOptions.TCP_NODELAY &&
 404                 (getSocket() != null)) {
 405             setOption(SocketOptions.TCP_NODELAY, value);
 406         } else {
 407             throw new UnsupportedOperationException("unsupported option");
 408         }
 409     }
 410 
 411     /**
 412      * Called to get a socket option.
 413      *
 414      * @param <T> The type of the socket option value
 415      * @param name The socket option
 416      *
 417      * @return the value of the named option
 418      *
 419      * @throws UnsupportedOperationException if the SocketImpl does not
 420      *         support the option.
 421      *
 422      * @throws IOException if an I/O error occurs, or if the socket is closed.
 423      *
 424      * @since 9
 425      */
 426     @SuppressWarnings("unchecked")
 427     protected <T> T getOption(SocketOption<T> name) throws IOException {
 428         if (name == StandardSocketOptions.SO_KEEPALIVE &&
 429                 (getSocket() != null)) {
 430             return (T)getOption(SocketOptions.SO_KEEPALIVE);
 431         } else if (name == StandardSocketOptions.SO_SNDBUF &&
 432                 (getSocket() != null)) {
 433             return (T)getOption(SocketOptions.SO_SNDBUF);
 434         } else if (name == StandardSocketOptions.SO_RCVBUF) {
 435             return (T)getOption(SocketOptions.SO_RCVBUF);
 436         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
 437             return (T)getOption(SocketOptions.SO_REUSEADDR);
 438         } else if (name == StandardSocketOptions.SO_REUSEPORT &&
 439             supportedOptions().contains(name)) {
 440             return (T)getOption(SocketOptions.SO_REUSEPORT);
 441         } else if (name == StandardSocketOptions.SO_LINGER &&
 442                 (getSocket() != null)) {
 443             return (T)getOption(SocketOptions.SO_LINGER);
 444         } else if (name == StandardSocketOptions.IP_TOS) {
 445             return (T)getOption(SocketOptions.IP_TOS);
 446         } else if (name == StandardSocketOptions.TCP_NODELAY &&
 447                 (getSocket() != null)) {
 448             return (T)getOption(SocketOptions.TCP_NODELAY);
 449         } else {
 450             throw new UnsupportedOperationException("unsupported option");
 451         }
 452     }
 453 
 454     private static final Set<SocketOption<?>> socketOptions;
 455 
 456     private static final Set<SocketOption<?>> serverSocketOptions;
 457 
 458     static {
 459         socketOptions = Set.of(StandardSocketOptions.SO_KEEPALIVE,
 460                                StandardSocketOptions.SO_SNDBUF,
 461                                StandardSocketOptions.SO_RCVBUF,
 462                                StandardSocketOptions.SO_REUSEADDR,
 463                                StandardSocketOptions.SO_LINGER,
 464                                StandardSocketOptions.IP_TOS,
 465                                StandardSocketOptions.TCP_NODELAY);
 466 
 467         serverSocketOptions = Set.of(StandardSocketOptions.SO_RCVBUF,
 468                                      StandardSocketOptions.SO_REUSEADDR,
 469                                      StandardSocketOptions.IP_TOS);
 470     }
 471 
 472     /**
 473      * Returns a set of SocketOptions supported by this impl
 474      * and by this impl's socket (Socket or ServerSocket)
 475      *
 476      * @return a Set of SocketOptions
 477      *
 478      * @since 9
 479      */
 480     protected Set<SocketOption<?>> supportedOptions() {
 481         if (getSocket() != null) {
 482             return socketOptions;
 483         } else {
 484             return serverSocketOptions;
 485         }
 486     }
 487 }