|  | /* | 
|  | * Copyright (C) 2014 The Android Open Source Project | 
|  | * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. | 
|  | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
|  | * | 
|  | * This code is free software; you can redistribute it and/or modify it | 
|  | * under the terms of the GNU General Public License version 2 only, as | 
|  | * published by the Free Software Foundation.  Oracle designates this | 
|  | * particular file as subject to the "Classpath" exception as provided | 
|  | * by Oracle in the LICENSE file that accompanied this code. | 
|  | * | 
|  | * This code is distributed in the hope that it will be useful, but WITHOUT | 
|  | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
|  | * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
|  | * version 2 for more details (a copy is included in the LICENSE file that | 
|  | * accompanied this code). | 
|  | * | 
|  | * You should have received a copy of the GNU General Public License version | 
|  | * 2 along with this work; if not, write to the Free Software Foundation, | 
|  | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
|  | * | 
|  | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
|  | * or visit www.oracle.com if you need additional information or have any | 
|  | * questions. | 
|  | */ | 
|  | package java.net; | 
|  |  | 
|  | import android.system.ErrnoException; | 
|  |  | 
|  | import java.io.IOException; | 
|  | import java.io.FileDescriptor; | 
|  | import java.util.Set; | 
|  | import java.util.HashSet; | 
|  | import java.util.Collections; | 
|  | import libcore.io.AsynchronousCloseMonitor; | 
|  | import libcore.io.IoBridge; | 
|  | import libcore.io.IoUtils; | 
|  | import libcore.io.Libcore; | 
|  |  | 
|  | import jdk.net.*; | 
|  |  | 
|  | import static android.system.OsConstants.AF_INET6; | 
|  | import static android.system.OsConstants.AF_UNIX; | 
|  | import static android.system.OsConstants.EAGAIN; | 
|  | import static android.system.OsConstants.EBADF; | 
|  | import static android.system.OsConstants.EINVAL; | 
|  | import static android.system.OsConstants.MSG_OOB; | 
|  | import static android.system.OsConstants.POLLERR; | 
|  | import static android.system.OsConstants.POLLIN; | 
|  | import static android.system.OsConstants.SOCK_DGRAM; | 
|  | import static android.system.OsConstants.SOCK_STREAM; | 
|  | import static android.system.OsConstants.SHUT_RDWR; | 
|  | import static sun.net.ExtendedOptionsImpl.*; | 
|  |  | 
|  | // Android-changed: Rewritten to use android.system POSIX calls and assume AF_INET6. | 
|  | /* | 
|  | * On Unix systems we simply delegate to native methods. | 
|  | * | 
|  | * @author Chris Hegarty | 
|  | */ | 
|  |  | 
|  | class PlainSocketImpl extends AbstractPlainSocketImpl | 
|  | { | 
|  | // Android-removed: Android doesn't need to call native initProto. | 
|  | /* | 
|  | static { | 
|  | initProto(); | 
|  | } | 
|  | */ | 
|  |  | 
|  | /** | 
|  | * Constructs an empty instance. | 
|  | */ | 
|  | PlainSocketImpl() { | 
|  | // Android-changed: Let PlainSocketImpl construct its own FileDescriptor. | 
|  | this.fd = new FileDescriptor(); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Constructs an instance with the given file descriptor. | 
|  | */ | 
|  | // Android-removed: Let PlainSocketImpl construct its own FileDescriptor. | 
|  | /* | 
|  | PlainSocketImpl(FileDescriptor fd) { | 
|  | this.fd = fd; | 
|  | } | 
|  | */ | 
|  |  | 
|  | protected <T> void setOption(SocketOption<T> name, T value) throws IOException { | 
|  | if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { | 
|  | super.setOption(name, value); | 
|  | } else { | 
|  | if (isClosedOrPending()) { | 
|  | throw new SocketException("Socket closed"); | 
|  | } | 
|  | checkSetOptionPermission(name); | 
|  | checkValueType(value, SocketFlow.class); | 
|  | setFlowOption(getFileDescriptor(), (SocketFlow)value); | 
|  | } | 
|  | } | 
|  |  | 
|  | protected <T> T getOption(SocketOption<T> name) throws IOException { | 
|  | if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { | 
|  | return super.getOption(name); | 
|  | } | 
|  | if (isClosedOrPending()) { | 
|  | throw new SocketException("Socket closed"); | 
|  | } | 
|  | checkGetOptionPermission(name); | 
|  | SocketFlow flow = SocketFlow.create(); | 
|  | getFlowOption(getFileDescriptor(), flow); | 
|  | return (T)flow; | 
|  | } | 
|  |  | 
|  | // BEGIN Android-changed: Rewrote on top of Libcore.io. | 
|  | protected void socketSetOption(int opt, Object val) throws SocketException { | 
|  | try { | 
|  | socketSetOption0(opt, val); | 
|  | } catch (SocketException se) { | 
|  | if (socket == null || !socket.isConnected()) | 
|  | throw se; | 
|  | } | 
|  | } | 
|  |  | 
|  | void socketCreate(boolean isStream) throws IOException { | 
|  | // The fd object must not change after calling bind, because we rely on this undocumented | 
|  | // behaviour. See libcore.java.net.SocketTest#testFileDescriptorStaysSame. | 
|  | fd.setInt$(IoBridge.socket(AF_INET6, isStream ? SOCK_STREAM : SOCK_DGRAM, 0).getInt$()); | 
|  | IoUtils.setFdOwner(fd, this); | 
|  |  | 
|  | if (serverSocket != null) { | 
|  | IoUtils.setBlocking(fd, false); | 
|  | IoBridge.setSocketOption(fd, SO_REUSEADDR, true); | 
|  | } | 
|  | } | 
|  |  | 
|  | void socketConnect(InetAddress address, int port, int timeout) throws IOException { | 
|  | if (fd == null || !fd.valid()) { | 
|  | throw new SocketException("Socket closed"); | 
|  | } | 
|  |  | 
|  | IoBridge.connect(fd, address, port, timeout); | 
|  |  | 
|  | this.address = address; | 
|  | this.port = port; | 
|  |  | 
|  | if (localport == 0) { | 
|  | // If socket is pending close, fd becomes an AF_UNIX socket and calling | 
|  | // getLocalInetSocketAddress will fail. | 
|  | // http://b/34645743 | 
|  | if (!isClosedOrPending()) { | 
|  | localport = IoBridge.getLocalInetSocketAddress(fd).getPort(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void socketBind(InetAddress address, int port) throws IOException { | 
|  | if (fd == null || !fd.valid()) { | 
|  | throw new SocketException("Socket closed"); | 
|  | } | 
|  |  | 
|  | IoBridge.bind(fd, address, port); | 
|  |  | 
|  | this.address = address; | 
|  | if (port == 0) { | 
|  | // Now that we're a connected socket, let's extract the port number that the system | 
|  | // chose for us and store it in the Socket object. | 
|  | localport = IoBridge.getLocalInetSocketAddress(fd).getPort(); | 
|  | } else { | 
|  | localport = port; | 
|  | } | 
|  | } | 
|  |  | 
|  | void socketListen(int count) throws IOException { | 
|  | if (fd == null || !fd.valid()) { | 
|  | throw new SocketException("Socket closed"); | 
|  | } | 
|  |  | 
|  | try { | 
|  | Libcore.os.listen(fd, count); | 
|  | } catch (ErrnoException errnoException) { | 
|  | throw errnoException.rethrowAsSocketException(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void socketAccept(SocketImpl s) throws IOException { | 
|  | if (fd == null || !fd.valid()) { | 
|  | throw new SocketException("Socket closed"); | 
|  | } | 
|  |  | 
|  | // poll() with a timeout of 0 means "poll for zero millis", but a Socket timeout == 0 means | 
|  | // "wait forever". When timeout == 0 we pass -1 to poll. | 
|  | if (timeout <= 0) { | 
|  | IoBridge.poll(fd, POLLIN | POLLERR, -1); | 
|  | } else { | 
|  | IoBridge.poll(fd, POLLIN | POLLERR, timeout); | 
|  | } | 
|  |  | 
|  | InetSocketAddress peerAddress = new InetSocketAddress(); | 
|  | try { | 
|  | FileDescriptor newfd = Libcore.os.accept(fd, peerAddress); | 
|  |  | 
|  | s.fd.setInt$(newfd.getInt$()); | 
|  | IoUtils.setFdOwner(s.fd, s); | 
|  | s.address = peerAddress.getAddress(); | 
|  | s.port = peerAddress.getPort(); | 
|  | } catch (ErrnoException errnoException) { | 
|  | if (errnoException.errno == EAGAIN) { | 
|  | SocketTimeoutException e = new SocketTimeoutException(); | 
|  | e.initCause(errnoException); | 
|  | throw e; | 
|  | } else if (errnoException.errno == EINVAL || errnoException.errno == EBADF) { | 
|  | throw new SocketException("Socket closed"); | 
|  | } | 
|  | errnoException.rethrowAsSocketException(); | 
|  | } | 
|  |  | 
|  | s.localport = IoBridge.getLocalInetSocketAddress(s.fd).getPort(); | 
|  | } | 
|  |  | 
|  | int socketAvailable() throws IOException { | 
|  | return IoBridge.available(fd); | 
|  | } | 
|  |  | 
|  | void socketClose0(boolean useDeferredClose) throws IOException { | 
|  | if (fd == null || !fd.valid()) { | 
|  | throw new SocketException("socket already closed"); | 
|  | } | 
|  |  | 
|  | FileDescriptor markerFD = null; | 
|  | if (useDeferredClose) { | 
|  | markerFD = getMarkerFD(); | 
|  | } | 
|  |  | 
|  | if (useDeferredClose && markerFD != null) { | 
|  | try { | 
|  | Libcore.os.dup2(markerFD, fd.getInt$()); | 
|  | Libcore.os.close(markerFD); | 
|  |  | 
|  | // This effectively closes the socket, needs to signal threads that blocks on this | 
|  | // file descriptor. | 
|  | AsynchronousCloseMonitor.signalBlockedThreads(fd); | 
|  | } catch (ErrnoException errnoException) { | 
|  | // close should not throw | 
|  | } | 
|  | } else { | 
|  | // If requested or a markerFD cannot be created, a non-deferred close is performed | 
|  | // instead. | 
|  | IoBridge.closeAndSignalBlockedThreads(fd); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Create the marker file descriptor by establishing a loopback connection which we shutdown but | 
|  | * do not close the fd. The result is an fd that can be used for read/write. | 
|  | * | 
|  | * The purpose is to keep hold of the raw fd handle until we are sure it is not used in any | 
|  | * thread. Otherwise if we close the file descriptor directly, the system might reuse the raw fd | 
|  | * number and threads holding old fd value might behave incorrectly. | 
|  | */ | 
|  | private FileDescriptor getMarkerFD() throws SocketException { | 
|  | FileDescriptor fd1 = new FileDescriptor(); | 
|  | FileDescriptor fd2 = new FileDescriptor(); | 
|  | try { | 
|  | Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd1, fd2); | 
|  |  | 
|  | // Shutdown fd1, any reads to this fd will get EOF; any writes will get an error. | 
|  | Libcore.os.shutdown(fd1, SHUT_RDWR); | 
|  | Libcore.os.close(fd2); | 
|  | } catch (ErrnoException errnoException) { | 
|  | // We might have reached the maximum file descriptor number and socketpair(2) would | 
|  | // fail. In this case, return null and let caller to fall back to an alternative method | 
|  | // that does not allocate more file descriptors. | 
|  | return null; | 
|  | } | 
|  | return fd1; | 
|  | } | 
|  |  | 
|  | void socketShutdown(int howto) throws IOException { | 
|  | try { | 
|  | Libcore.os.shutdown(fd, howto); | 
|  | } catch (ErrnoException errnoException) { | 
|  | throw errnoException.rethrowAsIOException(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void socketSetOption0(int cmd, Object value) throws SocketException { | 
|  | // OpenJDK does not set SO_TIMEOUT on Linux. | 
|  | if (cmd == SO_TIMEOUT) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | IoBridge.setSocketOption(fd, cmd, value); | 
|  | } | 
|  |  | 
|  | Object socketGetOption(int opt) throws SocketException { | 
|  | return IoBridge.getSocketOption(fd, opt); | 
|  | } | 
|  |  | 
|  | void socketSendUrgentData(int data) throws IOException { | 
|  | if (fd == null || !fd.valid()) { | 
|  | throw new SocketException("Socket closed"); | 
|  | } | 
|  |  | 
|  | try { | 
|  | byte[] buffer = new byte[] { (byte) data }; | 
|  | Libcore.os.sendto(fd, buffer, 0, 1, MSG_OOB, null, 0); | 
|  | } catch (ErrnoException errnoException) { | 
|  | throw errnoException.rethrowAsSocketException(); | 
|  | } | 
|  | } | 
|  | // END Android-changed: Rewrote on top of Libcore.io. | 
|  |  | 
|  | } |