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