in proton-j/src/main/java/org/apache/qpid/proton/engine/impl/ssl/SimpleSslTransportWrapper.java [107:206]
private void unwrapInput() throws SSLException
{
int prevInRemaining = -1;
while (true) {
SSLEngineResult result = _sslEngine.unwrap(_inputBuffer, _decodedInputBuffer);
logEngineClientModeAndResult(result, "input");
int read = result.bytesProduced();
Status status = result.getStatus();
HandshakeStatus hstatus = result.getHandshakeStatus();
int capacity = _underlyingInput.capacity();
if (capacity == Transport.END_OF_STREAM || capacity <= 0) {
_tail_closed = true;
if (_decodedInputBuffer.position() > 0) {
throw new TransportException("bytes left unconsumed");
}
} else {
_decodedInputBuffer.flip();
while (_decodedInputBuffer.hasRemaining() && capacity > 0) {
ByteBuffer tail = _underlyingInput.tail();
int limit = _decodedInputBuffer.limit();
int overflow = _decodedInputBuffer.remaining() - capacity;
if (overflow > 0) {
_decodedInputBuffer.limit(limit - overflow);
}
tail.put(_decodedInputBuffer);
_decodedInputBuffer.limit(limit);
_underlyingInput.process();
capacity = _underlyingInput.capacity();
}
if (capacity == Transport.END_OF_STREAM || capacity <= 0) {
_tail_closed = true;
if (_decodedInputBuffer.hasRemaining()) {
throw new TransportException("bytes left unconsumed");
}
}
_decodedInputBuffer.compact();
}
switch (status) {
case CLOSED:
_tail_closed = true;
break;
case BUFFER_OVERFLOW:
{
ByteBuffer old = _decodedInputBuffer;
_decodedInputBuffer = newWriteableBuffer(old.capacity()*2);
old.flip();
_decodedInputBuffer.put(old);
}
continue;
case BUFFER_UNDERFLOW:
if (_tail_closed) {
_head_closed = true;
}
// wait for more data
break;
case OK:
break;
}
switch (hstatus)
{
case NEED_WRAP:
int inputRemaining = _inputBuffer.remaining();
if (inputRemaining > 0 && status == Status.OK && (inputRemaining < prevInRemaining || prevInRemaining < 0)) {
// Track remaining input so we break if no progress is made.
prevInRemaining = inputRemaining;
// Process a wrap, try to progress on the remaining input.
pending();
continue;
}
// wait for write to kick in
break;
case NEED_TASK:
runDelegatedTasks(result);
continue;
case FINISHED:
updateCipherAndProtocolName(result);
case NOT_HANDSHAKING:
case NEED_UNWRAP:
if (_inputBuffer.position() > 0 && status == Status.OK) {
continue;
} else {
if (_inputBuffer.position() == 0 &&
hstatus == HandshakeStatus.NEED_UNWRAP &&
_tail_closed) {
_head_closed = true;
}
break;
}
}
break;
}
}