diff --git a/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-foreign/src/main/java/org/eclipse/jetty/quic/quiche/foreign/ForeignQuicheConnection.java b/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-foreign/src/main/java/org/eclipse/jetty/quic/quiche/foreign/ForeignQuicheConnection.java index 9aa018d0efe4..b71ee494c3d7 100644 --- a/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-foreign/src/main/java/org/eclipse/jetty/quic/quiche/foreign/ForeignQuicheConnection.java +++ b/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-foreign/src/main/java/org/eclipse/jetty/quic/quiche/foreign/ForeignQuicheConnection.java @@ -853,20 +853,21 @@ public int feedClearBytesForStream(long streamId, ByteBuffer buffer, boolean las throw new IOException("connection was released"); long written; - if (buffer.isDirect()) - { - // If the ByteBuffer is direct, it can be used without any copy. - MemorySegment bufferSegment = MemorySegment.ofBuffer(buffer); - written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, bufferSegment, buffer.remaining(), last); - } - else + try (Arena scope = Arena.ofConfined()) { - // If the ByteBuffer is heap-allocated, it must be copied to native memory. - try (Arena scope = Arena.ofConfined()) + MemorySegment outErrorCode = scope.allocate(NativeHelper.C_LONG); + if (buffer.isDirect()) { + // If the ByteBuffer is direct, it can be used without any copy. + MemorySegment bufferSegment = MemorySegment.ofBuffer(buffer); + written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, bufferSegment, buffer.remaining(), last, outErrorCode); + } + else + { + // If the ByteBuffer is heap-allocated, it must be copied to native memory. if (buffer.remaining() == 0) { - written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, MemorySegment.NULL, 0, last); + written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, MemorySegment.NULL, 0, last, outErrorCode); } else { @@ -874,7 +875,7 @@ public int feedClearBytesForStream(long streamId, ByteBuffer buffer, boolean las int prevPosition = buffer.position(); bufferSegment.asByteBuffer().put(buffer); buffer.position(prevPosition); - written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, bufferSegment, buffer.remaining(), last); + written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, bufferSegment, buffer.remaining(), last, outErrorCode); } } } @@ -904,21 +905,19 @@ public int drainClearBytesForStream(long streamId, ByteBuffer buffer) throws IOE long read; try (Arena scope = Arena.ofConfined()) { + MemorySegment fin = scope.allocate(NativeHelper.C_CHAR); + MemorySegment outErrorCode = scope.allocate(NativeHelper.C_LONG); if (buffer.isDirect()) { // If the ByteBuffer is direct, it can be used without any copy. MemorySegment bufferSegment = MemorySegment.ofBuffer(buffer); - MemorySegment fin = scope.allocate(NativeHelper.C_CHAR); - read = quiche_h.quiche_conn_stream_recv(quicheConn, streamId, bufferSegment, buffer.remaining(), fin); + read = quiche_h.quiche_conn_stream_recv(quicheConn, streamId, bufferSegment, buffer.remaining(), fin, outErrorCode); } else { // If the ByteBuffer is heap-allocated, native memory must be copied to it. MemorySegment bufferSegment = scope.allocate(buffer.remaining()); - - MemorySegment fin = scope.allocate(NativeHelper.C_CHAR); - read = quiche_h.quiche_conn_stream_recv(quicheConn, streamId, bufferSegment, buffer.remaining(), fin); - + read = quiche_h.quiche_conn_stream_recv(quicheConn, streamId, bufferSegment, buffer.remaining(), fin, outErrorCode); if (read > 0) { int prevPosition = buffer.position(); diff --git a/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-foreign/src/main/java/org/eclipse/jetty/quic/quiche/foreign/quiche_h.java b/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-foreign/src/main/java/org/eclipse/jetty/quic/quiche/foreign/quiche_h.java index e55229a8a69d..2125ccfe434a 100644 --- a/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-foreign/src/main/java/org/eclipse/jetty/quic/quiche/foreign/quiche_h.java +++ b/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-foreign/src/main/java/org/eclipse/jetty/quic/quiche/foreign/quiche_h.java @@ -30,7 +30,7 @@ public class quiche_h { - private static final String EXPECTED_QUICHE_VERSION = "0.21.0"; + private static final String EXPECTED_QUICHE_VERSION = "0.22.0"; private static final Logger LOG = LoggerFactory.getLogger(quiche_h.class); private static class LoggingCallback @@ -485,6 +485,7 @@ private static class DowncallHandles C_LONG, C_POINTER, C_LONG, + C_POINTER, C_POINTER )); private static final MethodHandle quiche_conn_stream_send = NativeHelper.downcallHandle( @@ -495,7 +496,8 @@ private static class DowncallHandles C_LONG, C_POINTER, C_LONG, - C_BOOL + C_BOOL, + C_POINTER )); private static final MethodHandle quiche_conn_stream_priority = NativeHelper.downcallHandle( "quiche_conn_stream_priority", @@ -1662,11 +1664,11 @@ public static long quiche_conn_send_quantum_on_path(MemorySegment conn, MemorySe } } - public static long quiche_conn_stream_recv(MemorySegment conn, long stream_id, MemorySegment out, long buf_len, MemorySegment fin) + public static long quiche_conn_stream_recv(MemorySegment conn, long stream_id, MemorySegment out, long buf_len, MemorySegment fin, MemorySegment out_error_code) { try { - return (long)DowncallHandles.quiche_conn_stream_recv.invokeExact(conn, stream_id, out, buf_len, fin); + return (long)DowncallHandles.quiche_conn_stream_recv.invokeExact(conn, stream_id, out, buf_len, fin, out_error_code); } catch (Throwable x) { @@ -1674,11 +1676,11 @@ public static long quiche_conn_stream_recv(MemorySegment conn, long stream_id, M } } - public static long quiche_conn_stream_send(MemorySegment conn, long stream_id, MemorySegment buf, long buf_len, boolean fin) + public static long quiche_conn_stream_send(MemorySegment conn, long stream_id, MemorySegment buf, long buf_len, boolean fin, MemorySegment out_error_code) { try { - return (long)DowncallHandles.quiche_conn_stream_send.invokeExact(conn, stream_id, buf, buf_len, fin); + return (long)DowncallHandles.quiche_conn_stream_send.invokeExact(conn, stream_id, buf, buf_len, fin, out_error_code); } catch (Throwable x) { diff --git a/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/JnaQuicheConnection.java b/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/JnaQuicheConnection.java index b81021957a2d..ba483c9c33a8 100644 --- a/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/JnaQuicheConnection.java +++ b/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/JnaQuicheConnection.java @@ -693,7 +693,8 @@ public int feedClearBytesForStream(long streamId, ByteBuffer buffer, boolean las { if (quicheConn == null) 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(); + uint64_t_pointer outErrorCode = new uint64_t_pointer(); + int written = LibQuiche.INSTANCE.quiche_conn_stream_send(quicheConn, new uint64_t(streamId), jnaBuffer(buffer), new size_t(buffer.remaining()), last, outErrorCode).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())); @@ -745,7 +746,8 @@ public int drainClearBytesForStream(long streamId, ByteBuffer buffer) throws IOE if (quicheConn == null) throw new IOException("connection was released"); bool_pointer fin = new bool_pointer(); - int read = LibQuiche.INSTANCE.quiche_conn_stream_recv(quicheConn, new uint64_t(streamId), buffer, new size_t(buffer.remaining()), fin).intValue(); + uint64_t_pointer outErrorCode = new uint64_t_pointer(); + int read = LibQuiche.INSTANCE.quiche_conn_stream_recv(quicheConn, new uint64_t(streamId), buffer, new size_t(buffer.remaining()), fin, outErrorCode).intValue(); if (read == quiche_error.QUICHE_ERR_DONE) return isStreamFinished(streamId) ? -1 : 0; if (read == quiche_error.QUICHE_ERR_STREAM_RESET) diff --git a/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/LibQuiche.java b/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/LibQuiche.java index 98c2a6ee7148..4a71c6a76855 100644 --- a/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/LibQuiche.java +++ b/jetty-core/jetty-quic/jetty-quic-quiche/jetty-quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/LibQuiche.java @@ -31,7 +31,7 @@ public interface LibQuiche extends Library { // This interface is a translation of the quiche.h header of a specific version. // It needs to be reviewed each time the native lib version changes. - String EXPECTED_QUICHE_VERSION = "0.21.0"; + String EXPECTED_QUICHE_VERSION = "0.22.0"; // The charset used to convert java.lang.String to char * and vice versa. Charset CHARSET = StandardCharsets.UTF_8; @@ -540,10 +540,18 @@ int quiche_conn_stream_shutdown(quiche_conn conn, uint64_t stream_id, void quiche_stream_iter_free(quiche_stream_iter iter); // Reads contiguous data from a stream. - ssize_t quiche_conn_stream_recv(quiche_conn conn, uint64_t stream_id, ByteBuffer out, size_t buf_len, bool_pointer fin); + // out_error_code is only set when STREAM_STOPPED or STREAM_RESET are returned. + // Set to the reported error code associated with STOP_SENDING or STREAM_RESET. + ssize_t quiche_conn_stream_recv(quiche_conn conn, uint64_t stream_id, + ByteBuffer out, size_t buf_len, bool_pointer fin, + uint64_t_pointer out_error_code); // Writes data to a stream. - ssize_t quiche_conn_stream_send(quiche_conn conn, uint64_t stream_id, ByteBuffer buf, size_t buf_len, boolean fin); + // out_error_code is only set when STREAM_STOPPED or STREAM_RESET are returned. + // Set to the reported error code associated with STOP_SENDING or STREAM_RESET. + ssize_t quiche_conn_stream_send(quiche_conn conn, uint64_t stream_id, + ByteBuffer buf, size_t buf_len, boolean fin, + uint64_t_pointer out_error_code); // Frees the connection object. void quiche_conn_free(quiche_conn conn); diff --git a/pom.xml b/pom.xml index c75f6e496c5c..233b7873695c 100644 --- a/pom.xml +++ b/pom.xml @@ -214,7 +214,7 @@ 2.2.1.Final 3.5.3.Final 1.1 - 0.21.0 + 0.22.0 1.2 2.7 1.0.7