use of javax.net.ssl.SSLEngineResult.Status in project spring-integration by spring-projects.
the class TcpNioSSLConnection method decode.
/**
* Performs the actual decryption of a received packet - which may be real
* data, or handshaking data. Appropriate action is taken with the data.
* If this side did not initiate the handshake, any handshaking data sent out
* is handled by the thread running in the {@link SSLChannelOutputStream#doWrite(ByteBuffer)}
* method, which is awoken here, as a result of reaching that stage in the handshaking.
*/
@SuppressWarnings("fallthrough")
private SSLEngineResult decode(ByteBuffer networkBuffer) throws IOException {
SSLEngineResult result = new SSLEngineResult(Status.OK, this.sslEngine.getHandshakeStatus(), 0, 0);
HandshakeStatus handshakeStatus = this.sslEngine.getHandshakeStatus();
switch(handshakeStatus) {
case NEED_TASK:
runTasks();
break;
case NEED_UNWRAP:
case FINISHED:
case NOT_HANDSHAKING:
this.decoded.clear();
result = this.sslEngine.unwrap(networkBuffer, this.decoded);
if (logger.isDebugEnabled()) {
logger.debug("After unwrap: " + resultToString(result));
}
Status status = result.getStatus();
if (status == Status.BUFFER_OVERFLOW) {
this.decoded = this.allocateEncryptionBuffer(this.sslEngine.getSession().getApplicationBufferSize());
}
if (result.bytesProduced() > 0) {
this.decoded.flip();
super.sendToPipe(this.decoded);
}
break;
case NEED_WRAP:
if (!resumeWriterIfNeeded()) {
this.encoded.clear();
result = this.sslEngine.wrap(networkBuffer, this.encoded);
if (logger.isDebugEnabled()) {
logger.debug("After wrap: " + resultToString(result));
}
if (result.getStatus() == Status.BUFFER_OVERFLOW) {
this.encoded = this.allocateEncryptionBuffer(this.sslEngine.getSession().getPacketBufferSize());
} else {
this.encoded.flip();
getSSLChannelOutputStream().writeEncoded(this.encoded);
}
}
break;
default:
}
switch(result.getHandshakeStatus()) {
case FINISHED:
// NOSONAR - fall-through intended
resumeWriterIfNeeded();
// switch fall-through intended
case NOT_HANDSHAKING:
case NEED_UNWRAP:
this.needMoreNetworkData = result.getStatus() == Status.BUFFER_UNDERFLOW || networkBuffer.remaining() == 0;
break;
default:
}
return result;
}
use of javax.net.ssl.SSLEngineResult.Status in project netty by netty.
the class SslHandler method unwrap.
/**
* Unwraps inbound SSL records.
*/
private int unwrap(ChannelHandlerContext ctx, ByteBuf packet, int length) throws SSLException {
final int originalLength = length;
boolean wrapLater = false;
boolean notifyClosure = false;
boolean executedRead = false;
ByteBuf decodeOut = allocate(ctx, length);
try {
// See https://github.com/netty/netty/issues/5860
do {
final SSLEngineResult result = engineType.unwrap(this, packet, length, decodeOut);
final Status status = result.getStatus();
final HandshakeStatus handshakeStatus = result.getHandshakeStatus();
final int produced = result.bytesProduced();
final int consumed = result.bytesConsumed();
// Skip bytes now in case unwrap is called in a re-entry scenario. For example LocalChannel.read()
// may entry this method in a re-entry fashion and if the peer is writing into a shared buffer we may
// unwrap the same data multiple times.
packet.skipBytes(consumed);
length -= consumed;
// 2. fireChannelRead for unwrapped data
if (handshakeStatus == HandshakeStatus.FINISHED || handshakeStatus == HandshakeStatus.NOT_HANDSHAKING) {
wrapLater |= (decodeOut.isReadable() ? setHandshakeSuccessUnwrapMarkReentry() : setHandshakeSuccess()) || handshakeStatus == HandshakeStatus.FINISHED;
}
// to preserve order of events.
if (decodeOut.isReadable()) {
setState(STATE_FIRE_CHANNEL_READ);
if (isStateSet(STATE_UNWRAP_REENTRY)) {
executedRead = true;
executeChannelRead(ctx, decodeOut);
} else {
ctx.fireChannelRead(decodeOut);
}
decodeOut = null;
}
if (status == Status.CLOSED) {
// notify about the CLOSED state of the SSLEngine. See #137
notifyClosure = true;
} else if (status == Status.BUFFER_OVERFLOW) {
if (decodeOut != null) {
decodeOut.release();
}
final int applicationBufferSize = engine.getSession().getApplicationBufferSize();
// Allocate a new buffer which can hold all the rest data and loop again.
// It may happen that applicationBufferSize < produced while there is still more to unwrap, in this
// case we will just allocate a new buffer with the capacity of applicationBufferSize and call
// unwrap again.
decodeOut = allocate(ctx, engineType.calculatePendingData(this, applicationBufferSize < produced ? applicationBufferSize : applicationBufferSize - produced));
continue;
}
if (handshakeStatus == HandshakeStatus.NEED_TASK) {
boolean pending = runDelegatedTasks(true);
if (!pending) {
// We scheduled a task on the delegatingTaskExecutor, so stop processing as we will
// resume once the task completes.
//
// We break out of the loop only and do NOT return here as we still may need to notify
// about the closure of the SSLEngine.
wrapLater = false;
break;
}
} else if (handshakeStatus == HandshakeStatus.NEED_WRAP) {
// costly unwrap operation and break out of the loop.
if (wrapNonAppData(ctx, true) && length == 0) {
break;
}
}
if (status == Status.BUFFER_UNDERFLOW || // If we processed NEED_TASK we should try again even we did not consume or produce anything.
handshakeStatus != HandshakeStatus.NEED_TASK && (consumed == 0 && produced == 0 || (length == 0 && handshakeStatus == HandshakeStatus.NOT_HANDSHAKING))) {
if (handshakeStatus == HandshakeStatus.NEED_UNWRAP) {
// The underlying engine is starving so we need to feed it with more data.
// See https://github.com/netty/netty/pull/5039
readIfNeeded(ctx);
}
break;
} else if (decodeOut == null) {
decodeOut = allocate(ctx, length);
}
} while (!ctx.isRemoved());
if (isStateSet(STATE_FLUSHED_BEFORE_HANDSHAKE) && handshakePromise.isDone()) {
// We need to call wrap(...) in case there was a flush done before the handshake completed to ensure
// we do not stale.
//
// See https://github.com/netty/netty/pull/2437
clearState(STATE_FLUSHED_BEFORE_HANDSHAKE);
wrapLater = true;
}
if (wrapLater) {
wrap(ctx, true);
}
} finally {
if (decodeOut != null) {
decodeOut.release();
}
if (notifyClosure) {
if (executedRead) {
executeNotifyClosePromise(ctx);
} else {
notifyClosePromise(null);
}
}
}
return originalLength - length;
}
Aggregations