Fix unwrapping loop in case reading bytebuffer has exactly 1 handshake message#1281
Conversation
In the scenario where the reading ByteBuffer only has enough bytes to unwrap one handshake message, the flow may enter a loop due to the call to ByteBuffer.clear(). That method does not actually erase any data, instead it sets the position back to 0, the limit to the capacity, and the mark is discarded. Since we are doing another unwrap attempt using the same reading ByteBuffer, the same handshake message will be read. Updating the reading ByteBuffer position instead of trying to clear it will result in a BUFFER_UNDERFLOW, which will then trigger another read from the channel (as expected).
|
Thank you for your analysis and contribution! Can we ensure that this change does not re-introduce these issues? |
|
@lukebakken TLS 1.3 with NIO is tested in The tests explicitly require JDK 11+, which does support TLS 1.3. |
|
Is there a way to reproduce the issue mentioned in #1280 in a test to make sure the PR fixes it? |
|
I was able to successfully test the fix in one of our development environments but I wasn't able to set up a similar scenario for an integration test. We could eventually replicate the issue if there was a way to control the ingest of handshake messages, but I do not see an easy way to do that. Any ideas? |
|
Since this is an IaaS-provider specific networking/TLS behavior (configuration), it can be extremely painful to test. If we trust our existing suites for #712 #715, then I find it acceptable to merge this PR as is, since @bmleite has identified the problem and tested a fix exactly in the environment where it was manifesting itself. We fairly often accept these env-specific testability limitations for RabbitMQ itself. |
Fixes #1280
Proposed Changes
In the scenario where the reading ByteBuffer only has enough bytes to unwrap one handshake message, the flow may enter a loop due to the call to
ByteBuffer.clear(). That method does not actually erase any data, instead, it sets the position back to 0, the limit to the capacity, and the mark is discarded. Since we are doing another unwrap attempt using the same reading ByteBuffer, the same handshake message will be read.Updating the reading ByteBuffer position instead of trying to clear it will result in a
BUFFER_UNDERFLOW, which will then trigger another read from the channel, as expected.Logs
Debug logs from successful NIO handshake attempt using AWS NLB with TLSv1.2:
Types of Changes
Checklist
CONTRIBUTING.mddocument