2
* Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
28
import java.io.FileDescriptor;
29
import java.io.FileInputStream;
30
import java.io.IOException;
31
import java.nio.channels.FileChannel;
32
import static ikvm.internal.Winsock.*;
33
import static java.net.net_util_md.*;
35
import sun.net.ConnectionResetException;
38
* This stream extends FileInputStream to implement a
39
* SocketInputStream. Note that this class should <b>NOT</b> be
42
* @author Jonathan Payne
43
* @author Arthur van Hoff
44
* @author Jeroen Frijters
46
class SocketInputStream extends FileInputStream
50
private AbstractPlainSocketImpl impl = null;
52
private Socket socket = null;
55
* Creates a new SocketInputStream. Can only be called
56
* by a Socket. This method needs to hang on to the owner Socket so
57
* that the fd will not be closed.
58
* @param impl the implemented socket input stream
60
SocketInputStream(AbstractPlainSocketImpl impl) throws IOException {
61
super(impl.getFileDescriptor());
63
socket = impl.getSocket();
67
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
68
* object associated with this file input stream.</p>
70
* The <code>getChannel</code> method of <code>SocketInputStream</code>
71
* returns <code>null</code> since it is a socket based stream.</p>
73
* @return the file channel associated with this file input stream
78
public final FileChannel getChannel() {
83
* Reads into an array of bytes at the specified offset using
84
* the received socket primitive.
85
* @param fd the FileDescriptor
86
* @param b the buffer into which the data is read
87
* @param off the start offset of the data
88
* @param len the maximum number of bytes read
89
* @param timeout the read timeout in ms
90
* @return the actual number of bytes read, -1 is
91
* returned when the end of the stream is reached.
92
* @exception IOException If an I/O error has occurred.
94
private int socketRead0(FileDescriptor fdObj, byte bufP[], int off, int len, int timeout) throws IOException
96
// [IKVM] this method is a direct port of the native code in openjdk6-b18\jdk\src\windows\native\java\net\SocketInputStream.c
97
cli.System.Net.Sockets.Socket fd = null;
100
if (IS_NULL(fdObj)) {
101
throw new SocketException("socket closed");
103
fd = fdObj.getSocket();
105
throw new SocketException("Socket closed");
109
if (timeout <= 5000 || !isRcvTimeoutSupported) {
110
int ret = NET_Timeout (fd, timeout);
114
throw new SocketTimeoutException("Read timed out");
116
// [IKVM] the OpenJDK native code is broken and always throws this exception on any failure of NET_Timeout
117
throw new SocketException("socket closed");
121
/*check if the socket has been closed while we were in timeout*/
122
if (fdObj.getSocket() == null) {
123
throw new SocketException("Socket Closed");
128
nread = recv(fd, bufP, off, len, 0);
136
switch (WSAGetLastError()) {
138
throw new SocketException("socket closed");
143
* Connection has been reset - Windows sometimes reports
144
* the reset as a shutdown error.
146
throw new ConnectionResetException();
149
throw new SocketTimeoutException("Read timed out");
152
throw NET_ThrowCurrent("recv failed");
160
* Reads into a byte array data from the socket.
161
* @param b the buffer into which the data is read
162
* @return the actual number of bytes read, -1 is
163
* returned when the end of the stream is reached.
164
* @exception IOException If an I/O error has occurred.
166
public int read(byte b[]) throws IOException {
167
return read(b, 0, b.length);
171
* Reads into a byte array <i>b</i> at offset <i>off</i>,
172
* <i>length</i> bytes of data.
173
* @param b the buffer into which the data is read
174
* @param off the start offset of the data
175
* @param len the maximum number of bytes read
176
* @return the actual number of bytes read, -1 is
177
* returned when the end of the stream is reached.
178
* @exception IOException If an I/O error has occurred.
180
public int read(byte b[], int off, int length) throws IOException {
181
return read(b, off, length, impl.getTimeout());
184
int read(byte b[], int off, int length, int timeout) throws IOException {
187
// EOF already encountered
193
if (impl.isConnectionReset()) {
194
throw new SocketException("Connection reset");
198
if (length <= 0 || off < 0 || off + length > b.length) {
202
throw new ArrayIndexOutOfBoundsException();
205
boolean gotReset = false;
207
// acquire file descriptor and do the read
208
FileDescriptor fd = impl.acquireFD();
210
n = socketRead0(fd, b, off, length, timeout);
214
} catch (ConnectionResetException rstExc) {
221
* We receive a "connection reset" but there may be bytes still
222
* buffered on the socket
225
impl.setConnectionResetPending();
228
n = socketRead0(fd, b, off, length, timeout);
232
} catch (ConnectionResetException rstExc) {
239
* If we get here we are at EOF, the socket has been closed,
240
* or the connection has been reset.
242
if (impl.isClosedOrPending()) {
243
throw new SocketException("Socket closed");
245
if (impl.isConnectionResetPending()) {
246
impl.setConnectionReset();
248
if (impl.isConnectionReset()) {
249
throw new SocketException("Connection reset");
256
* Reads a single byte from the socket.
258
public int read() throws IOException {
263
int n = read(temp, 0, 1);
267
return temp[0] & 0xff;
271
* Skips n bytes of input.
272
* @param n the number of bytes to skip
273
* @return the actual number of bytes skipped.
274
* @exception IOException If an I/O error has occurred.
276
public long skip(long numbytes) throws IOException {
281
int buflen = (int) Math.min(1024, n);
282
byte data[] = new byte[buflen];
284
int r = read(data, 0, (int) Math.min((long) buflen, n));
294
* Returns the number of bytes that can be read without blocking.
295
* @return the number of immediately available bytes
297
public int available() throws IOException {
298
return impl.available();
304
private boolean closing = false;
305
public void close() throws IOException {
306
// Prevent recursion. See BugId 4484411
310
if (socket != null) {
311
if (!socket.isClosed())
318
void setEOF(boolean eof) {
323
* Overrides finalize, the fd is closed by the Socket.
325
protected void finalize() {}