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 c338308c328..31045cf5c57 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 @@ -838,20 +838,21 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection throw new IOException("connection was released"); long written; - if (buffer.isDirect()) + try (ResourceScope scope = ResourceScope.newConfinedScope()) { - // If the ByteBuffer is direct, it can be used without any copy. - MemorySegment bufferSegment = MemorySegment.ofByteBuffer(buffer); - written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, bufferSegment.address(), buffer.remaining(), last ? C_TRUE : C_FALSE); - } - else - { - // If the ByteBuffer is heap-allocated, it must be copied to native memory. - try (ResourceScope scope = ResourceScope.newConfinedScope()) + MemorySegment outErrorCode = MemorySegment.allocateNative(CLinker.C_LONG, scope); + if (buffer.isDirect()) { + // If the ByteBuffer is direct, it can be used without any copy. + MemorySegment bufferSegment = MemorySegment.ofByteBuffer(buffer); + written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, bufferSegment.address(), buffer.remaining(), last ? C_TRUE : C_FALSE, outErrorCode.address()); + } + 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, MemoryAddress.NULL, 0, last ? C_TRUE : C_FALSE); + written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, MemoryAddress.NULL, 0, last ? C_TRUE : C_FALSE, outErrorCode.address()); } else { @@ -859,7 +860,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection int prevPosition = buffer.position(); bufferSegment.asByteBuffer().put(buffer); buffer.position(prevPosition); - written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, bufferSegment.address(), buffer.remaining(), last ? C_TRUE : C_FALSE); + written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, bufferSegment.address(), buffer.remaining(), last ? C_TRUE : C_FALSE, outErrorCode.address()); } } } @@ -889,24 +890,25 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection long read; try (ResourceScope scope = ResourceScope.newConfinedScope()) { + MemorySegment fin = MemorySegment.allocateNative(CLinker.C_CHAR, scope); + MemorySegment outErrorCode = MemorySegment.allocateNative(CLinker.C_LONG, scope); if (buffer.isDirect()) { // If the ByteBuffer is direct, it can be used without any copy. MemorySegment bufferSegment = MemorySegment.ofByteBuffer(buffer); - MemorySegment fin = MemorySegment.allocateNative(CLinker.C_CHAR, scope); - read = quiche_h.quiche_conn_stream_recv(quicheConn, streamId, bufferSegment.address(), buffer.remaining(), fin.address()); + read = quiche_h.quiche_conn_stream_recv(quicheConn, streamId, bufferSegment.address(), buffer.remaining(), fin.address(), outErrorCode.address()); } else { // If the ByteBuffer is heap-allocated, native memory must be copied to it. MemorySegment bufferSegment = MemorySegment.allocateNative(buffer.remaining(), scope); - - MemorySegment fin = MemorySegment.allocateNative(CLinker.C_CHAR, scope); - read = quiche_h.quiche_conn_stream_recv(quicheConn, streamId, bufferSegment.address(), buffer.remaining(), fin.address()); - - int prevPosition = buffer.position(); - buffer.put(bufferSegment.asByteBuffer().limit((int)read)); - buffer.position(prevPosition); + read = quiche_h.quiche_conn_stream_recv(quicheConn, streamId, bufferSegment.address(), buffer.remaining(), fin.address(), outErrorCode.address()); + if (read > 0) + { + int prevPosition = buffer.position(); + buffer.put(bufferSegment.asByteBuffer().limit((int)read)); + buffer.position(prevPosition); + } } } 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 1c7f08db24f..dbe6869f5ac 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 @@ -33,7 +33,7 @@ public class quiche_h { // 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. - private static final String EXPECTED_QUICHE_VERSION = "0.21.0"; + private static final String EXPECTED_QUICHE_VERSION = "0.22.0"; public static final byte C_FALSE = 0; public static final byte C_TRUE = 1; @@ -312,8 +312,8 @@ public class quiche_h private static final MethodHandle quiche_conn_stream_send$MH = downcallHandle( "quiche_conn_stream_send", - "(Ljdk/incubator/foreign/MemoryAddress;JLjdk/incubator/foreign/MemoryAddress;JB)J", - FunctionDescriptor.of(C_LONG, C_POINTER, C_LONG, C_POINTER, C_LONG, C_CHAR) + "(Ljdk/incubator/foreign/MemoryAddress;JLjdk/incubator/foreign/MemoryAddress;JBLjdk/incubator/foreign/MemoryAddress;)J", + FunctionDescriptor.of(C_LONG, C_POINTER, C_LONG, C_POINTER, C_LONG, C_CHAR, C_POINTER) ); private static final MethodHandle quiche_conn_stream_writable$MH = downcallHandle( @@ -324,8 +324,8 @@ public class quiche_h 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", - FunctionDescriptor.of(C_LONG, C_POINTER, C_LONG, C_POINTER, C_LONG, C_POINTER) + "(Ljdk/incubator/foreign/MemoryAddress;JLjdk/incubator/foreign/MemoryAddress;JLjdk/incubator/foreign/MemoryAddress;Ljdk/incubator/foreign/MemoryAddress;)J", + FunctionDescriptor.of(C_LONG, C_POINTER, C_LONG, C_POINTER, C_LONG, C_POINTER, C_POINTER) ); private static final MethodHandle quiche_stream_iter_next$MH = downcallHandle( @@ -658,11 +658,11 @@ public class quiche_h } } - public static long quiche_conn_stream_recv(MemoryAddress conn, long stream_id, MemoryAddress buf, long buf_len, MemoryAddress fin) + public static long quiche_conn_stream_recv(MemoryAddress conn, long stream_id, MemoryAddress buf, long buf_len, MemoryAddress fin, MemoryAddress outErrorCode) { try { - return (long) quiche_conn_stream_recv$MH.invokeExact(conn, stream_id, buf, buf_len, fin); + return (long) quiche_conn_stream_recv$MH.invokeExact(conn, stream_id, buf, buf_len, fin, outErrorCode); } catch (Throwable ex) { @@ -670,11 +670,11 @@ public class quiche_h } } - public static long quiche_conn_stream_send(MemoryAddress conn, long stream_id, MemoryAddress buf, long buf_len, byte fin) + public static long quiche_conn_stream_send(MemoryAddress conn, long stream_id, MemoryAddress buf, long buf_len, byte fin, MemoryAddress outErrorCode) { try { - return (long) quiche_conn_stream_send$MH.invokeExact(conn, stream_id, buf, buf_len, fin); + return (long) quiche_conn_stream_send$MH.invokeExact(conn, stream_id, buf, buf_len, fin, outErrorCode); } catch (Throwable ex) { 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 d5567bb2cfa..ce5e7d670bc 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 @@ -690,7 +690,8 @@ public class JnaQuicheConnection extends QuicheConnection { 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())); @@ -742,7 +743,8 @@ public class JnaQuicheConnection extends QuicheConnection 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 < 0L) diff --git a/jetty-quic/quic-quiche/quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/LibQuiche.java b/jetty-quic/quic-quiche/quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/LibQuiche.java index 98c2a6ee714..4a71c6a7685 100644 --- a/jetty-quic/quic-quiche/quic-quiche-jna/src/main/java/org/eclipse/jetty/quic/quiche/jna/LibQuiche.java +++ b/jetty-quic/quic-quiche/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 @@ public interface LibQuiche extends Library 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 66d5c81f5e8..5929fed049a 100644 --- a/pom.xml +++ b/pom.xml @@ -269,7 +269,7 @@ 2.2.1.Final 3.6.0.Final 1.1 - 0.21.0 + 0.22.0 1.2 2.7 1.0.7