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