Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
      4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      5  *
      6  * This code is free software; you can redistribute it and/or modify it
      7  * under the terms of the GNU General Public License version 2 only, as
      8  * published by the Free Software Foundation.  Oracle designates this
      9  * particular file as subject to the "Classpath" exception as provided
     10  * by Oracle in the LICENSE file that accompanied this code.
     11  *
     12  * This code is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15  * version 2 for more details (a copy is included in the LICENSE file that
     16  * accompanied this code).
     17  *
     18  * You should have received a copy of the GNU General Public License version
     19  * 2 along with this work; if not, write to the Free Software Foundation,
     20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     21  *
     22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     23  * or visit www.oracle.com if you need additional information or have any
     24  * questions.
     25  */
     26 
     27 package java.net;
     28 
     29 import java.io.IOException;
     30 import java.io.InputStream;
     31 import java.io.OutputStream;
     32 import java.io.FileDescriptor;
     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   JDK1.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
    186      * shutdownInput() on the socket, the stream will return EOF.
    187      *
    188      * @exception IOException if an I/O error occurs when shutting down this
    189      * socket.
    190      * @see java.net.Socket#shutdownOutput()
    191      * @see java.net.Socket#close()
    192      * @see java.net.Socket#setSoLinger(boolean, int)
    193      * @since 1.3
    194      */
    195     protected void shutdownInput() throws IOException {
    196       throw new IOException("Method not implemented!");
    197     }
    198 
    199     /**
    200      * Disables the output stream for this socket.
    201      * For a TCP socket, any previously written data will be sent
    202      * followed by TCP's normal connection termination sequence.
    203      *
    204      * If you write to a socket output stream after invoking
    205      * shutdownOutput() on the socket, the stream will throw
    206      * an IOException.
    207      *
    208      * @exception IOException if an I/O error occurs when shutting down this
    209      * socket.
    210      * @see java.net.Socket#shutdownInput()
    211      * @see java.net.Socket#close()
    212      * @see java.net.Socket#setSoLinger(boolean, int)
    213      * @since 1.3
    214      */
    215     protected void shutdownOutput() throws IOException {
    216       throw new IOException("Method not implemented!");
    217     }
    218 
    219     /**
    220      * Returns the value of this socket's {@code fd} field.
    221      *
    222      * @return  the value of this socket's {@code fd} field.
    223      * @see     java.net.SocketImpl#fd
    224      */
    225     protected FileDescriptor getFileDescriptor() {
    226         return fd;
    227     }
    228 
    229     /**
    230      * @hide used by java.nio tests
    231      */
    232     public FileDescriptor getFD$() {
    233         return fd;
    234     }
    235 
    236     /**
    237      * Returns the value of this socket's {@code address} field.
    238      *
    239      * @return  the value of this socket's {@code address} field.
    240      * @see     java.net.SocketImpl#address
    241      */
    242     protected InetAddress getInetAddress() {
    243         return address;
    244     }
    245 
    246     /**
    247      * Returns the value of this socket's {@code port} field.
    248      *
    249      * @return  the value of this socket's {@code port} field.
    250      * @see     java.net.SocketImpl#port
    251      */
    252     protected int getPort() {
    253         return port;
    254     }
    255 
    256     /**
    257      * Returns whether or not this SocketImpl supports sending
    258      * urgent data. By default, false is returned
    259      * unless the method is overridden in a sub-class
    260      *
    261      * @return  true if urgent data supported
    262      * @see     java.net.SocketImpl#address
    263      * @since 1.4
    264      */
    265     protected boolean supportsUrgentData () {
    266         return false; // must be overridden in sub-class
    267     }
    268 
    269     /**
    270      * Send one byte of urgent data on the socket.
    271      * The byte to be sent is the low eight bits of the parameter
    272      * @param data The byte of data to send
    273      * @exception IOException if there is an error
    274      *  sending the data.
    275      * @since 1.4
    276      */
    277     protected abstract void sendUrgentData (int data) throws IOException;
    278 
    279     /**
    280      * Returns the value of this socket's {@code localport} field.
    281      *
    282      * @return  the value of this socket's {@code localport} field.
    283      * @see     java.net.SocketImpl#localport
    284      */
    285     protected int getLocalPort() {
    286         return localport;
    287     }
    288 
    289     void setSocket(Socket soc) {
    290         this.socket = soc;
    291     }
    292 
    293     Socket getSocket() {
    294         return socket;
    295     }
    296 
    297     void setServerSocket(ServerSocket soc) {
    298         this.serverSocket = soc;
    299     }
    300 
    301     ServerSocket getServerSocket() {
    302         return serverSocket;
    303     }
    304 
    305     /**
    306      * Returns the address and port of this socket as a {@code String}.
    307      *
    308      * @return  a string representation of this socket.
    309      */
    310     public String toString() {
    311         return "Socket[addr=" + getInetAddress() +
    312             ",port=" + getPort() + ",localport=" + getLocalPort()  + "]";
    313     }
    314 
    315     void reset() throws IOException {
    316         address = null;
    317         port = 0;
    318         localport = 0;
    319     }
    320 
    321     /**
    322      * Sets performance preferences for this socket.
    323      *
    324      * <p> Sockets use the TCP/IP protocol by default.  Some implementations
    325      * may offer alternative protocols which have different performance
    326      * characteristics than TCP/IP.  This method allows the application to
    327      * express its own preferences as to how these tradeoffs should be made
    328      * when the implementation chooses from the available protocols.
    329      *
    330      * <p> Performance preferences are described by three integers
    331      * whose values indicate the relative importance of short connection time,
    332      * low latency, and high bandwidth.  The absolute values of the integers
    333      * are irrelevant; in order to choose a protocol the values are simply
    334      * compared, with larger values indicating stronger preferences. Negative
    335      * values represent a lower priority than positive values. If the
    336      * application prefers short connection time over both low latency and high
    337      * bandwidth, for example, then it could invoke this method with the values
    338      * {@code (1, 0, 0)}.  If the application prefers high bandwidth above low
    339      * latency, and low latency above short connection time, then it could
    340      * invoke this method with the values {@code (0, 1, 2)}.
    341      *
    342      * By default, this method does nothing, unless it is overridden in a
    343      * a sub-class.
    344      *
    345      * @param  connectionTime
    346      *         An {@code int} expressing the relative importance of a short
    347      *         connection time
    348      *
    349      * @param  latency
    350      *         An {@code int} expressing the relative importance of low
    351      *         latency
    352      *
    353      * @param  bandwidth
    354      *         An {@code int} expressing the relative importance of high
    355      *         bandwidth
    356      *
    357      * @since 1.5
    358      */
    359     protected void setPerformancePreferences(int connectionTime,
    360                                           int latency,
    361                                           int bandwidth)
    362     {
    363         /* Not implemented yet */
    364     }
    365 
    366     <T> void setOption(SocketOption<T> name, T value) throws IOException {
    367         if (name == StandardSocketOptions.SO_KEEPALIVE) {
    368             setOption(SocketOptions.SO_KEEPALIVE, value);
    369         } else if (name == StandardSocketOptions.SO_SNDBUF) {
    370             setOption(SocketOptions.SO_SNDBUF, value);
    371         } else if (name == StandardSocketOptions.SO_RCVBUF) {
    372             setOption(SocketOptions.SO_RCVBUF, value);
    373         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
    374             setOption(SocketOptions.SO_REUSEADDR, value);
    375         } else if (name == StandardSocketOptions.SO_LINGER) {
    376             setOption(SocketOptions.SO_LINGER, value);
    377         } else if (name == StandardSocketOptions.IP_TOS) {
    378             setOption(SocketOptions.IP_TOS, value);
    379         } else if (name == StandardSocketOptions.TCP_NODELAY) {
    380             setOption(SocketOptions.TCP_NODELAY, value);
    381         } else {
    382             throw new UnsupportedOperationException("unsupported option");
    383         }
    384     }
    385 
    386     <T> T getOption(SocketOption<T> name) throws IOException {
    387         if (name == StandardSocketOptions.SO_KEEPALIVE) {
    388             return (T)getOption(SocketOptions.SO_KEEPALIVE);
    389         } else if (name == StandardSocketOptions.SO_SNDBUF) {
    390             return (T)getOption(SocketOptions.SO_SNDBUF);
    391         } else if (name == StandardSocketOptions.SO_RCVBUF) {
    392             return (T)getOption(SocketOptions.SO_RCVBUF);
    393         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
    394             return (T)getOption(SocketOptions.SO_REUSEADDR);
    395         } else if (name == StandardSocketOptions.SO_LINGER) {
    396             return (T)getOption(SocketOptions.SO_LINGER);
    397         } else if (name == StandardSocketOptions.IP_TOS) {
    398             return (T)getOption(SocketOptions.IP_TOS);
    399         } else if (name == StandardSocketOptions.TCP_NODELAY) {
    400             return (T)getOption(SocketOptions.TCP_NODELAY);
    401         } else {
    402             throw new UnsupportedOperationException("unsupported option");
    403         }
    404     }
    405 }
    406