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 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     // Android-added: getFD$() for testing.
    231     /**
    232      * @hide used by java.nio tests
    233      */
    234     public FileDescriptor getFD$() {
    235         return fd;
    236     }
    237 
    238     /**
    239      * Returns the value of this socket's {@code address} field.
    240      *
    241      * @return  the value of this socket's {@code address} field.
    242      * @see     java.net.SocketImpl#address
    243      */
    244     protected InetAddress getInetAddress() {
    245         return address;
    246     }
    247 
    248     /**
    249      * Returns the value of this socket's {@code port} field.
    250      *
    251      * @return  the value of this socket's {@code port} field.
    252      * @see     java.net.SocketImpl#port
    253      */
    254     protected int getPort() {
    255         return port;
    256     }
    257 
    258     /**
    259      * Returns whether or not this SocketImpl supports sending
    260      * urgent data. By default, false is returned
    261      * unless the method is overridden in a sub-class
    262      *
    263      * @return  true if urgent data supported
    264      * @see     java.net.SocketImpl#address
    265      * @since 1.4
    266      */
    267     protected boolean supportsUrgentData () {
    268         return false; // must be overridden in sub-class
    269     }
    270 
    271     /**
    272      * Send one byte of urgent data on the socket.
    273      * The byte to be sent is the low eight bits of the parameter
    274      * @param data The byte of data to send
    275      * @exception IOException if there is an error
    276      *  sending the data.
    277      * @since 1.4
    278      */
    279     protected abstract void sendUrgentData (int data) throws IOException;
    280 
    281     /**
    282      * Returns the value of this socket's {@code localport} field.
    283      *
    284      * @return  the value of this socket's {@code localport} field.
    285      * @see     java.net.SocketImpl#localport
    286      */
    287     protected int getLocalPort() {
    288         return localport;
    289     }
    290 
    291     void setSocket(Socket soc) {
    292         this.socket = soc;
    293     }
    294 
    295     Socket getSocket() {
    296         return socket;
    297     }
    298 
    299     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 a
    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     <T> void setOption(SocketOption<T> name, T value) throws IOException {
    369         if (name == StandardSocketOptions.SO_KEEPALIVE) {
    370             setOption(SocketOptions.SO_KEEPALIVE, value);
    371         } else if (name == StandardSocketOptions.SO_SNDBUF) {
    372             setOption(SocketOptions.SO_SNDBUF, value);
    373         } else if (name == StandardSocketOptions.SO_RCVBUF) {
    374             setOption(SocketOptions.SO_RCVBUF, value);
    375         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
    376             setOption(SocketOptions.SO_REUSEADDR, value);
    377         } else if (name == StandardSocketOptions.SO_LINGER) {
    378             setOption(SocketOptions.SO_LINGER, value);
    379         } else if (name == StandardSocketOptions.IP_TOS) {
    380             setOption(SocketOptions.IP_TOS, value);
    381         } else if (name == StandardSocketOptions.TCP_NODELAY) {
    382             setOption(SocketOptions.TCP_NODELAY, value);
    383         } else {
    384             throw new UnsupportedOperationException("unsupported option");
    385         }
    386     }
    387 
    388     <T> T getOption(SocketOption<T> name) throws IOException {
    389         if (name == StandardSocketOptions.SO_KEEPALIVE) {
    390             return (T)getOption(SocketOptions.SO_KEEPALIVE);
    391         } else if (name == StandardSocketOptions.SO_SNDBUF) {
    392             return (T)getOption(SocketOptions.SO_SNDBUF);
    393         } else if (name == StandardSocketOptions.SO_RCVBUF) {
    394             return (T)getOption(SocketOptions.SO_RCVBUF);
    395         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
    396             return (T)getOption(SocketOptions.SO_REUSEADDR);
    397         } else if (name == StandardSocketOptions.SO_LINGER) {
    398             return (T)getOption(SocketOptions.SO_LINGER);
    399         } else if (name == StandardSocketOptions.IP_TOS) {
    400             return (T)getOption(SocketOptions.IP_TOS);
    401         } else if (name == StandardSocketOptions.TCP_NODELAY) {
    402             return (T)getOption(SocketOptions.TCP_NODELAY);
    403         } else {
    404             throw new UnsupportedOperationException("unsupported option");
    405         }
    406     }
    407 }
    408