com.bugvm.conscrypt.SSLSocketInputStream Maven / Gradle / Ivy
/*
* 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 com.bugvm.conscrypt;
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 static final int BUFFER_SIZE = SSLRecordProtocol.MAX_DATA_LENGTH;
// Internal buffer accumulating the received application data
private byte[] buffer = new byte[BUFFER_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 implementation -------------------
/**
* 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 until the data will be provided by
// record layer
owner.needAppData();
}
return buffer[pos++] & 0xFF;
}
@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 BUFFER_SIZE) {
// move the content of the buffer to the beginning
System.arraycopy(buffer, pos, buffer, 0, end-pos);
end -= pos;
pos = 0;
}
System.arraycopy(src, 0, buffer, end, length);
end = end + length;
}
}
}