1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 2007, 2008, 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 package java.net;
27 
28 import android.system.ErrnoException;
29 
30 import java.io.IOException;
31 import java.io.FileDescriptor;
32 import java.util.Set;
33 import java.util.HashSet;
34 import java.util.Collections;
35 import libcore.io.AsynchronousCloseMonitor;
36 import libcore.io.IoBridge;
37 import libcore.io.IoUtils;
38 import libcore.io.Libcore;
39 
40 import jdk.net.*;
41 
42 import static android.system.OsConstants.AF_INET6;
43 import static android.system.OsConstants.AF_UNIX;
44 import static android.system.OsConstants.EAGAIN;
45 import static android.system.OsConstants.EBADF;
46 import static android.system.OsConstants.EINVAL;
47 import static android.system.OsConstants.MSG_OOB;
48 import static android.system.OsConstants.POLLERR;
49 import static android.system.OsConstants.POLLIN;
50 import static android.system.OsConstants.SOCK_DGRAM;
51 import static android.system.OsConstants.SOCK_STREAM;
52 import static android.system.OsConstants.SHUT_RDWR;
53 import static sun.net.ExtendedOptionsImpl.*;
54 
55 // Android-changed: Rewritten to use android.system POSIX calls and assume AF_INET6.
56 /*
57  * On Unix systems we simply delegate to native methods.
58  *
59  * @author Chris Hegarty
60  */
61 
62 class PlainSocketImpl extends AbstractPlainSocketImpl
63 {
64     /**
65      * Constructs an empty instance.
66      */
PlainSocketImpl()67     PlainSocketImpl() {
68         this(new FileDescriptor());
69     }
70 
71     /**
72      * Constructs an instance with the given file descriptor.
73      */
PlainSocketImpl(FileDescriptor fd)74     PlainSocketImpl(FileDescriptor fd) {
75         this.fd = fd;
76     }
77 
setOption(SocketOption<T> name, T value)78     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
79         if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
80             super.setOption(name, value);
81         } else {
82             if (isClosedOrPending()) {
83                 throw new SocketException("Socket closed");
84             }
85             checkSetOptionPermission(name);
86             checkValueType(value, SocketFlow.class);
87             setFlowOption(getFileDescriptor(), (SocketFlow)value);
88         }
89     }
90 
getOption(SocketOption<T> name)91     protected <T> T getOption(SocketOption<T> name) throws IOException {
92         if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
93             return super.getOption(name);
94         }
95         if (isClosedOrPending()) {
96             throw new SocketException("Socket closed");
97         }
98         checkGetOptionPermission(name);
99         SocketFlow flow = SocketFlow.create();
100         getFlowOption(getFileDescriptor(), flow);
101         return (T)flow;
102     }
103 
socketSetOption(int opt, Object val)104     protected void socketSetOption(int opt, Object val) throws SocketException {
105         try {
106             socketSetOption0(opt, val);
107         } catch (SocketException se) {
108             if (socket == null || !socket.isConnected())
109                 throw se;
110         }
111     }
112 
socketCreate(boolean isStream)113     void socketCreate(boolean isStream) throws IOException {
114         // The fd object must not change after calling bind, because we rely on this undocumented
115         // behaviour. See libcore.java.net.SocketTest#testFileDescriptorStaysSame.
116         fd.setInt$(IoBridge.socket(AF_INET6, isStream ? SOCK_STREAM : SOCK_DGRAM, 0).getInt$());
117 
118         if (serverSocket != null) {
119             IoUtils.setBlocking(fd, false);
120             IoBridge.setSocketOption(fd, SO_REUSEADDR, true);
121         }
122     }
123 
socketConnect(InetAddress address, int port, int timeout)124     void socketConnect(InetAddress address, int port, int timeout) throws IOException {
125         if (fd == null || !fd.valid()) {
126             throw new SocketException("Socket closed");
127         }
128 
129         IoBridge.connect(fd, address, port, timeout);
130 
131         this.address = address;
132         this.port = port;
133 
134         if (localport == 0) {
135             // If socket is pending close, fd becomes an AF_UNIX socket and calling
136             // getLocalInetSocketAddress will fail.
137             // http://b/34645743
138             if (!isClosedOrPending()) {
139                 localport = IoBridge.getLocalInetSocketAddress(fd).getPort();
140             }
141         }
142     }
143 
socketBind(InetAddress address, int port)144     void socketBind(InetAddress address, int port) throws IOException {
145         if (fd == null || !fd.valid()) {
146             throw new SocketException("Socket closed");
147         }
148 
149         IoBridge.bind(fd, address, port);
150 
151         this.address = address;
152         if (port == 0) {
153             // Now that we're a connected socket, let's extract the port number that the system
154             // chose for us and store it in the Socket object.
155             localport = IoBridge.getLocalInetSocketAddress(fd).getPort();
156         } else {
157             localport = port;
158         }
159     }
160 
socketListen(int count)161     void socketListen(int count) throws IOException {
162         if (fd == null || !fd.valid()) {
163             throw new SocketException("Socket closed");
164         }
165 
166         try {
167             Libcore.os.listen(fd, count);
168         } catch (ErrnoException errnoException) {
169             throw errnoException.rethrowAsSocketException();
170         }
171     }
172 
socketAccept(SocketImpl s)173     void socketAccept(SocketImpl s) throws IOException {
174         if (fd == null || !fd.valid()) {
175             throw new SocketException("Socket closed");
176         }
177 
178         // poll() with a timeout of 0 means "poll for zero millis", but a Socket timeout == 0 means
179         // "wait forever". When timeout == 0 we pass -1 to poll.
180         if (timeout <= 0) {
181             IoBridge.poll(fd, POLLIN | POLLERR, -1);
182         } else {
183             IoBridge.poll(fd, POLLIN | POLLERR, timeout);
184         }
185 
186         InetSocketAddress peerAddress = new InetSocketAddress();
187         try {
188             FileDescriptor newfd = Libcore.os.accept(fd, peerAddress);
189 
190             s.fd.setInt$(newfd.getInt$());
191             s.address = peerAddress.getAddress();
192             s.port = peerAddress.getPort();
193         } catch (ErrnoException errnoException) {
194             if (errnoException.errno == EAGAIN) {
195                 throw new SocketTimeoutException(errnoException);
196             } else if (errnoException.errno == EINVAL || errnoException.errno == EBADF) {
197                 throw new SocketException("Socket closed");
198             }
199             errnoException.rethrowAsSocketException();
200         }
201 
202         s.localport = IoBridge.getLocalInetSocketAddress(s.fd).getPort();
203     }
204 
socketAvailable()205     int socketAvailable() throws IOException {
206         return IoBridge.available(fd);
207     }
208 
socketClose0(boolean useDeferredClose)209     void socketClose0(boolean useDeferredClose) throws IOException {
210         if (fd == null || !fd.valid()) {
211             throw new SocketException("socket already closed");
212         }
213 
214         FileDescriptor markerFD = null;
215         if (useDeferredClose) {
216             markerFD = getMarkerFD();
217         }
218 
219         if (useDeferredClose && markerFD != null) {
220             try {
221                 Libcore.os.dup2(markerFD, fd.getInt$());
222                 Libcore.os.close(markerFD);
223 
224                 // This effectively closes the socket, needs to signal threads that blocks on this
225                 // file descriptor.
226                 AsynchronousCloseMonitor.signalBlockedThreads(fd);
227             } catch (ErrnoException errnoException) {
228                 // close should not throw
229             }
230         } else {
231             // If requested or a markerFD cannot be created, a non-deferred close is performed
232             // instead.
233             IoBridge.closeAndSignalBlockedThreads(fd);
234         }
235     }
236 
237     /*
238      * Create the marker file descriptor by establishing a loopback connection which we shutdown but
239      * do not close the fd. The result is an fd that can be used for read/write.
240      *
241      * The purpose is to keep hold of the raw fd handle until we are sure it is not used in any
242      * thread. Otherwise if we close the file descriptor directly, the system might reuse the raw fd
243      * number and threads holding old fd value might behave incorrectly.
244      */
getMarkerFD()245     private FileDescriptor getMarkerFD() throws SocketException {
246         FileDescriptor fd1 = new FileDescriptor();
247         FileDescriptor fd2 = new FileDescriptor();
248         try {
249             Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd1, fd2);
250 
251             // Shutdown fd1, any reads to this fd will get EOF; any writes will get an error.
252             Libcore.os.shutdown(fd1, SHUT_RDWR);
253             Libcore.os.close(fd2);
254         } catch (ErrnoException errnoException) {
255             // We might have reached the maximum file descriptor number and socketpair(2) would
256             // fail. In this case, return null and let caller to fall back to an alternative method
257             // that does not allocate more file descriptors.
258             return null;
259         }
260         return fd1;
261     }
262 
socketShutdown(int howto)263     void socketShutdown(int howto) throws IOException {
264         try {
265             Libcore.os.shutdown(fd, howto);
266         } catch (ErrnoException errnoException) {
267             throw errnoException.rethrowAsIOException();
268         }
269     }
270 
socketSetOption0(int cmd, Object value)271     void socketSetOption0(int cmd, Object value) throws SocketException {
272         // OpenJDK does not set SO_TIMEOUT on Linux.
273         if (cmd == SO_TIMEOUT) {
274             return;
275         }
276 
277         IoBridge.setSocketOption(fd, cmd, value);
278     }
279 
socketGetOption(int opt)280     Object socketGetOption(int opt) throws SocketException {
281         return IoBridge.getSocketOption(fd, opt);
282     }
283 
socketSendUrgentData(int data)284     void socketSendUrgentData(int data) throws IOException {
285         if (fd == null || !fd.valid()) {
286             throw new SocketException("Socket closed");
287         }
288 
289         try {
290             byte[] buffer = new byte[] { (byte) data };
291             Libcore.os.sendto(fd, buffer, 0, 1, MSG_OOB, null, 0);
292         } catch (ErrnoException errnoException) {
293             throw errnoException.rethrowAsSocketException();
294         }
295     }
296 
297 }
298