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