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