1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1995, 2018, 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 27 package java.net; 28 29 import java.io.FileDescriptor; 30 import java.io.FileInputStream; 31 import java.io.IOException; 32 import java.nio.channels.FileChannel; 33 34 import dalvik.system.BlockGuard; 35 import sun.net.ConnectionResetException; 36 37 /** 38 * This stream extends FileInputStream to implement a 39 * SocketInputStream. Note that this class should <b>NOT</b> be 40 * public. 41 * 42 * @author Jonathan Payne 43 * @author Arthur van Hoff 44 */ 45 class SocketInputStream extends FileInputStream { 46 // Android-removed: Android doesn't need to call native init. 47 // static { 48 // init(); 49 //} 50 51 private boolean eof; 52 private AbstractPlainSocketImpl impl = null; 53 private byte temp[]; 54 private Socket socket = null; 55 56 /** 57 * Creates a new SocketInputStream. Can only be called 58 * by a Socket. This method needs to hang on to the owner Socket so 59 * that the fd will not be closed. 60 * @param impl the implemented socket input stream 61 */ SocketInputStream(AbstractPlainSocketImpl impl)62 SocketInputStream(AbstractPlainSocketImpl impl) throws IOException { 63 super(impl.getFileDescriptor()); 64 this.impl = impl; 65 socket = impl.getSocket(); 66 } 67 68 /** 69 * Returns the unique {@link java.nio.channels.FileChannel FileChannel} 70 * object associated with this file input stream.</p> 71 * 72 * The {@code getChannel} method of {@code SocketInputStream} 73 * returns {@code null} since it is a socket based stream.</p> 74 * 75 * @return the file channel associated with this file input stream 76 * 77 * @since 1.4 78 * @spec JSR-51 79 */ getChannel()80 public final FileChannel getChannel() { 81 return null; 82 } 83 84 /** 85 * Reads into an array of bytes at the specified offset using 86 * the received socket primitive. 87 * @param fd the FileDescriptor 88 * @param b the buffer into which the data is read 89 * @param off the start offset of the data 90 * @param len the maximum number of bytes read 91 * @param timeout the read timeout in ms 92 * @return the actual number of bytes read, -1 is 93 * returned when the end of the stream is reached. 94 * @exception IOException If an I/O error has occurred. 95 */ socketRead0(FileDescriptor fd, byte b[], int off, int len, int timeout)96 private native int socketRead0(FileDescriptor fd, 97 byte b[], int off, int len, 98 int timeout) 99 throws IOException; 100 101 // wrap native call to allow instrumentation 102 /** 103 * Reads into an array of bytes at the specified offset using 104 * the received socket primitive. 105 * @param fd the FileDescriptor 106 * @param b the buffer into which the data is read 107 * @param off the start offset of the data 108 * @param len the maximum number of bytes read 109 * @param timeout the read timeout in ms 110 * @return the actual number of bytes read, -1 is 111 * returned when the end of the stream is reached. 112 * @exception IOException If an I/O error has occurred. 113 */ socketRead(FileDescriptor fd, byte b[], int off, int len, int timeout)114 private int socketRead(FileDescriptor fd, 115 byte b[], int off, int len, 116 int timeout) 117 throws IOException { 118 return socketRead0(fd, b, off, len, timeout); 119 } 120 121 /** 122 * Reads into a byte array data from the socket. 123 * @param b the buffer into which the data is read 124 * @return the actual number of bytes read, -1 is 125 * returned when the end of the stream is reached. 126 * @exception IOException If an I/O error has occurred. 127 */ read(byte b[])128 public int read(byte b[]) throws IOException { 129 return read(b, 0, b.length); 130 } 131 132 /** 133 * Reads into a byte array <i>b</i> at offset <i>off</i>, 134 * <i>length</i> bytes of data. 135 * @param b the buffer into which the data is read 136 * @param off the start offset of the data 137 * @param length the maximum number of bytes read 138 * @return the actual number of bytes read, -1 is 139 * returned when the end of the stream is reached. 140 * @exception IOException If an I/O error has occurred. 141 */ read(byte b[], int off, int length)142 public int read(byte b[], int off, int length) throws IOException { 143 return read(b, off, length, impl.getTimeout()); 144 } 145 read(byte b[], int off, int length, int timeout)146 int read(byte b[], int off, int length, int timeout) throws IOException { 147 int n; 148 149 // EOF already encountered 150 if (eof) { 151 return -1; 152 } 153 154 // connection reset 155 if (impl.isConnectionReset()) { 156 throw new SocketException("Connection reset"); 157 } 158 159 // bounds check 160 if (length <= 0 || off < 0 || length > b.length - off) { 161 if (length == 0) { 162 return 0; 163 } 164 throw new ArrayIndexOutOfBoundsException("length == " + length 165 + " off == " + off + " buffer length == " + b.length); 166 } 167 168 // acquire file descriptor and do the read 169 FileDescriptor fd = impl.acquireFD(); 170 try { 171 // Android-added: Check BlockGuard policy in read(). 172 BlockGuard.getThreadPolicy().onNetwork(); 173 n = socketRead(fd, b, off, length, timeout); 174 if (n > 0) { 175 return n; 176 } 177 } catch (ConnectionResetException rstExc) { 178 impl.setConnectionReset(); 179 } finally { 180 impl.releaseFD(); 181 } 182 183 /* 184 * If we get here we are at EOF, the socket has been closed, 185 * or the connection has been reset. 186 */ 187 if (impl.isClosedOrPending()) { 188 throw new SocketException("Socket closed"); 189 } 190 if (impl.isConnectionReset()) { 191 throw new SocketException("Connection reset"); 192 } 193 eof = true; 194 return -1; 195 } 196 197 /** 198 * Reads a single byte from the socket. 199 */ read()200 public int read() throws IOException { 201 if (eof) { 202 return -1; 203 } 204 temp = new byte[1]; 205 int n = read(temp, 0, 1); 206 if (n <= 0) { 207 return -1; 208 } 209 return temp[0] & 0xff; 210 } 211 212 /** 213 * Skips n bytes of input. 214 * @param numbytes the number of bytes to skip 215 * @return the actual number of bytes skipped. 216 * @exception IOException If an I/O error has occurred. 217 */ skip(long numbytes)218 public long skip(long numbytes) throws IOException { 219 if (numbytes <= 0) { 220 return 0; 221 } 222 long n = numbytes; 223 int buflen = (int) Math.min(1024, n); 224 byte data[] = new byte[buflen]; 225 while (n > 0) { 226 int r = read(data, 0, (int) Math.min((long) buflen, n)); 227 if (r < 0) { 228 break; 229 } 230 n -= r; 231 } 232 return numbytes - n; 233 } 234 235 /** 236 * Returns the number of bytes that can be read without blocking. 237 * @return the number of immediately available bytes 238 */ available()239 public int available() throws IOException { 240 // Android-changed: Bug fix, if eof == true, we must indicate that we 241 // have 0 bytes available. 242 if (eof) { 243 return 0; 244 } else { 245 return impl.available(); 246 } 247 } 248 249 /** 250 * Closes the stream. 251 */ 252 private boolean closing = false; close()253 public void close() throws IOException { 254 // Prevent recursion. See BugId 4484411 255 if (closing) 256 return; 257 closing = true; 258 if (socket != null) { 259 if (!socket.isClosed()) 260 socket.close(); 261 } else 262 impl.close(); 263 closing = false; 264 } 265 setEOF(boolean eof)266 void setEOF(boolean eof) { 267 this.eof = eof; 268 } 269 270 /** 271 * Overrides finalize, the fd is closed by the Socket. 272 */ finalize()273 protected void finalize() {} 274 275 // Android-removed: Android doesn't need native init. 276 /* 277 * Perform class load-time initializations. 278 * 279 private native static void init(); 280 */ 281 } 282