10b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes/* 20b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * Copyright (C) 2011 The Android Open Source Project 30b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * 40b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 50b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * you may not use this file except in compliance with the License. 60b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * You may obtain a copy of the License at 70b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * 80b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 90b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * 100b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * Unless required by applicable law or agreed to in writing, software 110b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 120b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * See the License for the specific language governing permissions and 140b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * limitations under the License. 150b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes */ 160b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 170b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughespackage libcore.io; 180b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 1941d8acb87dd1b722cf54e4c64e72c6a13688a849Elliott Hughesimport android.system.ErrnoException; 205d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.StructGroupReq; 215d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.StructGroupSourceReq; 225d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.StructLinger; 235d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.StructPollfd; 245d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.StructTimeval; 255d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.util.MutableInt; 260b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.io.FileDescriptor; 270b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.io.FileNotFoundException; 280b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.io.IOException; 290b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.BindException; 300b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.ConnectException; 310b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.DatagramPacket; 320b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.Inet4Address; 330b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.Inet6Address; 340b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.InetAddress; 350b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.InetSocketAddress; 360b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.NetworkInterface; 370b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.PortUnreachableException; 380b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.SocketAddress; 390b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.SocketException; 400b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.SocketOptions; 410b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.SocketTimeoutException; 420b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.net.UnknownHostException; 430b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.nio.ByteBuffer; 440b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport java.util.Arrays; 455d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport static android.system.OsConstants.*; 460b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 470b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes/** 480b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * Implements java.io/java.net/java.nio semantics in terms of the underlying POSIX system calls. 490b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes */ 500b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughespublic final class IoBridge { 510b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 520b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes private IoBridge() { 530b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 540b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 550b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static int available(FileDescriptor fd) throws IOException { 560b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 570b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes MutableInt available = new MutableInt(0); 582ca11d6eae460f94bc42bc2e453fac93f4b94eb0Jesse Wilson Libcore.os.ioctlInt(fd, FIONREAD, available); 590b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (available.value < 0) { 600b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // If the fd refers to a regular file, the result is the difference between 610b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // the file size and the file position. This may be negative if the position 620b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // is past the end of the file. If the fd refers to a special file masquerading 630b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // as a regular file, the result may be negative because the special file 640b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // may appear to have zero size and yet a previous read call may have 650b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // read some amount of data and caused the file position to be advanced. 660b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes available.value = 0; 670b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 680b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return available.value; 690b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 700b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (errnoException.errno == ENOTTY) { 710b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // The fd is unwilling to opine about its read buffer. 720b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return 0; 730b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 740b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw errnoException.rethrowAsIOException(); 750b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 760b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 770b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 780b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 790b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static void bind(FileDescriptor fd, InetAddress address, int port) throws SocketException { 80df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller if (address instanceof Inet6Address) { 81df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller Inet6Address inet6Address = (Inet6Address) address; 82df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller if (inet6Address.getScopeId() == 0 && inet6Address.isLinkLocalAddress()) { 83df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller // Linux won't let you bind a link-local address without a scope id. 84df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller // Find one. 85df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller NetworkInterface nif = NetworkInterface.getByInetAddress(address); 86df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller if (nif == null) { 87df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller throw new SocketException("Can't bind to a link-local address without a scope id: " + address); 88df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller } 89df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller try { 90df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller address = Inet6Address.getByAddress(address.getHostName(), address.getAddress(), nif.getIndex()); 91df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller } catch (UnknownHostException ex) { 92df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller throw new AssertionError(ex); // Can't happen. 93df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller } 940b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 950b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 960b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 970b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.bind(fd, address, port); 980b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 990b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw new BindException(errnoException.getMessage(), errnoException); 1000b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 1010b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 1020b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 1030b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 1040b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes /** 1050b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * Connects socket 'fd' to 'inetAddress' on 'port', with no timeout. The lack of a timeout 1060b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * means this method won't throw SocketTimeoutException. 1070b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes */ 108933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller public static void connect(FileDescriptor fd, InetAddress inetAddress, int port) throws SocketException { 1090b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 110933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller IoBridge.connect(fd, inetAddress, port, 0); 1110b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (SocketTimeoutException ex) { 1120b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw new AssertionError(ex); // Can't happen for a connect without a timeout. 1130b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 1140b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 1150b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 1160b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes /** 1170b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * Connects socket 'fd' to 'inetAddress' on 'port', with a the given 'timeoutMs'. 1180b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * Use timeoutMs == 0 for a blocking connect with no timeout. 1190b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes */ 120933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller public static void connect(FileDescriptor fd, InetAddress inetAddress, int port, int timeoutMs) throws SocketException, SocketTimeoutException { 1210b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 122933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller connectErrno(fd, inetAddress, port, timeoutMs); 1230b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 1240b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw new ConnectException(connectDetail(inetAddress, port, timeoutMs, errnoException), errnoException); 1250b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (SocketException ex) { 1260b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw ex; // We don't want to doubly wrap these. 1270b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (SocketTimeoutException ex) { 1280b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw ex; // We don't want to doubly wrap these. 1290b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (IOException ex) { 1300b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw new SocketException(ex); 1310b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 1320b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 1330b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 134933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller private static void connectErrno(FileDescriptor fd, InetAddress inetAddress, int port, int timeoutMs) throws ErrnoException, IOException { 1350b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // With no timeout, just call connect(2) directly. 1360b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (timeoutMs == 0) { 1370b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.connect(fd, inetAddress, port); 138933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller return; 1390b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 1400b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 141796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes // For connect with a timeout, we: 142796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes // 1. set the socket to non-blocking, 143796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes // 2. connect(2), 144796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes // 3. loop using poll(2) to decide whether we're connected, whether we should keep 145796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes // waiting, or whether we've seen a permanent failure and should give up, 146796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes // 4. set the socket back to blocking. 147796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes 148796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes // 1. set the socket to non-blocking. 1490b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoUtils.setBlocking(fd, false); 150796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes 151796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes // 2. call connect(2) non-blocking. 152796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes long finishTimeMs = System.currentTimeMillis() + timeoutMs; 1530b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 154796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes Libcore.os.connect(fd, inetAddress, port); 155796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes IoUtils.setBlocking(fd, true); // 4. set the socket back to blocking. 156933fbbf606268eec9fc430632b8bca7002a833b3Neil Fuller return; // We connected immediately. 157796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes } catch (ErrnoException errnoException) { 158796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes if (errnoException.errno != EINPROGRESS) { 159796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes throw errnoException; 1600b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 161796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes // EINPROGRESS means we should keep trying... 1620b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 163796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes 164796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes // 3. loop using poll(2). 165796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes int remainingTimeoutMs; 166796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes do { 167796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes remainingTimeoutMs = (int) (finishTimeMs - System.currentTimeMillis()); 168796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes if (remainingTimeoutMs <= 0) { 169796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes throw new SocketTimeoutException(connectDetail(inetAddress, port, timeoutMs, null)); 170796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes } 171796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes } while (!IoBridge.isConnected(fd, inetAddress, port, timeoutMs, remainingTimeoutMs)); 172796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes IoUtils.setBlocking(fd, true); // 4. set the socket back to blocking. 1730b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 1740b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 1750b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes private static String connectDetail(InetAddress inetAddress, int port, int timeoutMs, ErrnoException cause) { 1760b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes String detail = "failed to connect to " + inetAddress + " (port " + port + ")"; 1770b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (timeoutMs > 0) { 1780b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes detail += " after " + timeoutMs + "ms"; 1790b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 1800b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (cause != null) { 1810b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes detail += ": " + cause.getMessage(); 1820b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 1830b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return detail; 1840b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 1850b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 186f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller /** 187f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * Closes the supplied file descriptor and sends a signal to any threads are currently blocking. 188f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * In order for the signal to be sent the blocked threads must have registered with 189f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * the AsynchronousCloseMonitor before they entered the blocking operation. 190f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * 191f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * <p>This method is a no-op if passed a {@code null} or already-closed file descriptor. 192f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller */ 193f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller public static void closeAndSignalBlockedThreads(FileDescriptor fd) throws IOException { 194f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller if (fd == null || !fd.valid()) { 1950b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 1960b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 1970b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int intFd = fd.getInt$(); 1980b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes fd.setInt$(-1); 1990b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes FileDescriptor oldFd = new FileDescriptor(); 2000b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes oldFd.setInt$(intFd); 2010b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes AsynchronousCloseMonitor.signalBlockedThreads(oldFd); 2020b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 2030b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.close(oldFd); 2040b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 2050b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // TODO: are there any cases in which we should throw? 2060b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 2070b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 2080b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 2090b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static boolean isConnected(FileDescriptor fd, InetAddress inetAddress, int port, int timeoutMs, int remainingTimeoutMs) throws IOException { 2102ca11d6eae460f94bc42bc2e453fac93f4b94eb0Jesse Wilson ErrnoException cause; 2110b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 2120b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes StructPollfd[] pollFds = new StructPollfd[] { new StructPollfd() }; 2130b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes pollFds[0].fd = fd; 2140b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes pollFds[0].events = (short) POLLOUT; 2150b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int rc = Libcore.os.poll(pollFds, remainingTimeoutMs); 2160b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (rc == 0) { 2170b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return false; // Timeout. 2180b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 2190b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int connectError = Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_ERROR); 2200b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (connectError == 0) { 2210b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return true; // Success! 2220b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 2230b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw new ErrnoException("isConnected", connectError); // The connect(2) failed. 2240b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 225796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes if (!fd.valid()) { 226796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes throw new SocketException("Socket closed"); 227796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes } 228fa542091e45db699a937c5ac0191194405107827Elliott Hughes cause = errnoException; 2290b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 2300b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes String detail = connectDetail(inetAddress, port, timeoutMs, cause); 23151f50987458f4b9c3bf3d53f829331a335f67113Elliott Hughes if (cause.errno == ETIMEDOUT) { 2320b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw new SocketTimeoutException(detail, cause); 2330b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 23451f50987458f4b9c3bf3d53f829331a335f67113Elliott Hughes throw new ConnectException(detail, cause); 2350b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 2360b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 2370b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // Socket options used by java.net but not exposed in SocketOptions. 2380b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static final int JAVA_MCAST_JOIN_GROUP = 19; 2390b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static final int JAVA_MCAST_LEAVE_GROUP = 20; 240df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller public static final int JAVA_MCAST_JOIN_SOURCE_GROUP = 21; 241df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller public static final int JAVA_MCAST_LEAVE_SOURCE_GROUP = 22; 242df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller public static final int JAVA_MCAST_BLOCK_SOURCE = 23; 243df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller public static final int JAVA_MCAST_UNBLOCK_SOURCE = 24; 2440b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static final int JAVA_IP_MULTICAST_TTL = 17; 2450b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 2460b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes /** 2470b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * java.net has its own socket options similar to the underlying Unix ones. We paper over the 2480b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * differences here. 2490b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes */ 2500b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static Object getSocketOption(FileDescriptor fd, int option) throws SocketException { 2510b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 2520b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return getSocketOptionErrno(fd, option); 2530b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 2540b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw errnoException.rethrowAsSocketException(); 2550b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 2560b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 2570b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 2589b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes private static Object getSocketOptionErrno(FileDescriptor fd, int option) throws ErrnoException, SocketException { 2590b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes switch (option) { 2600b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.IP_MULTICAST_IF: 2610b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // This is IPv4-only. 2620b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return Libcore.os.getsockoptInAddr(fd, IPPROTO_IP, IP_MULTICAST_IF); 2630b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.IP_MULTICAST_IF2: 2640b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // This is IPv6-only. 2650b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return Libcore.os.getsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF); 2660b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.IP_MULTICAST_LOOP: 2670b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // Since setting this from java.net always sets IPv4 and IPv6 to the same value, 2680b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // it doesn't matter which we return. 2690b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return booleanFromInt(Libcore.os.getsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP)); 2700b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case IoBridge.JAVA_IP_MULTICAST_TTL: 2710b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // Since setting this from java.net always sets IPv4 and IPv6 to the same value, 2720b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // it doesn't matter which we return. 2730b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return Libcore.os.getsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); 2740b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.IP_TOS: 2750b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // Since setting this from java.net always sets IPv4 and IPv6 to the same value, 2760b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // it doesn't matter which we return. 2770b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return Libcore.os.getsockoptInt(fd, IPPROTO_IPV6, IPV6_TCLASS); 2780b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_BROADCAST: 2790b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return booleanFromInt(Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_BROADCAST)); 2800b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_KEEPALIVE: 2810b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return booleanFromInt(Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_KEEPALIVE)); 2820b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_LINGER: 2830b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes StructLinger linger = Libcore.os.getsockoptLinger(fd, SOL_SOCKET, SO_LINGER); 2840b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (!linger.isOn()) { 2850b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return false; 2860b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 2870b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return linger.l_linger; 2880b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_OOBINLINE: 2890b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return booleanFromInt(Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_OOBINLINE)); 2900b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_RCVBUF: 29151cf1b49bca54ec0229a51df400ad1bee580b1bbBrian Carlstrom return Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_RCVBUF); 2920b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_REUSEADDR: 2930b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return booleanFromInt(Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_REUSEADDR)); 2940b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_SNDBUF: 2950b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_SNDBUF); 2960b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_TIMEOUT: 2970b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return (int) Libcore.os.getsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO).toMillis(); 2980b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.TCP_NODELAY: 2990b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return booleanFromInt(Libcore.os.getsockoptInt(fd, IPPROTO_TCP, TCP_NODELAY)); 3000b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes default: 3010b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw new SocketException("Unknown socket option: " + option); 3020b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 3030b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 3040b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 3050b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes private static boolean booleanFromInt(int i) { 3060b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return (i != 0); 3070b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 3080b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 3090b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes private static int booleanToInt(boolean b) { 3100b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return b ? 1 : 0; 3110b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 3120b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 3130b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes /** 3140b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * java.net has its own socket options similar to the underlying Unix ones. We paper over the 3150b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * differences here. 3160b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes */ 3170b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static void setSocketOption(FileDescriptor fd, int option, Object value) throws SocketException { 3180b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 3190b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes setSocketOptionErrno(fd, option, value); 3200b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 3210b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw errnoException.rethrowAsSocketException(); 3220b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 3230b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 3240b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 3259b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes private static void setSocketOptionErrno(FileDescriptor fd, int option, Object value) throws ErrnoException, SocketException { 3260b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes switch (option) { 3270b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.IP_MULTICAST_IF: 3280b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw new UnsupportedOperationException("Use IP_MULTICAST_IF2 on Android"); 3290b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.IP_MULTICAST_IF2: 3300b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // Although IPv6 was cleaned up to use int, IPv4 uses an ip_mreqn containing an int. 3310b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptIpMreqn(fd, IPPROTO_IP, IP_MULTICAST_IF, (Integer) value); 3320b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, (Integer) value); 3330b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3340b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.IP_MULTICAST_LOOP: 3350b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // Although IPv6 was cleaned up to use int, IPv4 multicast loopback uses a byte. 3360b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptByte(fd, IPPROTO_IP, IP_MULTICAST_LOOP, booleanToInt((Boolean) value)); 3370b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, booleanToInt((Boolean) value)); 3380b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3390b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case IoBridge.JAVA_IP_MULTICAST_TTL: 3400b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // Although IPv6 was cleaned up to use int, and IPv4 non-multicast TTL uses int, 3410b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // IPv4 multicast TTL uses a byte. 3420b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptByte(fd, IPPROTO_IP, IP_MULTICAST_TTL, (Integer) value); 3430b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (Integer) value); 3440b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3450b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.IP_TOS: 3460b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, IPPROTO_IP, IP_TOS, (Integer) value); 3470b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_TCLASS, (Integer) value); 3480b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3490b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_BROADCAST: 3500b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, SOL_SOCKET, SO_BROADCAST, booleanToInt((Boolean) value)); 3510b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3520b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_KEEPALIVE: 3530b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, SOL_SOCKET, SO_KEEPALIVE, booleanToInt((Boolean) value)); 3540b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3550b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_LINGER: 3560b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes boolean on = false; 3570b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int seconds = 0; 3580b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (value instanceof Integer) { 3590b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes on = true; 3600b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes seconds = Math.min((Integer) value, 65535); 3610b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 3620b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes StructLinger linger = new StructLinger(booleanToInt(on), seconds); 3630b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptLinger(fd, SOL_SOCKET, SO_LINGER, linger); 3640b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3650b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_OOBINLINE: 3660b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, SOL_SOCKET, SO_OOBINLINE, booleanToInt((Boolean) value)); 3670b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3680b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_RCVBUF: 3690b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, SOL_SOCKET, SO_RCVBUF, (Integer) value); 3700b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3710b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_REUSEADDR: 3720b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, SOL_SOCKET, SO_REUSEADDR, booleanToInt((Boolean) value)); 3730b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3740b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_SNDBUF: 3750b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, SOL_SOCKET, SO_SNDBUF, (Integer) value); 3760b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3770b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.SO_TIMEOUT: 3780b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int millis = (Integer) value; 3790b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes StructTimeval tv = StructTimeval.fromMillis(millis); 3800b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, tv); 3810b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3820b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case SocketOptions.TCP_NODELAY: 3830b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, IPPROTO_TCP, TCP_NODELAY, booleanToInt((Boolean) value)); 3840b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 3850b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case IoBridge.JAVA_MCAST_JOIN_GROUP: 3860b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes case IoBridge.JAVA_MCAST_LEAVE_GROUP: 387df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller { 3880b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes StructGroupReq groupReq = (StructGroupReq) value; 3890b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int level = (groupReq.gr_group instanceof Inet4Address) ? IPPROTO_IP : IPPROTO_IPV6; 3900b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int op = (option == JAVA_MCAST_JOIN_GROUP) ? MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP; 3910b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptGroupReq(fd, level, op, groupReq); 3920b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 393df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller } 394df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller case IoBridge.JAVA_MCAST_JOIN_SOURCE_GROUP: 395df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller case IoBridge.JAVA_MCAST_LEAVE_SOURCE_GROUP: 396df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller case IoBridge.JAVA_MCAST_BLOCK_SOURCE: 397df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller case IoBridge.JAVA_MCAST_UNBLOCK_SOURCE: 398df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller { 399df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller StructGroupSourceReq groupSourceReq = (StructGroupSourceReq) value; 400df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller int level = (groupSourceReq.gsr_group instanceof Inet4Address) 401df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller ? IPPROTO_IP : IPPROTO_IPV6; 402df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller int op = getGroupSourceReqOp(option); 403df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller Libcore.os.setsockoptGroupSourceReq(fd, level, op, groupSourceReq); 404df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller return; 405df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller } 4060b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes default: 4070b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw new SocketException("Unknown socket option: " + option); 4080b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4090b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4100b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 411df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller private static int getGroupSourceReqOp(int javaValue) { 412df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller switch (javaValue) { 413df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller case IoBridge.JAVA_MCAST_JOIN_SOURCE_GROUP: 414df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller return MCAST_JOIN_SOURCE_GROUP; 415df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller case IoBridge.JAVA_MCAST_LEAVE_SOURCE_GROUP: 416df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller return MCAST_LEAVE_SOURCE_GROUP; 417df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller case IoBridge.JAVA_MCAST_BLOCK_SOURCE: 418df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller return MCAST_BLOCK_SOURCE; 419df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller case IoBridge.JAVA_MCAST_UNBLOCK_SOURCE: 420df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller return MCAST_UNBLOCK_SOURCE; 421df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller default: 422df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller throw new AssertionError( 423df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller "Unknown java value for setsocketopt op lookup: " + javaValue); 424df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller } 425df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller } 426df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller 4270b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes /** 4280b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * java.io only throws FileNotFoundException when opening files, regardless of what actually 4290b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * went wrong. Additionally, java.io is more restrictive than POSIX when it comes to opening 4300b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * directories: POSIX says read-only is okay, but java.io doesn't even allow that. We also 4310b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * have an Android-specific hack to alter the default permissions. 4320b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes */ 4330b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static FileDescriptor open(String path, int flags) throws FileNotFoundException { 4340b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes FileDescriptor fd = null; 4350b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 4360b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // On Android, we don't want default permissions to allow global access. 4370b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int mode = ((flags & O_ACCMODE) == O_RDONLY) ? 0 : 0600; 4380b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes fd = Libcore.os.open(path, flags, mode); 43915443035ff7b8ac7d6a7e6e2caffcd88f2faef67Narayan Kamath // Posix open(2) fails with EISDIR only if you ask for write permission. 44015443035ff7b8ac7d6a7e6e2caffcd88f2faef67Narayan Kamath // Java disallows reading directories too. 44115443035ff7b8ac7d6a7e6e2caffcd88f2faef67Narayan Kamath if (S_ISDIR(Libcore.os.fstat(fd).st_mode)) { 44215443035ff7b8ac7d6a7e6e2caffcd88f2faef67Narayan Kamath throw new ErrnoException("open", EISDIR); 4430b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4440b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return fd; 4450b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 4460b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 4470b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (fd != null) { 4480b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes IoUtils.close(fd); 4490b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4500b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (IOException ignored) { 4510b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4520b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes FileNotFoundException ex = new FileNotFoundException(path + ": " + errnoException.getMessage()); 4530b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes ex.initCause(errnoException); 4540b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw ex; 4550b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4560b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4570b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 4580b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes /** 4590b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * java.io thinks that a read at EOF is an error and should return -1, contrary to traditional 4600b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * Unix practice where you'd read until you got 0 bytes (and any future read would return -1). 4610b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes */ 4620b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static int read(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws IOException { 4630b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Arrays.checkOffsetAndCount(bytes.length, byteOffset, byteCount); 4640b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (byteCount == 0) { 4650b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return 0; 4660b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4670b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 4680b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int readCount = Libcore.os.read(fd, bytes, byteOffset, byteCount); 4690b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (readCount == 0) { 4700b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return -1; 4710b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4720b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return readCount; 4730b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 4740b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (errnoException.errno == EAGAIN) { 4750b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // We return 0 rather than throw if we try to read from an empty non-blocking pipe. 4760b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return 0; 4770b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4780b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw errnoException.rethrowAsIOException(); 4790b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4800b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4810b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 4820b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes /** 4830b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * java.io always writes every byte it's asked to, or fails with an error. (That is, unlike 4840b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes * Unix it never just writes as many bytes as happens to be convenient.) 4850b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes */ 4860b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static void write(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws IOException { 4870b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Arrays.checkOffsetAndCount(bytes.length, byteOffset, byteCount); 4880b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (byteCount == 0) { 4890b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return; 4900b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4910b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 4920b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes while (byteCount > 0) { 4930b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int bytesWritten = Libcore.os.write(fd, bytes, byteOffset, byteCount); 4940b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes byteCount -= bytesWritten; 4950b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes byteOffset += bytesWritten; 4960b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 4970b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 4980b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw errnoException.rethrowAsIOException(); 4990b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5000b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5010b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 5020b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static int sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port) throws IOException { 5030b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes boolean isDatagram = (inetAddress != null); 5040b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (!isDatagram && byteCount <= 0) { 5050b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return 0; 5060b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5070b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int result; 5080b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 5090b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes result = Libcore.os.sendto(fd, bytes, byteOffset, byteCount, flags, inetAddress, port); 5100b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 5110b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes result = maybeThrowAfterSendto(isDatagram, errnoException); 5120b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5130b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return result; 5140b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5150b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 5160b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws IOException { 5170b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes boolean isDatagram = (inetAddress != null); 5180b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (!isDatagram && buffer.remaining() == 0) { 5190b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return 0; 5200b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5210b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int result; 5220b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 5230b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes result = Libcore.os.sendto(fd, buffer, flags, inetAddress, port); 5240b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 5250b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes result = maybeThrowAfterSendto(isDatagram, errnoException); 5260b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5270b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return result; 5280b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5290b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 5300b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes private static int maybeThrowAfterSendto(boolean isDatagram, ErrnoException errnoException) throws SocketException { 5310b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (isDatagram) { 5320b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (errnoException.errno == ECONNRESET || errnoException.errno == ECONNREFUSED) { 5330b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return 0; 5340b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5350b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } else { 536f4a4259d8a548ab172ca98b702feafcd0ceb1411Elliott Hughes if (errnoException.errno == EAGAIN) { 5370b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // We were asked to write to a non-blocking socket, but were told 5380b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // it would block, so report "no bytes written". 5390b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return 0; 5400b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5410b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5420b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw errnoException.rethrowAsSocketException(); 5430b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5440b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 5450b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static int recvfrom(boolean isRead, FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, DatagramPacket packet, boolean isConnected) throws IOException { 5460b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int result; 5470b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 5480b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes InetSocketAddress srcAddress = (packet != null && !isConnected) ? new InetSocketAddress() : null; 5490b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes result = Libcore.os.recvfrom(fd, bytes, byteOffset, byteCount, flags, srcAddress); 5500b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes result = postRecvfrom(isRead, packet, isConnected, srcAddress, result); 5510b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 5520b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes result = maybeThrowAfterRecvfrom(isRead, isConnected, errnoException); 5530b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5540b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return result; 5550b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5560b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 5570b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static int recvfrom(boolean isRead, FileDescriptor fd, ByteBuffer buffer, int flags, DatagramPacket packet, boolean isConnected) throws IOException { 5580b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes int result; 5590b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 5600b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes InetSocketAddress srcAddress = (packet != null && !isConnected) ? new InetSocketAddress() : null; 5610b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes result = Libcore.os.recvfrom(fd, buffer, flags, srcAddress); 5620b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes result = postRecvfrom(isRead, packet, isConnected, srcAddress, result); 5630b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 5640b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes result = maybeThrowAfterRecvfrom(isRead, isConnected, errnoException); 5650b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5660b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return result; 5670b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5680b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 5690b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes private static int postRecvfrom(boolean isRead, DatagramPacket packet, boolean isConnected, InetSocketAddress srcAddress, int byteCount) { 5700b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (isRead && byteCount == 0) { 5710b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return -1; 5720b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5730b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (packet != null) { 574e50d82455c813210a2d452070f45fd38d9903159Elliott Hughes packet.setReceivedLength(byteCount); 5750b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (!isConnected) { 5760b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes packet.setAddress(srcAddress.getAddress()); 5770b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes packet.setPort(srcAddress.getPort()); 5780b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5790b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5800b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return byteCount; 5810b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5820b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 5830b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes private static int maybeThrowAfterRecvfrom(boolean isRead, boolean isConnected, ErrnoException errnoException) throws SocketException, SocketTimeoutException { 5840b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (isRead) { 585f4a4259d8a548ab172ca98b702feafcd0ceb1411Elliott Hughes if (errnoException.errno == EAGAIN) { 5860b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return 0; 5870b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } else { 5880b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw errnoException.rethrowAsSocketException(); 5890b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5900b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } else { 5910b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (isConnected && errnoException.errno == ECONNREFUSED) { 5920b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw new PortUnreachableException("", errnoException); 593f4a4259d8a548ab172ca98b702feafcd0ceb1411Elliott Hughes } else if (errnoException.errno == EAGAIN) { 5940b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw new SocketTimeoutException(errnoException); 5950b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } else { 5960b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw errnoException.rethrowAsSocketException(); 5970b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5980b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 5990b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 6000b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 6010b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes public static FileDescriptor socket(boolean stream) throws SocketException { 6020b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes FileDescriptor fd; 6030b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes try { 6040b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes fd = Libcore.os.socket(AF_INET6, stream ? SOCK_STREAM : SOCK_DGRAM, 0); 6050b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 6060b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // The RFC (http://www.ietf.org/rfc/rfc3493.txt) says that IPV6_MULTICAST_HOPS defaults 6070b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // to 1. The Linux kernel (at least up to 2.6.38) accidentally defaults to 64 (which 6080b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // would be correct for the *unicast* hop limit). 6090b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // See http://www.spinics.net/lists/netdev/msg129022.html, though no patch appears to 6100b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // have been applied as a result of that discussion. If that bug is ever fixed, we can 6110b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // remove this code. Until then, we manually set the hop limit on IPv6 datagram sockets. 6120b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes // (IPv4 is already correct.) 6130b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes if (!stream) { 6140b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes Libcore.os.setsockoptInt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 1); 6150b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 6160b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 6170b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return fd; 6180b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } catch (ErrnoException errnoException) { 6190b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes throw errnoException.rethrowAsSocketException(); 6200b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 6210b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 6220b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 623255a6f4ab321614ed1ca26849d1df7fa9c0610f5Elliott Hughes public static InetAddress getSocketLocalAddress(FileDescriptor fd) throws SocketException { 6249b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes try { 6259b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes SocketAddress sa = Libcore.os.getsockname(fd); 6269b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes InetSocketAddress isa = (InetSocketAddress) sa; 6279b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes return isa.getAddress(); 6289b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes } catch (ErrnoException errnoException) { 629255a6f4ab321614ed1ca26849d1df7fa9c0610f5Elliott Hughes throw errnoException.rethrowAsSocketException(); 6309b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes } 6310b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 6320b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes 633255a6f4ab321614ed1ca26849d1df7fa9c0610f5Elliott Hughes public static int getSocketLocalPort(FileDescriptor fd) throws SocketException { 6349b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes try { 6359b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes SocketAddress sa = Libcore.os.getsockname(fd); 6369b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes InetSocketAddress isa = (InetSocketAddress) sa; 6379b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes return isa.getPort(); 6389b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes } catch (ErrnoException errnoException) { 639255a6f4ab321614ed1ca26849d1df7fa9c0610f5Elliott Hughes throw errnoException.rethrowAsSocketException(); 6409b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes } 6410b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes } 6420b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes} 643