/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketInputStream.java
Java | 197 lines | 86 code | 21 blank | 90 comment | 17 complexity | 9bae37c2db03fec226b03b3cb0116a74 MD5 | raw file
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.harmony.xnet.provider.jsse;
- import java.io.IOException;
- import java.io.InputStream;
- import javax.net.ssl.SSLException;
- /**
- * This class provides input data stream functionality
- * for SSLSocket. It accumulates the application data
- * received by SSL protocol.
- */
- public final class SSLSocketInputStream
- extends InputStream {
- // The size of the internal data buffer.
- // It should not be less than maximum data chunk enclosed
- // in one ssl packet.
- private final int size = SSLRecordProtocol.MAX_DATA_LENGTH;
- // Internal buffer accumulating the received application data
- private byte[] buffer = new byte[size];
- // position of the next byte to read from the buffer
- private int pos;
- // position of the last byte to read + 1
- private int end;
- // the ssl socket owning the stream
- private final SSLSocketImpl owner;
- // the flag indicating that the end of the (owner's) input stream
- // has been reached
- private boolean end_reached = false;
- /**
- * Creates the application data input stream for specified socket.
- * @param owner the socket which will provide this input stream
- * to client applications.
- */
- protected SSLSocketInputStream(SSLSocketImpl owner) {
- this.owner = owner;
- }
- // The helper delivering the application data from the record layer
- protected Adapter dataPoint = new Adapter();
- /**
- * Tells to the stream that the end of the income data has
- * been reached.
- */
- protected void setEnd() {
- end_reached = true;
- }
- // ------------------ InputStream implementetion -------------------
- /**
- * Returns the number of bytes available for reading without blocking.
- * @return the number of available bytes.
- * @throws IOException
- */
- @Override
- public int available() throws IOException {
- return end - pos;
- }
- /**
- * Closes the stream
- * @throws IOException
- */
- @Override
- public void close() throws IOException {
- buffer = null;
- }
- /**
- * Reads one byte. If there is no data in the underlying buffer,
- * this operation can block until the data will be
- * available.
- * @return read value.
- * @throws IOException
- */
- @Override
- public int read() throws IOException {
- if (buffer == null) {
- throw new IOException("Stream was closed.");
- }
- while (pos == end) {
- if (end_reached) {
- return -1;
- }
- // If there is no data in the buffer
- // - will block untill the data will be provided by
- // record layer
- owner.needAppData();
- }
- return buffer[pos++] & 0xFF;
- }
- /**
- * Method acts as described in spec for superclass.
- * @see java.io.InputStream#read(byte[])
- */
- @Override
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
- }
- /**
- * Method acts as described in spec for superclass.
- * @see java.io.InputStream#read(byte[],int,int)
- */
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- int read_b;
- int i = 0;
- do {
- if ((read_b = read()) == -1) {
- return (i == 0) ? -1 : i;
- }
- b[off+i] = (byte) read_b;
- i++;
- } while ((available() != 0) && (i<len));
- return i;
- }
- /**
- * Method acts as described in spec for superclass.
- * @see java.io.InputStream#skip(long)
- */
- @Override
- public long skip(long n) throws IOException {
- long i = 0;
- int av = available();
- if (av < n) {
- n = av;
- }
- while ((i < n) && (read() != -1)) {
- i++;
- }
- return i;
- }
- // The helper class devivering the application data from the record layer
- // to this input stream.
- // It 'adapts' the InputStream interface to Appendable, which is used for
- // transmition of income data from the record protocol to its clients.
- private class Adapter implements org.apache.harmony.xnet.provider.jsse.Appendable {
- /**
- * Appends the data to the stream.
- * This method could be implemented in the outer class
- * itself, but it could be insecure.
- */
- public void append(byte[] src) {
- int length = src.length;
- if (size - (end - pos) < length) {
- // If the size of the buffer is greater than or equals to
- // SSLRecordProtocol.MAX_DATA_LENGTH this situation will
- // happen iff:
- // 1. the length of received data fragment is greater
- // than allowed by the spec
- // 2. it is rehandhaking stage and we have got several
- // extra app data messages.
- // In any case it is better to throw alert exception.
- throw new AlertException(AlertProtocol.INTERNAL_ERROR,
- new SSLException("Could not accept income app data."));
- }
- if (end + length > size) {
- // move the content of the buffer to the beginnig
- System.arraycopy(buffer, pos, buffer, 0, end-pos);
- end -= pos;
- pos = 0;
- }
- System.arraycopy(src, 0, buffer, end, length);
- end = end + length;
- }
- }
- }