[tcp] Fix TlsState by aborting the channel selected callback

Instead of breaking in case the SSLEngine signals NEED_WRAP, which
leads to an endless loop while holding the
channelSelectedCallbackLock, we have to return, so that the
asynchronously invoked callback can aquire it, and do its work.
This commit is contained in:
Florian Schmaus 2020-09-17 21:07:35 +02:00
parent b7824f008d
commit 488d01796a
1 changed files with 16 additions and 4 deletions

View File

@ -1066,18 +1066,25 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
SSLEngineResult.HandshakeStatus handshakeStatus = handleHandshakeStatus(result);
switch (handshakeStatus) {
case NEED_TASK:
// A delegated task is asynchronously running. Signal that there is pending input data and
// cycle again through the smack reactor.
// A delegated task is asynchronously running. Take care of the remaining accumulatedData.
addAsPendingInputData(accumulatedData);
break;
// Return here, as the async task created by handleHandshakeStatus will continue calling the
// cannelSelectedCallback.
return null;
case NEED_UNWRAP:
continue;
case NEED_WRAP:
// NEED_WRAP means that the SSLEngine needs to send data, probably without consuming data.
// We exploit here the fact that the channelSelectedCallback is single threaded and that the
// input processing is after the output processing.
addAsPendingInputData(accumulatedData);
// Note that it is ok that we the provided argument for pending input filter data to channel
// selected callback is false, as setPendingInputFilterData() will have set the internal state
// boolean accordingly.
connectionInternal.asyncGo(() -> callChannelSelectedCallback(false, true));
break;
// Do not break here, but instead return and let the asynchronously invoked
// callChannelSelectedCallback() do its work.
return null;
default:
break;
}
@ -1109,8 +1116,13 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
}
private void addAsPendingInputData(ByteBuffer byteBuffer) {
// TODO: Why doeesn't simply
// pendingInputData = byteBuffer;
// work?
pendingInputData = ByteBuffer.allocate(byteBuffer.remaining());
pendingInputData.put(byteBuffer).flip();
pendingInputFilterData = pendingInputData.hasRemaining();
}
private SSLEngineResult.HandshakeStatus handleHandshakeStatus(SSLEngineResult sslEngineResult) {