1 /* 2 * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.net; 27 28 import java.io.FileDescriptor; 29 import java.io.FileInputStream; 30 import java.io.IOException; 31 import java.nio.channels.FileChannel; 32 33 import sun.net.ConnectionResetException; 34 35 /** 36 * This stream extends FileInputStream to implement a 37 * SocketInputStream. Note that this class should <b>NOT</b> be 38 * public. 39 * 40 * @author Jonathan Payne 41 * @author Arthur van Hoff 42 */ 43 class SocketInputStream extends FileInputStream { 44 static { 45 init(); 46 } 47 48 private boolean eof; 49 private AbstractPlainSocketImpl impl = null; 50 private byte temp[]; 51 52 /** 53 * Creates a new SocketInputStream. Can only be called 54 * by a Socket. This method needs to hang on to the owner Socket so 55 * that the fd will not be closed. 56 * @param impl the implemented socket input stream 57 */ 58 SocketInputStream(AbstractPlainSocketImpl impl) throws IOException { 59 super(impl.getFileDescriptor()); 60 this.impl = impl; 61 } 62 63 /** 64 * Returns the unique {@link java.nio.channels.FileChannel FileChannel} 65 * object associated with this file input stream.</p> 66 * 67 * The {@code getChannel} method of {@code SocketInputStream} 68 * returns {@code null} since it is a socket based stream.</p> 69 * 70 * @return the file channel associated with this file input stream 71 * 72 * @since 1.4 73 * @spec JSR-51 74 */ 75 public final FileChannel getChannel() { 76 return null; 77 } 78 79 /** 80 * Reads into an array of bytes at the specified offset using 81 * the received socket primitive. 82 * @param fd the FileDescriptor 83 * @param b the buffer into which the data is read 84 * @param off the start offset of the data 85 * @param len the maximum number of bytes read 86 * @param timeout the read timeout in ms 87 * @return the actual number of bytes read, -1 is 88 * returned when the end of the stream is reached. 89 * @throws IOException If an I/O error has occurred. 90 */ 91 private native int socketRead0(FileDescriptor fd, 92 byte b[], int off, int len, 93 int timeout) 94 throws IOException; 95 96 // wrap native call to allow instrumentation 97 /** 98 * Reads into an array of bytes at the specified offset using 99 * the received socket primitive. 100 * @param fd the FileDescriptor 101 * @param b the buffer into which the data is read 102 * @param off the start offset of the data 103 * @param len the maximum number of bytes read 104 * @param timeout the read timeout in ms 105 * @return the actual number of bytes read, -1 is 106 * returned when the end of the stream is reached. 107 * @throws IOException If an I/O error has occurred. 108 */ 109 private int socketRead(FileDescriptor fd, 110 byte b[], int off, int len, 111 int timeout) 112 throws IOException { 113 return socketRead0(fd, b, off, len, timeout); 114 } 115 116 /** 117 * Reads into a byte array data from the socket. 118 * @param b the buffer into which the data is read 119 * @return the actual number of bytes read, -1 is 120 * returned when the end of the stream is reached. 121 * @throws IOException If an I/O error has occurred. 122 */ 123 public int read(byte b[]) throws IOException { 124 return read(b, 0, b.length); 125 } 126 127 /** 128 * Reads into a byte array <i>b</i> at offset <i>off</i>, 129 * <i>length</i> bytes of data. 130 * @param b the buffer into which the data is read 131 * @param off the start offset of the data 132 * @param length the maximum number of bytes read 133 * @return the actual number of bytes read, -1 is 134 * returned when the end of the stream is reached. 135 * @throws IOException If an I/O error has occurred. 136 */ 137 public int read(byte b[], int off, int length) throws IOException { 138 return read(b, off, length, impl.getTimeout()); 139 } 140 141 int read(byte b[], int off, int length, int timeout) throws IOException { 142 int n; 143 144 // EOF already encountered 145 if (eof) { 146 return -1; 147 } 148 149 // connection reset 150 if (impl.isConnectionReset()) { 151 throw new SocketException("Connection reset"); 152 } 153 154 // bounds check 155 if (length <= 0 || off < 0 || length > b.length - off) { 156 if (length == 0) { 157 return 0; 158 } 159 throw new ArrayIndexOutOfBoundsException("length == " + length 160 + " off == " + off + " buffer length == " + b.length); 161 } 162 163 // acquire file descriptor and do the read 164 FileDescriptor fd = impl.acquireFD(); 165 try { 166 n = socketRead(fd, b, off, length, timeout); 167 if (n > 0) { 168 return n; 169 } 170 } catch (ConnectionResetException rstExc) { 171 impl.setConnectionReset(); 172 } finally { 173 impl.releaseFD(); 174 } 175 176 /* 177 * If we get here we are at EOF, the socket has been closed, 178 * or the connection has been reset. 179 */ 180 if (impl.isClosedOrPending()) { 181 throw new SocketException("Socket closed"); 182 } 183 if (impl.isConnectionReset()) { 184 throw new SocketException("Connection reset"); 185 } 186 eof = true; 187 return -1; 188 } 189 190 /** 191 * Reads a single byte from the socket. 192 */ 193 public int read() throws IOException { 194 if (eof) { 195 return -1; 196 } 197 temp = new byte[1]; 198 int n = read(temp, 0, 1); 199 if (n <= 0) { 200 return -1; 201 } 202 return temp[0] & 0xff; 203 } 204 205 /** 206 * Skips n bytes of input. 207 * @param numbytes the number of bytes to skip 208 * @return the actual number of bytes skipped. 209 * @throws IOException If an I/O error has occurred. 210 */ 211 public long skip(long numbytes) throws IOException { 212 if (numbytes <= 0) { 213 return 0; 214 } 215 long n = numbytes; 216 int buflen = (int) Math.min(1024, n); 217 byte data[] = new byte[buflen]; 218 while (n > 0) { 219 int r = read(data, 0, (int) Math.min((long) buflen, n)); 220 if (r < 0) { 221 break; 222 } 223 n -= r; 224 } 225 return numbytes - n; 226 } 227 228 /** 229 * Returns the number of bytes that can be read without blocking. 230 * @return the number of immediately available bytes 231 */ 232 public int available() throws IOException { 233 int available = impl.available(); 234 return eof ? 0 : available; 235 } 236 237 void setEOF(boolean eof) { 238 this.eof = eof; 239 } 240 241 public void close() throws IOException { 242 // No longer used. Socket.getInputStream returns an 243 // InputStream which calls Socket.close directly 244 assert false; 245 } 246 247 /** 248 * Overrides finalize, the fd is closed by the Socket. 249 */ 250 @SuppressWarnings({"deprecation", "removal"}) 251 protected void finalize() {} 252 253 /** 254 * Perform class load-time initializations. 255 */ 256 private static native void init(); 257 }