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      */
create(boolean stream)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-changed: Closed sockets use an invalid fd, not null. b/26470377
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      */
connect(String host, int port)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      */
connect(InetAddress address, int port)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      */
connect(SocketAddress address, int timeout)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 
connectToAddress(InetAddress address, int port, int timeout)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 
setOption(int opt, Object val)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     }
getOption(int opt)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 
doConnect(InetAddress address, int port, int timeout)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      */
bind(InetAddress address, int lport)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      */
listen(int count)438     protected synchronized void listen(int count) throws IOException {
439         socketListen(count);
440     }
441 
442     /**
443      * Accepts connections.
444      * @param s the connection
445      */
accept(SocketImpl s)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      */
getInputStream()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 
setInputStream(SocketInputStream in)472     void setInputStream(SocketInputStream in) {
473         socketInputStream = in;
474     }
475 
476     /**
477      * Gets an OutputStream for this socket.
478      */
getOutputStream()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     // Android-removed: this.fd is maintained by the concrete implementation.
492     /*
493     void setFileDescriptor(FileDescriptor fd) {
494         this.fd = fd;
495     }
496     */
497 
setAddress(InetAddress address)498     void setAddress(InetAddress address) {
499         this.address = address;
500     }
501 
setPort(int port)502     void setPort(int port) {
503         this.port = port;
504     }
505 
setLocalPort(int localport)506     void setLocalPort(int localport) {
507         this.localport = localport;
508     }
509 
510     /**
511      * Returns the number of bytes that can be read without blocking.
512      */
available()513     protected synchronized int available() throws IOException {
514         if (isClosedOrPending()) {
515             throw new IOException("Stream closed.");
516         }
517 
518         /*
519          * If connection has been reset or shut down for input, then return 0
520          * to indicate there are no buffered bytes.
521          */
522         if (isConnectionReset() || shut_rd) {
523             return 0;
524         }
525 
526         /*
527          * If no bytes available and we were previously notified
528          * of a connection reset then we move to the reset state.
529          *
530          * If are notified of a connection reset then check
531          * again if there are bytes buffered on the socket.
532          */
533         int n = 0;
534         try {
535             n = socketAvailable();
536             if (n == 0 && isConnectionResetPending()) {
537                 setConnectionReset();
538             }
539         } catch (ConnectionResetException exc1) {
540             setConnectionResetPending();
541             try {
542                 n = socketAvailable();
543                 if (n == 0) {
544                     setConnectionReset();
545                 }
546             } catch (ConnectionResetException exc2) {
547             }
548         }
549         return n;
550     }
551 
552     /**
553      * Closes the socket.
554      */
close()555     protected void close() throws IOException {
556         synchronized(fdLock) {
557             if (fd != null && fd.valid()) {
558                 if (!stream) {
559                     ResourceManager.afterUdpClose();
560                 }
561                 // Android-changed: Socket should be untagged before the preclose.
562                 // After preclose, socket will dup2-ed to marker_fd, therefore, it won't describe
563                 // the same file.  If closingPending is true, then the socket has been preclosed.
564                 //
565                 // Also, close the CloseGuard when the #close is called.
566                 if (!closePending) {
567                     closePending = true;
568                     guard.close();
569 
570                     if (fdUseCount == 0) {
571                         /*
572                          * We close the FileDescriptor in two-steps - first the
573                          * "pre-close" which closes the socket but doesn't
574                          * release the underlying file descriptor. This operation
575                          * may be lengthy due to untransmitted data and a long
576                          * linger interval. Once the pre-close is done we do the
577                          * actual socket to release the fd.
578                          */
579                         try {
580                             socketPreClose();
581                         } finally {
582                             socketClose();
583                         }
584                         // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
585                         // socketClose invalidates the fd by closing the fd.
586                         // fd = null;
587                         return;
588                     } else {
589                         /*
590                          * If a thread has acquired the fd and a close
591                          * isn't pending then use a deferred close.
592                          * Also decrement fdUseCount to signal the last
593                          * thread that releases the fd to close it.
594                          */
595                         fdUseCount--;
596                         socketPreClose();
597                     }
598                 }
599             }
600         }
601     }
602 
reset()603     void reset() throws IOException {
604         if (fd != null && fd.valid()) {
605             socketClose();
606             // Android-changed: Notified the CloseGuard object as the fd has been released.
607             guard.close();
608         }
609         // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
610         // fd = null;
611         super.reset();
612     }
613 
614 
615     /**
616      * Shutdown read-half of the socket connection;
617      */
shutdownInput()618     protected void shutdownInput() throws IOException {
619       // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
620       if (fd != null && fd.valid()) {
621           socketShutdown(SHUT_RD);
622           if (socketInputStream != null) {
623               socketInputStream.setEOF(true);
624           }
625           shut_rd = true;
626       }
627     }
628 
629     /**
630      * Shutdown write-half of the socket connection;
631      */
shutdownOutput()632     protected void shutdownOutput() throws IOException {
633       // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
634       if (fd != null && fd.valid()) {
635           socketShutdown(SHUT_WR);
636           shut_wr = true;
637       }
638     }
639 
supportsUrgentData()640     protected boolean supportsUrgentData () {
641         return true;
642     }
643 
sendUrgentData(int data)644     protected void sendUrgentData (int data) throws IOException {
645         // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
646         if (fd == null || !fd.valid()) {
647             throw new IOException("Socket Closed");
648         }
649         socketSendUrgentData (data);
650     }
651 
652     /**
653      * Cleans up if the user forgets to close it.
654      */
finalize()655     protected void finalize() throws IOException {
656         // Android-added: CloseGuard.
657         if (guard != null) {
658             guard.warnIfOpen();
659         }
660 
661         close();
662     }
663 
664     /*
665      * "Acquires" and returns the FileDescriptor for this impl
666      *
667      * A corresponding releaseFD is required to "release" the
668      * FileDescriptor.
669      */
acquireFD()670     FileDescriptor acquireFD() {
671         synchronized (fdLock) {
672             fdUseCount++;
673             return fd;
674         }
675     }
676 
677     /*
678      * "Release" the FileDescriptor for this impl.
679      *
680      * If the use count goes to -1 then the socket is closed.
681      */
releaseFD()682     void releaseFD() {
683         synchronized (fdLock) {
684             fdUseCount--;
685             if (fdUseCount == -1) {
686                 if (fd != null) {
687                     try {
688                         socketClose();
689                     } catch (IOException e) {
690                         // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
691                         // socketClose invalidates the fd by closing the fd.
692                         // } finally {
693                         //     fd = null;
694                     }
695                 }
696             }
697         }
698     }
699 
isConnectionReset()700     public boolean isConnectionReset() {
701         synchronized (resetLock) {
702             return (resetState == CONNECTION_RESET);
703         }
704     }
705 
isConnectionResetPending()706     public boolean isConnectionResetPending() {
707         synchronized (resetLock) {
708             return (resetState == CONNECTION_RESET_PENDING);
709         }
710     }
711 
setConnectionReset()712     public void setConnectionReset() {
713         synchronized (resetLock) {
714             resetState = CONNECTION_RESET;
715         }
716     }
717 
setConnectionResetPending()718     public void setConnectionResetPending() {
719         synchronized (resetLock) {
720             if (resetState == CONNECTION_NOT_RESET) {
721                 resetState = CONNECTION_RESET_PENDING;
722             }
723         }
724 
725     }
726 
727     /*
728      * Return true if already closed or close is pending
729      */
isClosedOrPending()730     public boolean isClosedOrPending() {
731         /*
732          * Lock on fdLock to ensure that we wait if a
733          * close is in progress.
734          */
735         synchronized (fdLock) {
736             // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
737             if (closePending || (fd == null) || !fd.valid()) {
738                 return true;
739             } else {
740                 return false;
741             }
742         }
743     }
744 
745     /*
746      * Return the current value of SO_TIMEOUT
747      */
getTimeout()748     public int getTimeout() {
749         return timeout;
750     }
751 
752     /*
753      * "Pre-close" a socket by dup'ing the file descriptor - this enables
754      * the socket to be closed without releasing the file descriptor.
755      */
socketPreClose()756     private void socketPreClose() throws IOException {
757         socketClose0(true);
758     }
759 
760     /*
761      * Close the socket (and release the file descriptor).
762      */
socketClose()763     protected void socketClose() throws IOException {
764         socketClose0(false);
765     }
766 
socketCreate(boolean isServer)767     abstract void socketCreate(boolean isServer) throws IOException;
socketConnect(InetAddress address, int port, int timeout)768     abstract void socketConnect(InetAddress address, int port, int timeout)
769         throws IOException;
socketBind(InetAddress address, int port)770     abstract void socketBind(InetAddress address, int port)
771         throws IOException;
socketListen(int count)772     abstract void socketListen(int count)
773         throws IOException;
socketAccept(SocketImpl s)774     abstract void socketAccept(SocketImpl s)
775         throws IOException;
socketAvailable()776     abstract int socketAvailable()
777         throws IOException;
socketClose0(boolean useDeferredClose)778     abstract void socketClose0(boolean useDeferredClose)
779         throws IOException;
socketShutdown(int howto)780     abstract void socketShutdown(int howto)
781         throws IOException;
782 
783     // Android-changed: Method signature changes.
784     // socket{Get,Set}Option work directly with Object values.
socketSetOption(int cmd, Object value)785     abstract void socketSetOption(int cmd, Object value) throws SocketException;
socketGetOption(int opt)786     abstract Object socketGetOption(int opt) throws SocketException;
787 
socketSendUrgentData(int data)788     abstract void socketSendUrgentData(int data)
789         throws IOException;
790 
791     public final static int SHUT_RD = 0;
792     public final static int SHUT_WR = 1;
793 }
794