diff --git a/jetty-quic/quic-common/src/main/java/org/eclipse/jetty/quic/common/QuicSession.java b/jetty-quic/quic-common/src/main/java/org/eclipse/jetty/quic/common/QuicSession.java index 48a0fb46bc2c..d23d85d0efed 100644 --- a/jetty-quic/quic-common/src/main/java/org/eclipse/jetty/quic/common/QuicSession.java +++ b/jetty-quic/quic-common/src/main/java/org/eclipse/jetty/quic/common/QuicSession.java @@ -410,7 +410,6 @@ private void finishOutwardClose(Throwable failure) try { endPoints.clear(); - flusher.close(); getQuicConnection().outwardClose(this, failure); } finally @@ -455,13 +454,6 @@ public void onTimeoutExpired() }; } - @Override - public void close() - { - super.close(); - timeout.destroy(); - } - @Override protected Action process() throws IOException { @@ -514,8 +506,7 @@ protected void onCompleteSuccess() { if (LOG.isDebugEnabled()) LOG.debug("connection closed {}", QuicSession.this); - byteBufferPool.release(cipherBuffer); - finishOutwardClose(new ClosedChannelException()); + finish(new ClosedChannelException()); } @Override @@ -523,8 +514,14 @@ protected void onCompleteFailure(Throwable failure) { if (LOG.isDebugEnabled()) LOG.debug("failed to write cipher bytes, closing session on {}", QuicSession.this, failure); + finish(failure); + } + + private void finish(Throwable failure) + { byteBufferPool.release(cipherBuffer); finishOutwardClose(failure); + timeout.destroy(); } } diff --git a/jetty-quic/quic-quiche/quic-quiche-foreign-incubator/src/main/java/org/eclipse/jetty/quic/quiche/foreign/incubator/ForeignIncubatorQuicheConnection.java b/jetty-quic/quic-quiche/quic-quiche-foreign-incubator/src/main/java/org/eclipse/jetty/quic/quiche/foreign/incubator/ForeignIncubatorQuicheConnection.java index e3f8057f5b70..cc119bfb3d0f 100644 --- a/jetty-quic/quic-quiche/quic-quiche-foreign-incubator/src/main/java/org/eclipse/jetty/quic/quiche/foreign/incubator/ForeignIncubatorQuicheConnection.java +++ b/jetty-quic/quic-quiche/quic-quiche-foreign-incubator/src/main/java/org/eclipse/jetty/quic/quiche/foreign/incubator/ForeignIncubatorQuicheConnection.java @@ -29,8 +29,8 @@ import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import org.eclipse.jetty.quic.quiche.Quiche; -import org.eclipse.jetty.quic.quiche.Quiche.quiche_error; import org.eclipse.jetty.quic.quiche.Quiche.quic_error; +import org.eclipse.jetty.quic.quiche.Quiche.quiche_error; import org.eclipse.jetty.quic.quiche.QuicheConfig; import org.eclipse.jetty.quic.quiche.QuicheConnection; import org.eclipse.jetty.util.BufferUtil; @@ -865,7 +865,12 @@ public int feedClearBytesForStream(long streamId, ByteBuffer buffer, boolean las } if (written == quiche_error.QUICHE_ERR_DONE) + { + int rc = quiche_h.quiche_conn_stream_writable(quicheConn, streamId, buffer.remaining()); + if (rc < 0) + throw new IOException("failed to write to stream " + streamId + "; quiche_err=" + quiche_error.errToString(rc)); return 0; + } if (written < 0L) throw new IOException("failed to write to stream " + streamId + "; quiche_err=" + quiche_error.errToString(written)); buffer.position((int)(buffer.position() + written)); diff --git a/jetty-quic/quic-quiche/quic-quiche-foreign-incubator/src/main/java/org/eclipse/jetty/quic/quiche/foreign/incubator/quiche_h.java b/jetty-quic/quic-quiche/quic-quiche-foreign-incubator/src/main/java/org/eclipse/jetty/quic/quiche/foreign/incubator/quiche_h.java index 9994b5bcfe65..2bfad6e253ae 100644 --- a/jetty-quic/quic-quiche/quic-quiche-foreign-incubator/src/main/java/org/eclipse/jetty/quic/quiche/foreign/incubator/quiche_h.java +++ b/jetty-quic/quic-quiche/quic-quiche-foreign-incubator/src/main/java/org/eclipse/jetty/quic/quiche/foreign/incubator/quiche_h.java @@ -310,6 +310,12 @@ public class quiche_h FunctionDescriptor.of(C_LONG, C_POINTER, C_LONG, C_POINTER, C_LONG, C_CHAR) ); + private static final MethodHandle quiche_conn_stream_writable$MH = downcallHandle( + "quiche_conn_stream_writable", + "(Ljdk/incubator/foreign/MemoryAddress;JJ)I", + FunctionDescriptor.of(C_INT, C_POINTER, C_LONG, C_LONG) + ); + private static final MethodHandle quiche_conn_stream_recv$MH = downcallHandle( "quiche_conn_stream_recv", "(Ljdk/incubator/foreign/MemoryAddress;JLjdk/incubator/foreign/MemoryAddress;JLjdk/incubator/foreign/MemoryAddress;)J", @@ -670,6 +676,18 @@ public static long quiche_conn_stream_send(MemoryAddress conn, long stream_id, M } } + public static int quiche_conn_stream_writable(MemoryAddress conn, long stream_id, long buf_len) + { + try + { + return (int) quiche_conn_stream_writable$MH.invokeExact(conn, stream_id, buf_len); + } + catch (Throwable ex) + { + throw new AssertionError("should not reach here", ex); + } + } + public static byte quiche_stream_iter_next(MemoryAddress conn, MemoryAddress stream_id) { try diff --git a/jetty-quic/quic-quiche/quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/JnaQuicheConnection.java b/jetty-quic/quic-quiche/quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/JnaQuicheConnection.java index 5a4f980df8a2..7383aabe777f 100644 --- a/jetty-quic/quic-quiche/quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/JnaQuicheConnection.java +++ b/jetty-quic/quic-quiche/quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/JnaQuicheConnection.java @@ -692,7 +692,12 @@ public int feedClearBytesForStream(long streamId, ByteBuffer buffer, boolean las throw new IOException("connection was released"); int written = LibQuiche.INSTANCE.quiche_conn_stream_send(quicheConn, new uint64_t(streamId), jnaBuffer(buffer), new size_t(buffer.remaining()), last).intValue(); if (written == quiche_error.QUICHE_ERR_DONE) + { + int rc = LibQuiche.INSTANCE.quiche_conn_stream_writable(quicheConn, new uint64_t(streamId), new size_t(buffer.remaining())); + if (rc < 0) + throw new IOException("failed to write to stream " + streamId + "; quiche_err=" + quiche_error.errToString(rc)); return 0; + } if (written < 0L) throw new IOException("failed to write to stream " + streamId + "; quiche_err=" + quiche_error.errToString(written)); buffer.position(buffer.position() + written);