0N/A/*
2362N/A * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A
0N/Apackage sun.security.ssl;
0N/A
0N/Aimport java.io.*;
0N/A
0N/A/**
0N/A * InputStream for application data as returned by SSLSocket.getInputStream().
0N/A * It uses an InputRecord as internal buffer that is refilled on demand
0N/A * whenever it runs out of data.
0N/A *
0N/A * @author David Brownell
0N/A */
0N/Aclass AppInputStream extends InputStream {
0N/A
0N/A // static dummy array we use to implement skip()
0N/A private final static byte[] SKIP_ARRAY = new byte[1024];
0N/A
0N/A private SSLSocketImpl c;
0N/A InputRecord r;
0N/A
0N/A // One element array used to implement the single byte read() method
0N/A private final byte[] oneByte = new byte[1];
0N/A
0N/A AppInputStream(SSLSocketImpl conn) {
0N/A r = new InputRecord();
0N/A c = conn;
0N/A }
0N/A
0N/A /**
0N/A * Return the minimum number of bytes that can be read without blocking.
0N/A * Currently not synchronized.
0N/A */
0N/A public int available() throws IOException {
0N/A if (c.checkEOF() || (r.isAppDataValid() == false)) {
0N/A return 0;
0N/A }
0N/A return r.available();
0N/A }
0N/A
0N/A /**
0N/A * Read a single byte, returning -1 on non-fault EOF status.
0N/A */
0N/A public synchronized int read() throws IOException {
0N/A int n = read(oneByte, 0, 1);
0N/A if (n <= 0) { // EOF
0N/A return -1;
0N/A }
0N/A return oneByte[0] & 0xff;
0N/A }
0N/A
0N/A /**
0N/A * Read up to "len" bytes into this buffer, starting at "off".
0N/A * If the layer above needs more data, it asks for more, so we
0N/A * are responsible only for blocking to fill at most one buffer,
0N/A * and returning "-1" on non-fault EOF status.
0N/A */
0N/A public synchronized int read(byte b[], int off, int len)
0N/A throws IOException {
897N/A if (b == null) {
897N/A throw new NullPointerException();
897N/A } else if (off < 0 || len < 0 || len > b.length - off) {
897N/A throw new IndexOutOfBoundsException();
897N/A } else if (len == 0) {
897N/A return 0;
897N/A }
897N/A
0N/A if (c.checkEOF()) {
0N/A return -1;
0N/A }
0N/A try {
0N/A /*
0N/A * Read data if needed ... notice that the connection guarantees
0N/A * that handshake, alert, and change cipher spec data streams are
0N/A * handled as they arrive, so we never see them here.
0N/A */
0N/A while (r.available() == 0) {
0N/A c.readDataRecord(r);
0N/A if (c.checkEOF()) {
0N/A return -1;
0N/A }
0N/A }
0N/A
0N/A int howmany = Math.min(len, r.available());
0N/A howmany = r.read(b, off, howmany);
0N/A return howmany;
0N/A } catch (Exception e) {
0N/A // shutdown and rethrow (wrapped) exception as appropriate
0N/A c.handleException(e);
0N/A // dummy for compiler
0N/A return -1;
0N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Skip n bytes. This implementation is somewhat less efficient
0N/A * than possible, but not badly so (redundant copy). We reuse
0N/A * the read() code to keep things simpler. Note that SKIP_ARRAY
0N/A * is static and may garbled by concurrent use, but we are not interested
0N/A * in the data anyway.
0N/A */
0N/A public synchronized long skip(long n) throws IOException {
0N/A long skipped = 0;
0N/A while (n > 0) {
0N/A int len = (int)Math.min(n, SKIP_ARRAY.length);
0N/A int r = read(SKIP_ARRAY, 0, len);
0N/A if (r <= 0) {
0N/A break;
0N/A }
0N/A n -= r;
0N/A skipped += r;
0N/A }
0N/A return skipped;
0N/A }
0N/A
0N/A /*
0N/A * Socket close is already synchronized, no need to block here.
0N/A */
0N/A public void close() throws IOException {
0N/A c.close();
0N/A }
0N/A
0N/A // inherit default mark/reset behavior (throw Exceptions) from InputStream
0N/A
0N/A}