~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/openjdk/java/net/SocketInputStream.java

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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.
 
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
import static ikvm.internal.Winsock.*;
 
33
import static java.net.net_util_md.*;
 
34
 
 
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
 * @author      Jeroen Frijters
 
45
 */
 
46
class SocketInputStream extends FileInputStream
 
47
{
 
48
 
 
49
    private boolean eof;
 
50
    private AbstractPlainSocketImpl impl = null;
 
51
    private byte temp[];
 
52
    private Socket socket = null;
 
53
 
 
54
    /**
 
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
 
59
     */
 
60
    SocketInputStream(AbstractPlainSocketImpl impl) throws IOException {
 
61
        super(impl.getFileDescriptor());
 
62
        this.impl = impl;
 
63
        socket = impl.getSocket();
 
64
    }
 
65
 
 
66
    /**
 
67
     * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
 
68
     * object associated with this file input stream.</p>
 
69
     *
 
70
     * The <code>getChannel</code> method of <code>SocketInputStream</code>
 
71
     * returns <code>null</code> since it is a socket based stream.</p>
 
72
     *
 
73
     * @return  the file channel associated with this file input stream
 
74
     *
 
75
     * @since 1.4
 
76
     * @spec JSR-51
 
77
     */
 
78
    public final FileChannel getChannel() {
 
79
        return null;
 
80
    }
 
81
 
 
82
    /**
 
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.
 
93
     */
 
94
    private int socketRead0(FileDescriptor fdObj, byte bufP[], int off, int len, int timeout) throws IOException
 
95
    {
 
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;
 
98
        int nread;
 
99
        
 
100
        if (IS_NULL(fdObj)) {
 
101
            throw new SocketException("socket closed");
 
102
        }
 
103
        fd = fdObj.getSocket();
 
104
        if (fd == null) {
 
105
            throw new SocketException("Socket closed");
 
106
        }
 
107
 
 
108
        if (timeout != 0) {
 
109
            if (timeout <= 5000 || !isRcvTimeoutSupported) {
 
110
                int ret = NET_Timeout (fd, timeout);
 
111
                
 
112
                if (ret <= 0) {
 
113
                    if (ret == 0) {
 
114
                        throw new SocketTimeoutException("Read timed out");
 
115
                    } else {
 
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");
 
118
                    }
 
119
                }
 
120
                
 
121
                /*check if the socket has been closed while we were in timeout*/
 
122
                if (fdObj.getSocket() == null) {
 
123
                    throw new SocketException("Socket Closed");
 
124
                }
 
125
            }
 
126
        }
 
127
        
 
128
        nread = recv(fd, bufP, off, len, 0);
 
129
        if (nread > 0) {
 
130
            // ok
 
131
        } else {
 
132
            if (nread < 0) {
 
133
                /*
 
134
                 * Recv failed.
 
135
                 */
 
136
                switch (WSAGetLastError()) {
 
137
                    case WSAEINTR:
 
138
                        throw new SocketException("socket closed");
 
139
 
 
140
                    case WSAECONNRESET:
 
141
                    case WSAESHUTDOWN:
 
142
                        /*
 
143
                         * Connection has been reset - Windows sometimes reports
 
144
                         * the reset as a shutdown error.
 
145
                         */
 
146
                        throw new ConnectionResetException();
 
147
 
 
148
                    case WSAETIMEDOUT :
 
149
                        throw new SocketTimeoutException("Read timed out");
 
150
 
 
151
                    default:
 
152
                        throw NET_ThrowCurrent("recv failed");
 
153
                }
 
154
            }
 
155
        }
 
156
        return nread;
 
157
    }
 
158
 
 
159
    /**
 
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.
 
165
     */
 
166
    public int read(byte b[]) throws IOException {
 
167
        return read(b, 0, b.length);
 
168
    }
 
169
 
 
170
    /**
 
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.
 
179
     */
 
180
    public int read(byte b[], int off, int length) throws IOException {
 
181
        return read(b, off, length, impl.getTimeout());
 
182
    }
 
183
 
 
184
    int read(byte b[], int off, int length, int timeout) throws IOException {
 
185
        int n;
 
186
 
 
187
        // EOF already encountered
 
188
        if (eof) {
 
189
            return -1;
 
190
        }
 
191
 
 
192
        // connection reset
 
193
        if (impl.isConnectionReset()) {
 
194
            throw new SocketException("Connection reset");
 
195
        }
 
196
 
 
197
        // bounds check
 
198
        if (length <= 0 || off < 0 || off + length > b.length) {
 
199
            if (length == 0) {
 
200
                return 0;
 
201
            }
 
202
            throw new ArrayIndexOutOfBoundsException();
 
203
        }
 
204
 
 
205
        boolean gotReset = false;
 
206
 
 
207
        // acquire file descriptor and do the read
 
208
        FileDescriptor fd = impl.acquireFD();
 
209
        try {
 
210
            n = socketRead0(fd, b, off, length, timeout);
 
211
            if (n > 0) {
 
212
                return n;
 
213
            }
 
214
        } catch (ConnectionResetException rstExc) {
 
215
            gotReset = true;
 
216
        } finally {
 
217
            impl.releaseFD();
 
218
        }
 
219
 
 
220
        /*
 
221
         * We receive a "connection reset" but there may be bytes still
 
222
         * buffered on the socket
 
223
         */
 
224
        if (gotReset) {
 
225
            impl.setConnectionResetPending();
 
226
            impl.acquireFD();
 
227
            try {
 
228
                n = socketRead0(fd, b, off, length, timeout);
 
229
                if (n > 0) {
 
230
                    return n;
 
231
                }
 
232
            } catch (ConnectionResetException rstExc) {
 
233
            } finally {
 
234
                impl.releaseFD();
 
235
            }
 
236
        }
 
237
 
 
238
        /*
 
239
         * If we get here we are at EOF, the socket has been closed,
 
240
         * or the connection has been reset.
 
241
         */
 
242
        if (impl.isClosedOrPending()) {
 
243
            throw new SocketException("Socket closed");
 
244
        }
 
245
        if (impl.isConnectionResetPending()) {
 
246
            impl.setConnectionReset();
 
247
        }
 
248
        if (impl.isConnectionReset()) {
 
249
            throw new SocketException("Connection reset");
 
250
        }
 
251
        eof = true;
 
252
        return -1;
 
253
    }
 
254
 
 
255
    /**
 
256
     * Reads a single byte from the socket.
 
257
     */
 
258
    public int read() throws IOException {
 
259
        if (eof) {
 
260
            return -1;
 
261
        }
 
262
        temp = new byte[1];
 
263
        int n = read(temp, 0, 1);
 
264
        if (n <= 0) {
 
265
            return -1;
 
266
        }
 
267
        return temp[0] & 0xff;
 
268
    }
 
269
 
 
270
    /**
 
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.
 
275
     */
 
276
    public long skip(long numbytes) throws IOException {
 
277
        if (numbytes <= 0) {
 
278
            return 0;
 
279
        }
 
280
        long n = numbytes;
 
281
        int buflen = (int) Math.min(1024, n);
 
282
        byte data[] = new byte[buflen];
 
283
        while (n > 0) {
 
284
            int r = read(data, 0, (int) Math.min((long) buflen, n));
 
285
            if (r < 0) {
 
286
                break;
 
287
            }
 
288
            n -= r;
 
289
        }
 
290
        return numbytes - n;
 
291
    }
 
292
 
 
293
    /**
 
294
     * Returns the number of bytes that can be read without blocking.
 
295
     * @return the number of immediately available bytes
 
296
     */
 
297
    public int available() throws IOException {
 
298
        return impl.available();
 
299
    }
 
300
 
 
301
    /**
 
302
     * Closes the stream.
 
303
     */
 
304
    private boolean closing = false;
 
305
    public void close() throws IOException {
 
306
        // Prevent recursion. See BugId 4484411
 
307
        if (closing)
 
308
            return;
 
309
        closing = true;
 
310
        if (socket != null) {
 
311
            if (!socket.isClosed())
 
312
                socket.close();
 
313
        } else
 
314
            impl.close();
 
315
        closing = false;
 
316
    }
 
317
 
 
318
    void setEOF(boolean eof) {
 
319
        this.eof = eof;
 
320
    }
 
321
 
 
322
    /**
 
323
     * Overrides finalize, the fd is closed by the Socket.
 
324
     */
 
325
    protected void finalize() {}
 
326
}