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 import dalvik.annotation.optimization.ReachabilitySensitive;
     35 import dalvik.system.BlockGuard;
     36 import dalvik.system.CloseGuard;
     37 import dalvik.system.SocketTagger;
     38 import sun.net.ConnectionResetException;
     39 import sun.net.NetHooks;
     40 import sun.net.ResourceManager;
     41 
     42 /**
     43  * Default Socket Implementation. This implementation does
     44  * not implement any security checks.
     45  * Note this class should <b>NOT</b> be public.
     46  *
     47  * @author  Steven B. Byrne
     48  */
     49 abstract class AbstractPlainSocketImpl extends SocketImpl
     50 {
     51     /* instance variable for SO_TIMEOUT */
     52     int timeout;   // timeout in millisec
     53     // Android-removed: traffic class is set through socket
     54     // private int trafficClass;
     55 
     56     private boolean shut_rd = false;
     57     private boolean shut_wr = false;
     58 
     59     private SocketInputStream socketInputStream = null;
     60     private SocketOutputStream socketOutputStream = null;
     61 
     62     /* number of threads using the FileDescriptor */
     63     protected int fdUseCount = 0;
     64 
     65     /* lock when increment/decrementing fdUseCount */
     66     // Android-added: @ReachabilitySensitive
     67     // Marked mostly because it's used where fd is, and fd isn't declared here.
     68     // This adds reachabilityFences where we would if fd were annotated.
     69     @ReachabilitySensitive
     70     protected final Object fdLock = new Object();
     71 
     72     /* indicates a close is pending on the file descriptor */
     73     protected boolean closePending = false;
     74 
     75     /* indicates connection reset state */
     76     private int CONNECTION_NOT_RESET = 0;
     77     private int CONNECTION_RESET_PENDING = 1;
     78     private int CONNECTION_RESET = 2;
     79     private int resetState;
     80     private final Object resetLock = new Object();
     81 
     82    /* whether this Socket is a stream (TCP) socket or not (UDP)
     83     */
     84     protected boolean stream;
     85 
     86     // BEGIN Android-removed: Android doesn't need to load native net library
     87     /*
     88     /**
     89      * Load net library into runtime.
     90      *
     91     static {
     92         java.security.AccessController.doPrivileged(
     93             new java.security.PrivilegedAction<Void>() {
     94                 public Void run() {
     95                     System.loadLibrary("net");
     96                     return null;
     97                 }
     98             });
     99     }
    100     */
    101     // END Android-removed: Android doesn't need to load native net library
    102 
    103     // Android-added: logs a warning if socket is not closed
    104     @ReachabilitySensitive
    105     private final CloseGuard guard = CloseGuard.get();
    106 
    107     /**
    108      * Creates a socket with a boolean that specifies whether this
    109      * is a stream socket (true) or an unconnected UDP socket (false).
    110      */
    111     protected synchronized void create(boolean stream) throws IOException {
    112         this.stream = stream;
    113         if (!stream) {
    114             ResourceManager.beforeUdpCreate();
    115             // Android-removed: socketCreate should set fd if it succeeds
    116             // fd = new FileDescriptor();
    117             try {
    118                 socketCreate(false);
    119             } catch (IOException ioe) {
    120                 ResourceManager.afterUdpClose();
    121                 // Android-removed: b/26470377 Represent closed sockets with invalid fd, not null.
    122                 // fd = null;
    123                 throw ioe;
    124             }
    125         } else {
    126             // Android-removed: socketCreate should set fd if it succeeds
    127             // fd = new FileDescriptor();
    128             socketCreate(true);
    129         }
    130         if (socket != null)
    131             socket.setCreated();
    132         if (serverSocket != null)
    133             serverSocket.setCreated();
    134 
    135         // Android-added: CloseGuard
    136         if (fd != null && fd.valid()) {
    137             guard.open("close");
    138         }
    139     }
    140 
    141     /**
    142      * Creates a socket and connects it to the specified port on
    143      * the specified host.
    144      * @param host the specified host
    145      * @param port the specified port
    146      */
    147     protected void connect(String host, int port)
    148         throws UnknownHostException, IOException
    149     {
    150         boolean connected = false;
    151         try {
    152             InetAddress address = InetAddress.getByName(host);
    153             this.port = port;
    154             this.address = address;
    155 
    156             connectToAddress(address, port, timeout);
    157             connected = true;
    158         } finally {
    159             if (!connected) {
    160                 try {
    161                     close();
    162                 } catch (IOException ioe) {
    163                     /* Do nothing. If connect threw an exception then
    164                        it will be passed up the call stack */
    165                 }
    166             }
    167         }
    168     }
    169 
    170     /**
    171      * Creates a socket and connects it to the specified address on
    172      * the specified port.
    173      * @param address the address
    174      * @param port the specified port
    175      */
    176     protected void connect(InetAddress address, int port) throws IOException {
    177         this.port = port;
    178         this.address = address;
    179 
    180         try {
    181             connectToAddress(address, port, timeout);
    182             return;
    183         } catch (IOException e) {
    184             // everything failed
    185             close();
    186             throw e;
    187         }
    188     }
    189 
    190     /**
    191      * Creates a socket and connects it to the specified address on
    192      * the specified port.
    193      * @param address the address
    194      * @param timeout the timeout value in milliseconds, or zero for no timeout.
    195      * @throws IOException if connection fails
    196      * @throws  IllegalArgumentException if address is null or is a
    197      *          SocketAddress subclass not supported by this socket
    198      * @since 1.4
    199      */
    200     protected void connect(SocketAddress address, int timeout)
    201             throws IOException {
    202         boolean connected = false;
    203         try {
    204             if (address == null || !(address instanceof InetSocketAddress))
    205                 throw new IllegalArgumentException("unsupported address type");
    206             InetSocketAddress addr = (InetSocketAddress) address;
    207             if (addr.isUnresolved())
    208                 throw new UnknownHostException(addr.getHostName());
    209             this.port = addr.getPort();
    210             this.address = addr.getAddress();
    211 
    212             connectToAddress(this.address, port, timeout);
    213             connected = true;
    214         } finally {
    215             if (!connected) {
    216                 try {
    217                     close();
    218                 } catch (IOException ioe) {
    219                     /* Do nothing. If connect threw an exception then
    220                        it will be passed up the call stack */
    221                 }
    222             }
    223         }
    224     }
    225 
    226     private void connectToAddress(InetAddress address, int port, int timeout) throws IOException {
    227         if (address.isAnyLocalAddress()) {
    228             doConnect(InetAddress.getLocalHost(), port, timeout);
    229         } else {
    230             doConnect(address, port, timeout);
    231         }
    232     }
    233 
    234     public void setOption(int opt, Object val) throws SocketException {
    235         if (isClosedOrPending()) {
    236             throw new SocketException("Socket Closed");
    237         }
    238         // BEGIN Android-removed: Logic dealing with value type moved to socketSetOption.
    239         /*
    240         boolean on = true;
    241         switch (opt) {
    242             /* check type safety b4 going native.  These should never
    243              * fail, since only java.Socket* has access to
    244              * PlainSocketImpl.setOption().
    245              *
    246         case SO_LINGER:
    247             if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean)))
    248                 throw new SocketException("Bad parameter for option");
    249             if (val instanceof Boolean) {
    250                 /* true only if disabling - enabling should be Integer *
    251                 on = false;
    252             }
    253             break;
    254         case SO_TIMEOUT:
    255             if (val == null || (!(val instanceof Integer)))
    256                 throw new SocketException("Bad parameter for SO_TIMEOUT");
    257             int tmp = ((Integer) val).intValue();
    258             if (tmp < 0)
    259                 throw new IllegalArgumentException("timeout < 0");
    260             timeout = tmp;
    261             break;
    262         case IP_TOS:
    263              if (val == null || !(val instanceof Integer)) {
    264                  throw new SocketException("bad argument for IP_TOS");
    265              }
    266              trafficClass = ((Integer)val).intValue();
    267              break;
    268         case SO_BINDADDR:
    269             throw new SocketException("Cannot re-bind socket");
    270         case TCP_NODELAY:
    271             if (val == null || !(val instanceof Boolean))
    272                 throw new SocketException("bad parameter for TCP_NODELAY");
    273             on = ((Boolean)val).booleanValue();
    274             break;
    275         case SO_SNDBUF:
    276         case SO_RCVBUF:
    277             if (val == null || !(val instanceof Integer) ||
    278                 !(((Integer)val).intValue() > 0)) {
    279                 throw new SocketException("bad parameter for SO_SNDBUF " +
    280                                           "or SO_RCVBUF");
    281             }
    282             break;
    283         case SO_KEEPALIVE:
    284             if (val == null || !(val instanceof Boolean))
    285                 throw new SocketException("bad parameter for SO_KEEPALIVE");
    286             on = ((Boolean)val).booleanValue();
    287             break;
    288         case SO_OOBINLINE:
    289             if (val == null || !(val instanceof Boolean))
    290                 throw new SocketException("bad parameter for SO_OOBINLINE");
    291             on = ((Boolean)val).booleanValue();
    292             break;
    293         case SO_REUSEADDR:
    294             if (val == null || !(val instanceof Boolean))
    295                 throw new SocketException("bad parameter for SO_REUSEADDR");
    296             on = ((Boolean)val).booleanValue();
    297             break;
    298         default:
    299             throw new SocketException("unrecognized TCP option: " + opt);
    300         }
    301         socketSetOption(opt, on, val);
    302         */
    303         // END Android-removed: Logic dealing with value type moved to socketSetOption.
    304         // Android-added: Keep track of timeout value not handled by socketSetOption
    305         if (opt == SO_TIMEOUT) {
    306             timeout = (Integer) val;
    307         }
    308         socketSetOption(opt, val);
    309     }
    310     public Object getOption(int opt) throws SocketException {
    311         if (isClosedOrPending()) {
    312             throw new SocketException("Socket Closed");
    313         }
    314         if (opt == SO_TIMEOUT) {
    315             return new Integer(timeout);
    316         }
    317         // BEGIN Android-changed: Logic dealing with value type moved to socketGetOption.
    318         /*
    319         int ret = 0;
    320         /*
    321          * The native socketGetOption() knows about 3 options.
    322          * The 32 bit value it returns will be interpreted according
    323          * to what we're asking.  A return of -1 means it understands
    324          * the option but its turned off.  It will raise a SocketException
    325          * if "opt" isn't one it understands.
    326          *
    327 
    328         switch (opt) {
    329         case TCP_NODELAY:
    330             ret = socketGetOption(opt, null);
    331             return Boolean.valueOf(ret != -1);
    332         case SO_OOBINLINE:
    333             ret = socketGetOption(opt, null);
    334             return Boolean.valueOf(ret != -1);
    335         case SO_LINGER:
    336             ret = socketGetOption(opt, null);
    337             return (ret == -1) ? Boolean.FALSE: (Object)(new Integer(ret));
    338         case SO_REUSEADDR:
    339             ret = socketGetOption(opt, null);
    340             return Boolean.valueOf(ret != -1);
    341         case SO_BINDADDR:
    342             InetAddressContainer in = new InetAddressContainer();
    343             ret = socketGetOption(opt, in);
    344             return in.addr;
    345         case SO_SNDBUF:
    346         case SO_RCVBUF:
    347             ret = socketGetOption(opt, null);
    348             return new Integer(ret);
    349         case IP_TOS:
    350             try {
    351                 ret = socketGetOption(opt, null);
    352                 if (ret == -1) { // ipv6 tos
    353                     return trafficClass;
    354                 } else {
    355                     return ret;
    356                 }
    357             } catch (SocketException se) {
    358                 // TODO - should make better effort to read TOS or TCLASS
    359                 return trafficClass; // ipv6 tos
    360             }
    361         case SO_KEEPALIVE:
    362             ret = socketGetOption(opt, null);
    363             return Boolean.valueOf(ret != -1);
    364         // should never get here
    365         default:
    366             return null;
    367         }
    368         */
    369         return socketGetOption(opt);
    370         // END Android-changed: Logic dealing with value type moved to socketGetOption.
    371     }
    372 
    373     /**
    374      * The workhorse of the connection operation.  Tries several times to
    375      * establish a connection to the given <host, port>.  If unsuccessful,
    376      * throws an IOException indicating what went wrong.
    377      */
    378 
    379     synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
    380         synchronized (fdLock) {
    381             if (!closePending && (socket == null || !socket.isBound())) {
    382                 NetHooks.beforeTcpConnect(fd, address, port);
    383             }
    384         }
    385         try {
    386             acquireFD();
    387             try {
    388                 // Android-added: BlockGuard
    389                 BlockGuard.getThreadPolicy().onNetwork();
    390                 socketConnect(address, port, timeout);
    391                 /* socket may have been closed during poll/select */
    392                 synchronized (fdLock) {
    393                     if (closePending) {
    394                         throw new SocketException ("Socket closed");
    395                     }
    396                 }
    397                 // If we have a ref. to the Socket, then sets the flags
    398                 // created, bound & connected to true.
    399                 // This is normally done in Socket.connect() but some
    400                 // subclasses of Socket may call impl.connect() directly!
    401                 if (socket != null) {
    402                     socket.setBound();
    403                     socket.setConnected();
    404                 }
    405             } finally {
    406                 releaseFD();
    407             }
    408         } catch (IOException e) {
    409             close();
    410             throw e;
    411         }
    412     }
    413 
    414     /**
    415      * Binds the socket to the specified address of the specified local port.
    416      * @param address the address
    417      * @param lport the port
    418      */
    419     protected synchronized void bind(InetAddress address, int lport)
    420         throws IOException
    421     {
    422        synchronized (fdLock) {
    423             if (!closePending && (socket == null || !socket.isBound())) {
    424                 NetHooks.beforeTcpBind(fd, address, lport);
    425             }
    426         }
    427         socketBind(address, lport);
    428         if (socket != null)
    429             socket.setBound();
    430         if (serverSocket != null)
    431             serverSocket.setBound();
    432     }
    433 
    434     /**
    435      * Listens, for a specified amount of time, for connections.
    436      * @param count the amount of time to listen for connections
    437      */
    438     protected synchronized void listen(int count) throws IOException {
    439         socketListen(count);
    440     }
    441 
    442     /**
    443      * Accepts connections.
    444      * @param s the connection
    445      */
    446     protected void accept(SocketImpl s) throws IOException {
    447         acquireFD();
    448         try {
    449             // Android-added: BlockGuard
    450             BlockGuard.getThreadPolicy().onNetwork();
    451             socketAccept(s);
    452         } finally {
    453             releaseFD();
    454         }
    455     }
    456 
    457     /**
    458      * Gets an InputStream for this socket.
    459      */
    460     protected synchronized InputStream getInputStream() throws IOException {
    461         synchronized (fdLock) {
    462             if (isClosedOrPending())
    463                 throw new IOException("Socket Closed");
    464             if (shut_rd)
    465                 throw new IOException("Socket input is shutdown");
    466             if (socketInputStream == null)
    467                 socketInputStream = new SocketInputStream(this);
    468         }
    469         return socketInputStream;
    470     }
    471 
    472     void setInputStream(SocketInputStream in) {
    473         socketInputStream = in;
    474     }
    475 
    476     /**
    477      * Gets an OutputStream for this socket.
    478      */
    479     protected synchronized OutputStream getOutputStream() throws IOException {
    480         synchronized (fdLock) {
    481             if (isClosedOrPending())
    482                 throw new IOException("Socket Closed");
    483             if (shut_wr)
    484                 throw new IOException("Socket output is shutdown");
    485             if (socketOutputStream == null)
    486                 socketOutputStream = new SocketOutputStream(this);
    487         }
    488         return socketOutputStream;
    489     }
    490 
    491     void setFileDescriptor(FileDescriptor fd) {
    492         this.fd = fd;
    493     }
    494 
    495     void setAddress(InetAddress address) {
    496         this.address = address;
    497     }
    498 
    499     void setPort(int port) {
    500         this.port = port;
    501     }
    502 
    503     void setLocalPort(int localport) {
    504         this.localport = localport;
    505     }
    506 
    507     /**
    508      * Returns the number of bytes that can be read without blocking.
    509      */
    510     protected synchronized int available() throws IOException {
    511         if (isClosedOrPending()) {
    512             throw new IOException("Stream closed.");
    513         }
    514 
    515         /*
    516          * If connection has been reset or shut down for input, then return 0
    517          * to indicate there are no buffered bytes.
    518          */
    519         if (isConnectionReset() || shut_rd) {
    520             return 0;
    521         }
    522 
    523         /*
    524          * If no bytes available and we were previously notified
    525          * of a connection reset then we move to the reset state.
    526          *
    527          * If are notified of a connection reset then check
    528          * again if there are bytes buffered on the socket.
    529          */
    530         int n = 0;
    531         try {
    532             n = socketAvailable();
    533             if (n == 0 && isConnectionResetPending()) {
    534                 setConnectionReset();
    535             }
    536         } catch (ConnectionResetException exc1) {
    537             setConnectionResetPending();
    538             try {
    539                 n = socketAvailable();
    540                 if (n == 0) {
    541                     setConnectionReset();
    542                 }
    543             } catch (ConnectionResetException exc2) {
    544             }
    545         }
    546         return n;
    547     }
    548 
    549     /**
    550      * Closes the socket.
    551      */
    552     protected void close() throws IOException {
    553         synchronized(fdLock) {
    554             if (fd != null && fd.valid()) {
    555                 if (!stream) {
    556                     ResourceManager.afterUdpClose();
    557                 }
    558                 // Android-changed:
    559                 // Socket should be untagged before the preclose. After preclose,
    560                 // socket will dup2-ed to marker_fd, therefore, it won't describe the same file.
    561                 // If closingPending is true, then the socket has been preclosed.
    562                 //
    563                 // Also, close the CloseGuard when the #close is called.
    564                 if (!closePending) {
    565                     closePending = true;
    566                     guard.close();
    567 
    568                     if (fdUseCount == 0) {
    569                         /*
    570                          * We close the FileDescriptor in two-steps - first the
    571                          * "pre-close" which closes the socket but doesn't
    572                          * release the underlying file descriptor. This operation
    573                          * may be lengthy due to untransmitted data and a long
    574                          * linger interval. Once the pre-close is done we do the
    575                          * actual socket to release the fd.
    576                          */
    577                         try {
    578                             socketPreClose();
    579                         } finally {
    580                             socketClose();
    581                         }
    582                         // Android-changed(http://b/26470377): Some Android code doesn't expect file
    583                         // descriptor to be null. socketClose invalidates the fd by closing the fd.
    584                         // fd = null;
    585                         return;
    586                     } else {
    587                         /*
    588                          * If a thread has acquired the fd and a close
    589                          * isn't pending then use a deferred close.
    590                          * Also decrement fdUseCount to signal the last
    591                          * thread that releases the fd to close it.
    592                          */
    593                         fdUseCount--;
    594                         socketPreClose();
    595                     }
    596                 }
    597             }
    598         }
    599     }
    600 
    601     void reset() throws IOException {
    602         if (fd != null && fd.valid()) {
    603             socketClose();
    604             // Android-changed: Notified the CloseGuard object as the fd has been released.
    605             guard.close();
    606         }
    607         // Android-removed: b/26470377 Represent closed sockets with invalid fd, not null.
    608         // fd = null;
    609         super.reset();
    610     }
    611 
    612 
    613     /**
    614      * Shutdown read-half of the socket connection;
    615      */
    616     protected void shutdownInput() throws IOException {
    617       // Android-changed: b/26470377 Represent closed sockets with invalid fd, not null.
    618       if (fd != null && fd.valid()) {
    619           socketShutdown(SHUT_RD);
    620           if (socketInputStream != null) {
    621               socketInputStream.setEOF(true);
    622           }
    623           shut_rd = true;
    624       }
    625     }
    626 
    627     /**
    628      * Shutdown write-half of the socket connection;
    629      */
    630     protected void shutdownOutput() throws IOException {
    631       // Android-changed: b/26470377 Represent closed sockets with invalid fd, not null.
    632       if (fd != null && fd.valid()) {
    633           socketShutdown(SHUT_WR);
    634           shut_wr = true;
    635       }
    636     }
    637 
    638     protected boolean supportsUrgentData () {
    639         return true;
    640     }
    641 
    642     protected void sendUrgentData (int data) throws IOException {
    643         // Android-changed: b/26470377 Represent closed sockets with invalid fd, not null.
    644         if (fd == null || !fd.valid()) {
    645             throw new IOException("Socket Closed");
    646         }
    647         socketSendUrgentData (data);
    648     }
    649 
    650     /**
    651      * Cleans up if the user forgets to close it.
    652      */
    653     protected void finalize() throws IOException {
    654         // Android-added: CloseGuard
    655         if (guard != null) {
    656             guard.warnIfOpen();
    657         }
    658 
    659         close();
    660     }
    661 
    662     /*
    663      * "Acquires" and returns the FileDescriptor for this impl
    664      *
    665      * A corresponding releaseFD is required to "release" the
    666      * FileDescriptor.
    667      */
    668     FileDescriptor acquireFD() {
    669         synchronized (fdLock) {
    670             fdUseCount++;
    671             return fd;
    672         }
    673     }
    674 
    675     /*
    676      * "Release" the FileDescriptor for this impl.
    677      *
    678      * If the use count goes to -1 then the socket is closed.
    679      */
    680     void releaseFD() {
    681         synchronized (fdLock) {
    682             fdUseCount--;
    683             if (fdUseCount == -1) {
    684                 if (fd != null) {
    685                     try {
    686                         socketClose();
    687                     } catch (IOException e) {
    688                         // Android-removed: b/26470377 Some Android code doesn't expect file
    689                         // descriptor to be null. socketClose invalidates the fd by closing the fd.
    690                         // } finally {
    691                         //     fd = null;
    692                     }
    693                 }
    694             }
    695         }
    696     }
    697 
    698     public boolean isConnectionReset() {
    699         synchronized (resetLock) {
    700             return (resetState == CONNECTION_RESET);
    701         }
    702     }
    703 
    704     public boolean isConnectionResetPending() {
    705         synchronized (resetLock) {
    706             return (resetState == CONNECTION_RESET_PENDING);
    707         }
    708     }
    709 
    710     public void setConnectionReset() {
    711         synchronized (resetLock) {
    712             resetState = CONNECTION_RESET;
    713         }
    714     }
    715 
    716     public void setConnectionResetPending() {
    717         synchronized (resetLock) {
    718             if (resetState == CONNECTION_NOT_RESET) {
    719                 resetState = CONNECTION_RESET_PENDING;
    720             }
    721         }
    722 
    723     }
    724 
    725     /*
    726      * Return true if already closed or close is pending
    727      */
    728     public boolean isClosedOrPending() {
    729         /*
    730          * Lock on fdLock to ensure that we wait if a
    731          * close is in progress.
    732          */
    733         synchronized (fdLock) {
    734             // Android-changed: b/26470377 Represent closed sockets with invalid fd, not null.
    735             if (closePending || (fd == null) || !fd.valid()) {
    736                 return true;
    737             } else {
    738                 return false;
    739             }
    740         }
    741     }
    742 
    743     /*
    744      * Return the current value of SO_TIMEOUT
    745      */
    746     public int getTimeout() {
    747         return timeout;
    748     }
    749 
    750     /*
    751      * "Pre-close" a socket by dup'ing the file descriptor - this enables
    752      * the socket to be closed without releasing the file descriptor.
    753      */
    754     private void socketPreClose() throws IOException {
    755         socketClose0(true);
    756     }
    757 
    758     /*
    759      * Close the socket (and release the file descriptor).
    760      */
    761     protected void socketClose() throws IOException {
    762         socketClose0(false);
    763     }
    764 
    765     abstract void socketCreate(boolean isServer) throws IOException;
    766     abstract void socketConnect(InetAddress address, int port, int timeout)
    767         throws IOException;
    768     abstract void socketBind(InetAddress address, int port)
    769         throws IOException;
    770     abstract void socketListen(int count)
    771         throws IOException;
    772     abstract void socketAccept(SocketImpl s)
    773         throws IOException;
    774     abstract int socketAvailable()
    775         throws IOException;
    776     abstract void socketClose0(boolean useDeferredClose)
    777         throws IOException;
    778     abstract void socketShutdown(int howto)
    779         throws IOException;
    780 
    781     // Android-changed: Method signature changed, socket{Get,Set}Option work directly with Object
    782     // values.
    783     abstract void socketSetOption(int cmd, Object value) throws SocketException;
    784     abstract Object socketGetOption(int opt) throws SocketException;
    785 
    786     abstract void socketSendUrgentData(int data)
    787         throws IOException;
    788 
    789     public final static int SHUT_RD = 0;
    790     public final static int SHUT_WR = 1;
    791 }
    792