This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push: new b311c0a0ac Fix BZ 66076. Non-blocking flush with TLS+NIO must flush network buffer b311c0a0ac is described below commit b311c0a0acc33d0d6530c92e6b1f0f5906b62144 Author: Mark Thomas <ma...@apache.org> AuthorDate: Mon May 23 10:17:02 2022 +0100 Fix BZ 66076. Non-blocking flush with TLS+NIO must flush network buffer https://bz.apache.org/bugzilla/show_bug.cgi?id=66076 --- java/org/apache/tomcat/util/net/NioEndpoint.java | 24 ++++++++++++++++++---- .../apache/tomcat/util/net/SocketWrapperBase.java | 14 +++++++++++++ webapps/docs/changelog.xml | 9 ++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/java/org/apache/tomcat/util/net/NioEndpoint.java b/java/org/apache/tomcat/util/net/NioEndpoint.java index 78f4d3ca53..b8b6d4339d 100644 --- a/java/org/apache/tomcat/util/net/NioEndpoint.java +++ b/java/org/apache/tomcat/util/net/NioEndpoint.java @@ -1345,20 +1345,20 @@ public class NioEndpoint extends AbstractJsseEndpoint<NioChannel,SocketChannel> @Override protected boolean flushNonBlocking() throws IOException { - boolean dataLeft = !socketBufferHandler.isWriteBufferEmpty(); + boolean dataLeft = socketOrNetworkBufferHasDataLeft(); // Write to the socket, if there is anything to write if (dataLeft) { doWrite(false); - dataLeft = !socketBufferHandler.isWriteBufferEmpty(); + dataLeft = socketOrNetworkBufferHasDataLeft(); } if (!dataLeft && !nonBlockingWriteBuffer.isEmpty()) { dataLeft = nonBlockingWriteBuffer.write(this, false); - if (!dataLeft && !socketBufferHandler.isWriteBufferEmpty()) { + if (!dataLeft && socketOrNetworkBufferHasDataLeft()) { doWrite(false); - dataLeft = !socketBufferHandler.isWriteBufferEmpty(); + dataLeft = socketOrNetworkBufferHasDataLeft(); } } @@ -1366,6 +1366,22 @@ public class NioEndpoint extends AbstractJsseEndpoint<NioChannel,SocketChannel> } + /* + * https://bz.apache.org/bugzilla/show_bug.cgi?id=66076 + * + * When using TLS an additional buffer is used for the encrypted data + * before it is written to the network. It is possible for this network + * output buffer to contain data while the socket write buffer is empty. + * + * For NIO with non-blocking I/O, this case is handling by ensuring that + * flush only returns false (i.e. no data left to flush) if all buffers + * are empty. + */ + private boolean socketOrNetworkBufferHasDataLeft() { + return !socketBufferHandler.isWriteBufferEmpty() || getSocket().getOutboundRemaining() > 0; + } + + @Override protected void doWrite(boolean block, ByteBuffer buffer) throws IOException { int n = 0; diff --git a/java/org/apache/tomcat/util/net/SocketWrapperBase.java b/java/org/apache/tomcat/util/net/SocketWrapperBase.java index 67a6d0f08d..bcb0119fc6 100644 --- a/java/org/apache/tomcat/util/net/SocketWrapperBase.java +++ b/java/org/apache/tomcat/util/net/SocketWrapperBase.java @@ -722,6 +722,12 @@ public abstract class SocketWrapperBase<E> { } + /** + * Writes all remaining data from the buffers and blocks until the write is + * complete. + * + * @throws IOException If an IO error occurs during the write + */ protected void flushBlocking() throws IOException { doWrite(true); @@ -736,6 +742,14 @@ public abstract class SocketWrapperBase<E> { } + /** + * Writes as much data as possible from any that remains in the buffers. + * + * @return <code>true</code> if data remains to be flushed after this method + * completes, otherwise <code>false</code>. + * + * @throws IOException If an IO error occurs during the write + */ protected abstract boolean flushNonBlocking() throws IOException; diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 5e6fa49603..24c8a20c36 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -126,6 +126,15 @@ </fix> </changelog> </subsection> + <subsection name="Coyote"> + <changelog> + <fix> + <bug>66076</bug>: When using TLS with non-blocking writes and the NIO + connector, ensure that flushing the buffers attempts to empty all of the + output buffers. (markt) + </fix> + </changelog> + </subsection> <subsection name="Jasper"> <changelog> <fix> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org