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