From d2e76b077b5d56575f78abb70613087bcfc8173a Mon Sep 17 00:00:00 2001 From: Ludovic Orban Date: Tue, 9 Nov 2021 09:18:40 +0100 Subject: [PATCH] Issue #6728 - QUIC and HTTP/3 - commonalize quiche constants across bindings --- .../org/eclipse/jetty/quic/quiche/Quiche.java | 95 +++++++++++++++- .../ForeignIncubatorQuicheConnection.java | 97 ++++++++-------- .../quiche/foreign/incubator/quiche_h.java | 101 ----------------- .../foreign/incubator/LowLevelQuicheTest.java | 9 +- .../quic/quiche/jna/JnaQuicheConnection.java | 67 +++++------ .../jetty/quic/quiche/jna/LibQuiche.java | 106 ------------------ .../quic/quiche/jna/LowLevelQuicheTest.java | 9 +- 7 files changed, 190 insertions(+), 294 deletions(-) diff --git a/jetty-quic/quic-quiche/quic-quiche-common/src/main/java/org/eclipse/jetty/quic/quiche/Quiche.java b/jetty-quic/quic-quiche/quic-quiche-common/src/main/java/org/eclipse/jetty/quic/quiche/Quiche.java index d7e80d176a3..294f3b54fee 100644 --- a/jetty-quic/quic-quiche/quic-quiche-common/src/main/java/org/eclipse/jetty/quic/quiche/Quiche.java +++ b/jetty-quic/quic-quiche/quic-quiche-common/src/main/java/org/eclipse/jetty/quic/quiche/Quiche.java @@ -13,16 +13,109 @@ package org.eclipse.jetty.quic.quiche; -interface Quiche +public interface Quiche { // The current QUIC wire version. int QUICHE_PROTOCOL_VERSION = 0x00000001; // The maximum length of a connection ID. int QUICHE_MAX_CONN_ID_LEN = 20; + // The minimum length of Initial packets sent by a client. + int QUICHE_MIN_CLIENT_INITIAL_LEN = 1200; interface quiche_cc_algorithm { int QUICHE_CC_RENO = 0, QUICHE_CC_CUBIC = 1; } + + interface quiche_error + { + // There is no more work to do. + long QUICHE_ERR_DONE = -1, + + // The provided buffer is too short. + QUICHE_ERR_BUFFER_TOO_SHORT = -2, + + // The provided packet cannot be parsed because its version is unknown. + QUICHE_ERR_UNKNOWN_VERSION = -3, + + // The provided packet cannot be parsed because it contains an invalid + // frame. + QUICHE_ERR_INVALID_FRAME = -4, + + // The provided packet cannot be parsed. + QUICHE_ERR_INVALID_PACKET = -5, + + // The operation cannot be completed because the connection is in an + // invalid state. + QUICHE_ERR_INVALID_STATE = -6, + + // The operation cannot be completed because the stream is in an + // invalid state. + QUICHE_ERR_INVALID_STREAM_STATE = -7, + + // The peer's transport params cannot be parsed. + QUICHE_ERR_INVALID_TRANSPORT_PARAM = -8, + + // A cryptographic operation failed. + QUICHE_ERR_CRYPTO_FAIL = -9, + + // The TLS handshake failed. + QUICHE_ERR_TLS_FAIL = -10, + + // The peer violated the local flow control limits. + QUICHE_ERR_FLOW_CONTROL = -11, + + // The peer violated the local stream limits. + QUICHE_ERR_STREAM_LIMIT = -12, + + // The specified stream was stopped by the peer. + QUICHE_ERR_STREAM_STOPPED = -15, + + // The specified stream was reset by the peer. + QUICHE_ERR_STREAM_RESET = -16, + + // The received data exceeds the stream's final size. + QUICHE_ERR_FINAL_SIZE = -13, + + // Error in congestion control. + QUICHE_ERR_CONGESTION_CONTROL = -14; + + static String errToString(long err) + { + if (err == QUICHE_ERR_DONE) + return "QUICHE_ERR_DONE"; + if (err == QUICHE_ERR_BUFFER_TOO_SHORT) + return "QUICHE_ERR_BUFFER_TOO_SHORT"; + if (err == QUICHE_ERR_UNKNOWN_VERSION) + return "QUICHE_ERR_UNKNOWN_VERSION"; + if (err == QUICHE_ERR_INVALID_FRAME) + return "QUICHE_ERR_INVALID_FRAME"; + if (err == QUICHE_ERR_INVALID_PACKET) + return "QUICHE_ERR_INVALID_PACKET"; + if (err == QUICHE_ERR_INVALID_STATE) + return "QUICHE_ERR_INVALID_STATE"; + if (err == QUICHE_ERR_INVALID_STREAM_STATE) + return "QUICHE_ERR_INVALID_STREAM_STATE"; + if (err == QUICHE_ERR_INVALID_TRANSPORT_PARAM) + return "QUICHE_ERR_INVALID_TRANSPORT_PARAM"; + if (err == QUICHE_ERR_CRYPTO_FAIL) + return "QUICHE_ERR_CRYPTO_FAIL"; + if (err == QUICHE_ERR_TLS_FAIL) + return "QUICHE_ERR_TLS_FAIL"; + if (err == QUICHE_ERR_FLOW_CONTROL) + return "QUICHE_ERR_FLOW_CONTROL"; + if (err == QUICHE_ERR_STREAM_LIMIT) + return "QUICHE_ERR_STREAM_LIMIT"; + if (err == QUICHE_ERR_FINAL_SIZE) + return "QUICHE_ERR_FINAL_SIZE"; + if (err == QUICHE_ERR_CONGESTION_CONTROL) + return "QUICHE_ERR_CONGESTION_CONTROL"; + if (err == QUICHE_ERR_STREAM_STOPPED) + return "QUICHE_ERR_STREAM_STOPPED"; + if (err == QUICHE_ERR_STREAM_RESET) + return "QUICHE_ERR_STREAM_RESET"; + return "?? " + err; + } + } } 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 17a8a620618..b53fa30faea 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 @@ -28,6 +28,7 @@ import jdk.incubator.foreign.CLinker; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; +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; @@ -35,6 +36,10 @@ import org.eclipse.jetty.util.thread.AutoLock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.eclipse.jetty.quic.quiche.Quiche.QUICHE_MAX_CONN_ID_LEN; +import static org.eclipse.jetty.quic.quiche.foreign.incubator.quiche_h.C_FALSE; +import static org.eclipse.jetty.quic.quiche.foreign.incubator.quiche_h.C_TRUE; + public class ForeignIncubatorQuicheConnection extends QuicheConnection { private static final Logger LOG = LoggerFactory.getLogger(ForeignIncubatorQuicheConnection.class); @@ -67,12 +72,12 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection MemorySegment version = MemorySegment.allocateNative(CLinker.C_INT, scope); // Source Connection ID - MemorySegment scid = MemorySegment.allocateNative(quiche_h.QUICHE_MAX_CONN_ID_LEN, scope); + MemorySegment scid = MemorySegment.allocateNative(QUICHE_MAX_CONN_ID_LEN, scope); MemorySegment scid_len = MemorySegment.allocateNative(CLinker.C_LONG, scope); scid_len.asByteBuffer().order(ByteOrder.nativeOrder()).putLong(scid.byteSize()); // Destination Connection ID - MemorySegment dcid = MemorySegment.allocateNative(quiche_h.QUICHE_MAX_CONN_ID_LEN, scope); + MemorySegment dcid = MemorySegment.allocateNative(QUICHE_MAX_CONN_ID_LEN, scope); MemorySegment dcid_len = MemorySegment.allocateNative(CLinker.C_LONG, scope); dcid_len.asByteBuffer().order(ByteOrder.nativeOrder()).putLong(dcid.byteSize()); @@ -87,7 +92,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection { // If the ByteBuffer is direct, it can be used without any copy. MemorySegment packetReadSegment = MemorySegment.ofByteBuffer(packet); - rc = quiche_h.quiche_header_info(packetReadSegment.address(), packet.remaining(), quiche_h.QUICHE_MAX_CONN_ID_LEN, + rc = quiche_h.quiche_header_info(packetReadSegment.address(), packet.remaining(), QUICHE_MAX_CONN_ID_LEN, version.address(), type.address(), scid.address(), scid_len.address(), dcid.address(), dcid_len.address(), @@ -100,7 +105,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection int prevPosition = packet.position(); packetReadSegment.asByteBuffer().order(ByteOrder.nativeOrder()).put(packet); packet.position(prevPosition); - rc = quiche_h.quiche_header_info(packetReadSegment.address(), packet.remaining(), quiche_h.QUICHE_MAX_CONN_ID_LEN, + rc = quiche_h.quiche_header_info(packetReadSegment.address(), packet.remaining(), QUICHE_MAX_CONN_ID_LEN, version.address(), type.address(), scid.address(), scid_len.address(), dcid.address(), dcid_len.address(), @@ -121,13 +126,13 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection public static ForeignIncubatorQuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress peer) throws IOException { - return connect(quicheConfig, peer, quiche_h.QUICHE_MAX_CONN_ID_LEN); + return connect(quicheConfig, peer, QUICHE_MAX_CONN_ID_LEN); } public static ForeignIncubatorQuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress peer, int connectionIdLength) throws IOException { - if (connectionIdLength > quiche_h.QUICHE_MAX_CONN_ID_LEN) - throw new IOException("Connection ID length is too large: " + connectionIdLength + " > " + quiche_h.QUICHE_MAX_CONN_ID_LEN); + if (connectionIdLength > QUICHE_MAX_CONN_ID_LEN) + throw new IOException("Connection ID length is too large: " + connectionIdLength + " > " + QUICHE_MAX_CONN_ID_LEN); ResourceScope scope = ResourceScope.newSharedScope(); byte[] scidBytes = new byte[connectionIdLength]; SECURE_RANDOM.nextBytes(scidBytes); @@ -148,7 +153,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection Boolean verifyPeer = config.getVerifyPeer(); if (verifyPeer != null) - quiche_h.quiche_config_verify_peer(quicheConfig, verifyPeer ? quiche_h.C_TRUE : quiche_h.C_FALSE); + quiche_h.quiche_config_verify_peer(quicheConfig, verifyPeer ? C_TRUE : C_FALSE); String certChainPemPath = config.getCertChainPemPath(); if (certChainPemPath != null) @@ -208,7 +213,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection Boolean disableActiveMigration = config.getDisableActiveMigration(); if (disableActiveMigration != null) - quiche_h.quiche_config_set_disable_active_migration(quicheConfig, disableActiveMigration ? quiche_h.C_TRUE : quiche_h.C_FALSE); + quiche_h.quiche_config_set_disable_active_migration(quicheConfig, disableActiveMigration ? C_TRUE : C_FALSE); return quicheConfig; } @@ -236,12 +241,12 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection MemorySegment version = MemorySegment.allocateNative(CLinker.C_INT, scope); // Source Connection ID - MemorySegment scid = MemorySegment.allocateNative(quiche_h.QUICHE_MAX_CONN_ID_LEN, scope); + MemorySegment scid = MemorySegment.allocateNative(QUICHE_MAX_CONN_ID_LEN, scope); MemorySegment scid_len = MemorySegment.allocateNative(CLinker.C_LONG, scope); scid_len.asByteBuffer().order(ByteOrder.nativeOrder()).putLong(scid.byteSize()); // Destination Connection ID - MemorySegment dcid = MemorySegment.allocateNative(quiche_h.QUICHE_MAX_CONN_ID_LEN, scope); + MemorySegment dcid = MemorySegment.allocateNative(QUICHE_MAX_CONN_ID_LEN, scope); MemorySegment dcid_len = MemorySegment.allocateNative(CLinker.C_LONG, scope); dcid_len.asByteBuffer().order(ByteOrder.nativeOrder()).putLong(dcid.byteSize()); @@ -250,13 +255,13 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection token_len.asByteBuffer().order(ByteOrder.nativeOrder()).putLong(token.byteSize()); LOG.debug("getting header info (negotiate)..."); - int rc = quiche_h.quiche_header_info(packetReadSegment.address(), packetRead.remaining(), quiche_h.QUICHE_MAX_CONN_ID_LEN, + int rc = quiche_h.quiche_header_info(packetReadSegment.address(), packetRead.remaining(), QUICHE_MAX_CONN_ID_LEN, version.address(), type.address(), scid.address(), scid_len.address(), dcid.address(), dcid_len.address(), token.address(), token_len.address()); if (rc < 0) - throw new IOException("failed to parse header: " + quiche_h.quiche_error.errToString(rc)); + throw new IOException("failed to parse header: " + quiche_error.errToString(rc)); packetRead.position(packetRead.limit()); LOG.debug("version: {}", version.asByteBuffer().order(ByteOrder.nativeOrder()).getInt()); @@ -265,7 +270,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection LOG.debug("dcid len: {}", dcid_len.asByteBuffer().order(ByteOrder.nativeOrder()).getLong()); LOG.debug("token len: {}", token_len.asByteBuffer().order(ByteOrder.nativeOrder()).getLong()); - if (quiche_h.quiche_version_is_supported(version.asByteBuffer().order(ByteOrder.nativeOrder()).getInt()) == quiche_h.C_FALSE) + if (quiche_h.quiche_version_is_supported(version.asByteBuffer().order(ByteOrder.nativeOrder()).getInt()) == C_FALSE) { LOG.debug("version negotiation"); @@ -283,7 +288,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection long generated = quiche_h.quiche_negotiate_version(scid.address(), scid_len.asByteBuffer().order(ByteOrder.nativeOrder()).getLong(), dcid.address(), dcid_len.asByteBuffer().order(ByteOrder.nativeOrder()).getLong(), packetToSendSegment.address(), packetToSend.remaining()); if (generated < 0) - throw new IOException("failed to create vneg packet : " + quiche_h.quiche_error.errToString(generated)); + throw new IOException("failed to create vneg packet : " + quiche_error.errToString(generated)); if (!packetToSend.isDirect()) packetToSend.put(packetToSendSegment.asByteBuffer().order(ByteOrder.nativeOrder()).limit((int)generated)); else @@ -300,7 +305,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection byte[] tokenBytes = tokenMinter.mint(dcidBytes, dcidBytes.length); token.asByteBuffer().order(ByteOrder.nativeOrder()).put(tokenBytes); - byte[] newCid = new byte[quiche_h.QUICHE_MAX_CONN_ID_LEN]; + byte[] newCid = new byte[QUICHE_MAX_CONN_ID_LEN]; SECURE_RANDOM.nextBytes(newCid); MemorySegment newCidSegment = MemorySegment.allocateNative(newCid.length, scope); newCidSegment.asByteBuffer().order(ByteOrder.nativeOrder()).put(newCid); @@ -325,7 +330,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection packetToSendSegment.address(), packetToSendSegment.byteSize() ); if (generated < 0) - throw new IOException("failed to create retry packet: " + quiche_h.quiche_error.errToString(generated)); + throw new IOException("failed to create retry packet: " + quiche_error.errToString(generated)); if (!packetToSend.isDirect()) packetToSend.put(packetToSendSegment.asByteBuffer().order(ByteOrder.nativeOrder()).limit((int)generated)); else @@ -345,12 +350,12 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection MemorySegment version = MemorySegment.allocateNative(CLinker.C_INT, scope); // Source Connection ID - MemorySegment scid = MemorySegment.allocateNative(quiche_h.QUICHE_MAX_CONN_ID_LEN, scope); + MemorySegment scid = MemorySegment.allocateNative(QUICHE_MAX_CONN_ID_LEN, scope); MemorySegment scid_len = MemorySegment.allocateNative(CLinker.C_LONG, scope); scid_len.asByteBuffer().order(ByteOrder.nativeOrder()).putLong(scid.byteSize()); // Destination Connection ID - MemorySegment dcid = MemorySegment.allocateNative(quiche_h.QUICHE_MAX_CONN_ID_LEN, scope); + MemorySegment dcid = MemorySegment.allocateNative(QUICHE_MAX_CONN_ID_LEN, scope); MemorySegment dcid_len = MemorySegment.allocateNative(CLinker.C_LONG, scope); dcid_len.asByteBuffer().order(ByteOrder.nativeOrder()).putLong(dcid.byteSize()); @@ -365,7 +370,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection { // If the ByteBuffer is direct, it can be used without any copy. MemorySegment packetReadSegment = MemorySegment.ofByteBuffer(packetRead); - rc = quiche_h.quiche_header_info(packetReadSegment.address(), packetRead.remaining(), quiche_h.QUICHE_MAX_CONN_ID_LEN, + rc = quiche_h.quiche_header_info(packetReadSegment.address(), packetRead.remaining(), QUICHE_MAX_CONN_ID_LEN, version.address(), type.address(), scid.address(), scid_len.address(), dcid.address(), dcid_len.address(), @@ -380,7 +385,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection int prevPosition = packetRead.position(); packetReadSegment.asByteBuffer().order(ByteOrder.nativeOrder()).put(packetRead); packetRead.position(prevPosition); - rc = quiche_h.quiche_header_info(packetReadSegment.address(), packetRead.remaining(), quiche_h.QUICHE_MAX_CONN_ID_LEN, + rc = quiche_h.quiche_header_info(packetReadSegment.address(), packetRead.remaining(), QUICHE_MAX_CONN_ID_LEN, version.address(), type.address(), scid.address(), scid_len.address(), dcid.address(), dcid_len.address(), @@ -390,7 +395,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection if (rc < 0) { scope.close(); - throw new IOException("failed to parse header: " + quiche_h.quiche_error.errToString(rc)); + throw new IOException("failed to parse header: " + quiche_error.errToString(rc)); } LOG.debug("version: {}", version.asByteBuffer().order(ByteOrder.nativeOrder()).getInt()); @@ -399,7 +404,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection LOG.debug("dcid len: {}", dcid_len.asByteBuffer().order(ByteOrder.nativeOrder()).getLong()); LOG.debug("token len: {}", token_len.asByteBuffer().order(ByteOrder.nativeOrder()).getLong()); - if (quiche_h.quiche_version_is_supported(version.asByteBuffer().order(ByteOrder.nativeOrder()).getInt()) == quiche_h.C_FALSE) + if (quiche_h.quiche_version_is_supported(version.asByteBuffer().order(ByteOrder.nativeOrder()).getInt()) == C_FALSE) { LOG.debug("need version negotiation"); scope.close(); @@ -469,7 +474,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection try (ResourceScope scope = ResourceScope.newConfinedScope()) { MemorySegment streamIdSegment = MemorySegment.allocateNative(CLinker.C_LONG, scope); - while (quiche_h.quiche_stream_iter_next(quiche_stream_iter, streamIdSegment.address()) != quiche_h.C_FALSE) + while (quiche_h.quiche_stream_iter_next(quiche_stream_iter, streamIdSegment.address()) != C_FALSE) { long streamId = streamIdSegment.asByteBuffer().order(ByteOrder.nativeOrder()).getLong(); result.add(streamId); @@ -510,7 +515,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection } } if (received < 0) - throw new IOException("failed to receive packet; err=" + quiche_h.quiche_error.errToString(received)); + throw new IOException("failed to receive packet; err=" + quiche_error.errToString(received)); buffer.position((int)(buffer.position() + received)); return (int)received; } @@ -544,10 +549,10 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection } } - if (written == quiche_h.quiche_error.QUICHE_ERR_DONE) + if (written == quiche_error.QUICHE_ERR_DONE) return 0; if (written < 0L) - throw new IOException("failed to send packet; err=" + quiche_h.quiche_error.errToString(written)); + throw new IOException("failed to send packet; err=" + quiche_error.errToString(written)); buffer.position((int)(prevPosition + written)); return (int)written; } @@ -560,7 +565,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection { if (quicheConn == null) throw new IllegalStateException("connection was released"); - return quiche_h.quiche_conn_is_closed(quicheConn) != quiche_h.C_FALSE; + return quiche_h.quiche_conn_is_closed(quicheConn) != C_FALSE; } } @@ -571,7 +576,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection { if (quicheConn == null) throw new IllegalStateException("connection was released"); - return quiche_h.quiche_conn_is_established(quicheConn) != quiche_h.C_FALSE; + return quiche_h.quiche_conn_is_established(quicheConn) != C_FALSE; } } @@ -636,7 +641,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection int rc; if (reason == null) { - rc = quiche_h.quiche_conn_close(quicheConn, quiche_h.C_TRUE, error, MemoryAddress.NULL, 0); + rc = quiche_h.quiche_conn_close(quicheConn, C_TRUE, error, MemoryAddress.NULL, 0); } else { @@ -647,16 +652,16 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection reasonSegment.asByteBuffer().order(ByteOrder.nativeOrder()).put(reasonBytes); int length = reasonBytes.length; MemoryAddress reasonAddress = reasonSegment.address(); - rc = quiche_h.quiche_conn_close(quicheConn, quiche_h.C_TRUE, error, reasonAddress, length); + rc = quiche_h.quiche_conn_close(quicheConn, C_TRUE, error, reasonAddress, length); } } if (rc == 0) return true; - if (rc == quiche_h.quiche_error.QUICHE_ERR_DONE) + if (rc == quiche_error.QUICHE_ERR_DONE) return false; if (LOG.isDebugEnabled()) - LOG.debug("could not close connection: {}", quiche_h.quiche_error.errToString(rc)); + LOG.debug("could not close connection: {}", quiche_error.errToString(rc)); return false; } } @@ -690,7 +695,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection { if (quicheConn == null) throw new IllegalStateException("connection was released"); - return quiche_h.quiche_conn_is_draining(quicheConn) != quiche_h.C_FALSE; + return quiche_h.quiche_conn_is_draining(quicheConn) != C_FALSE; } } @@ -729,7 +734,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection if (value < 0) { if (LOG.isDebugEnabled()) - LOG.debug("could not read window capacity for stream {} err={}", streamId, quiche_h.quiche_error.errToString(value)); + LOG.debug("could not read window capacity for stream {} err={}", streamId, quiche_error.errToString(value)); } return value; } @@ -744,9 +749,9 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection throw new IOException("connection was released"); int direction = writeSide ? quiche_h.quiche_shutdown.QUICHE_SHUTDOWN_WRITE : quiche_h.quiche_shutdown.QUICHE_SHUTDOWN_READ; int rc = quiche_h.quiche_conn_stream_shutdown(quicheConn, streamId, direction, error); - if (rc == 0 || rc == quiche_h.quiche_error.QUICHE_ERR_DONE) + if (rc == 0 || rc == quiche_error.QUICHE_ERR_DONE) return; - throw new IOException("failed to shutdown stream " + streamId + ": " + quiche_h.quiche_error.errToString(rc)); + throw new IOException("failed to shutdown stream " + streamId + ": " + quiche_error.errToString(rc)); } } @@ -763,7 +768,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection { // 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 ? quiche_h.C_TRUE : quiche_h.C_FALSE); + written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, bufferSegment.address(), buffer.remaining(), last ? C_TRUE : C_FALSE); } else { @@ -772,7 +777,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection { if (buffer.remaining() == 0) { - written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, MemoryAddress.NULL, 0, last ? quiche_h.C_TRUE : quiche_h.C_FALSE); + written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, MemoryAddress.NULL, 0, last ? C_TRUE : C_FALSE); } else { @@ -780,15 +785,15 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection int prevPosition = buffer.position(); bufferSegment.asByteBuffer().order(ByteOrder.nativeOrder()).put(buffer); buffer.position(prevPosition); - written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, bufferSegment.address(), buffer.remaining(), last ? quiche_h.C_TRUE : quiche_h.C_FALSE); + written = quiche_h.quiche_conn_stream_send(quicheConn, streamId, bufferSegment.address(), buffer.remaining(), last ? C_TRUE : C_FALSE); } } } - if (written == quiche_h.quiche_error.QUICHE_ERR_DONE) + if (written == quiche_error.QUICHE_ERR_DONE) return 0; if (written < 0L) - throw new IOException("failed to write to stream " + streamId + "; err=" + quiche_h.quiche_error.errToString(written)); + throw new IOException("failed to write to stream " + streamId + "; err=" + quiche_error.errToString(written)); buffer.position((int)(buffer.position() + written)); return (int)written; } @@ -826,10 +831,10 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection } } - if (read == quiche_h.quiche_error.QUICHE_ERR_DONE) + if (read == quiche_error.QUICHE_ERR_DONE) return isStreamFinished(streamId) ? -1 : 0; if (read < 0L) - throw new IOException("failed to read from stream " + streamId + "; err=" + quiche_h.quiche_error.errToString(read)); + throw new IOException("failed to read from stream " + streamId + "; err=" + quiche_error.errToString(read)); buffer.position((int)(buffer.position() + read)); return (int)read; } @@ -842,7 +847,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection { if (quicheConn == null) throw new IllegalStateException("connection was released"); - return quiche_h.quiche_conn_stream_finished(quicheConn, streamId) != quiche_h.C_FALSE; + return quiche_h.quiche_conn_stream_finished(quicheConn, streamId) != C_FALSE; } } @@ -859,7 +864,7 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection MemorySegment error = MemorySegment.allocateNative(CLinker.C_LONG, scope); MemorySegment reason = MemorySegment.allocateNative(CLinker.C_POINTER, scope); MemorySegment reasonLength = MemorySegment.allocateNative(CLinker.C_LONG, scope); - if (quiche_h.quiche_conn_peer_error(quicheConn, app.address(), error.address(), reason.address(), reasonLength.address()) != quiche_h.C_FALSE) + if (quiche_h.quiche_conn_peer_error(quicheConn, app.address(), error.address(), reason.address(), reasonLength.address()) != C_FALSE) { long errorValue = error.asByteBuffer().order(ByteOrder.nativeOrder()).getLong(); long reasonLengthValue = reasonLength.asByteBuffer().order(ByteOrder.nativeOrder()).getLong(); 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 6881d663af1..68062a397aa 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 @@ -322,113 +322,12 @@ public class quiche_h FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER) ); - public interface quiche_error - { - // There is no more work to do. - long QUICHE_ERR_DONE = -1, - - // The provided buffer is too short. - QUICHE_ERR_BUFFER_TOO_SHORT = -2, - - // The provided packet cannot be parsed because its version is unknown. - QUICHE_ERR_UNKNOWN_VERSION = -3, - - // The provided packet cannot be parsed because it contains an invalid - // frame. - QUICHE_ERR_INVALID_FRAME = -4, - - // The provided packet cannot be parsed. - QUICHE_ERR_INVALID_PACKET = -5, - - // The operation cannot be completed because the connection is in an - // invalid state. - QUICHE_ERR_INVALID_STATE = -6, - - // The operation cannot be completed because the stream is in an - // invalid state. - QUICHE_ERR_INVALID_STREAM_STATE = -7, - - // The peer's transport params cannot be parsed. - QUICHE_ERR_INVALID_TRANSPORT_PARAM = -8, - - // A cryptographic operation failed. - QUICHE_ERR_CRYPTO_FAIL = -9, - - // The TLS handshake failed. - QUICHE_ERR_TLS_FAIL = -10, - - // The peer violated the local flow control limits. - QUICHE_ERR_FLOW_CONTROL = -11, - - // The peer violated the local stream limits. - QUICHE_ERR_STREAM_LIMIT = -12, - - // The specified stream was stopped by the peer. - QUICHE_ERR_STREAM_STOPPED = -15, - - // The specified stream was reset by the peer. - QUICHE_ERR_STREAM_RESET = -16, - - // The received data exceeds the stream's final size. - QUICHE_ERR_FINAL_SIZE = -13, - - // Error in congestion control. - QUICHE_ERR_CONGESTION_CONTROL = -14; - - static String errToString(long err) - { - if (err == QUICHE_ERR_DONE) - return "QUICHE_ERR_DONE"; - if (err == QUICHE_ERR_BUFFER_TOO_SHORT) - return "QUICHE_ERR_BUFFER_TOO_SHORT"; - if (err == QUICHE_ERR_UNKNOWN_VERSION) - return "QUICHE_ERR_UNKNOWN_VERSION"; - if (err == QUICHE_ERR_INVALID_FRAME) - return "QUICHE_ERR_INVALID_FRAME"; - if (err == QUICHE_ERR_INVALID_PACKET) - return "QUICHE_ERR_INVALID_PACKET"; - if (err == QUICHE_ERR_INVALID_STATE) - return "QUICHE_ERR_INVALID_STATE"; - if (err == QUICHE_ERR_INVALID_STREAM_STATE) - return "QUICHE_ERR_INVALID_STREAM_STATE"; - if (err == QUICHE_ERR_INVALID_TRANSPORT_PARAM) - return "QUICHE_ERR_INVALID_TRANSPORT_PARAM"; - if (err == QUICHE_ERR_CRYPTO_FAIL) - return "QUICHE_ERR_CRYPTO_FAIL"; - if (err == QUICHE_ERR_TLS_FAIL) - return "QUICHE_ERR_TLS_FAIL"; - if (err == QUICHE_ERR_FLOW_CONTROL) - return "QUICHE_ERR_FLOW_CONTROL"; - if (err == QUICHE_ERR_STREAM_LIMIT) - return "QUICHE_ERR_STREAM_LIMIT"; - if (err == QUICHE_ERR_FINAL_SIZE) - return "QUICHE_ERR_FINAL_SIZE"; - if (err == QUICHE_ERR_CONGESTION_CONTROL) - return "QUICHE_ERR_CONGESTION_CONTROL"; - if (err == QUICHE_ERR_STREAM_STOPPED) - return "QUICHE_ERR_STREAM_STOPPED"; - if (err == QUICHE_ERR_STREAM_RESET) - return "QUICHE_ERR_STREAM_RESET"; - return "?? " + err; - } - } - public interface quiche_shutdown { int QUICHE_SHUTDOWN_READ = 0, QUICHE_SHUTDOWN_WRITE = 1; } - public interface quiche_cc_algorithm - { - int QUICHE_CC_RENO = 0, - QUICHE_CC_CUBIC = 1; - } - - public static int QUICHE_MIN_CLIENT_INITIAL_LEN = 1200; - public static int QUICHE_MAX_CONN_ID_LEN = 20; - public static int QUICHE_PROTOCOL_VERSION = 0x00000001; - public static MemoryAddress quiche_config_new(int version) { try diff --git a/jetty-quic/quic-quiche/quic-quiche-foreign-incubator/src/test/java/org/eclipse/jetty/quic/quiche/foreign/incubator/LowLevelQuicheTest.java b/jetty-quic/quic-quiche/quic-quiche-foreign-incubator/src/test/java/org/eclipse/jetty/quic/quiche/foreign/incubator/LowLevelQuicheTest.java index 8c2611d05aa..f4d97e3a0bf 100644 --- a/jetty-quic/quic-quiche/quic-quiche-foreign-incubator/src/test/java/org/eclipse/jetty/quic/quiche/foreign/incubator/LowLevelQuicheTest.java +++ b/jetty-quic/quic-quiche/quic-quiche-foreign-incubator/src/test/java/org/eclipse/jetty/quic/quiche/foreign/incubator/LowLevelQuicheTest.java @@ -33,6 +33,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static org.eclipse.jetty.quic.quiche.Quiche.QUICHE_MIN_CLIENT_INITIAL_LEN; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; @@ -187,7 +188,7 @@ public class LowLevelQuicheTest { ForeignIncubatorQuicheConnection clientQuicheConnection = entry.getKey(); ForeignIncubatorQuicheConnection serverQuicheConnection = entry.getValue(); - ByteBuffer buffer = ByteBuffer.allocate(quiche_h.QUICHE_MIN_CLIENT_INITIAL_LEN); + ByteBuffer buffer = ByteBuffer.allocate(QUICHE_MIN_CLIENT_INITIAL_LEN); int drained = serverQuicheConnection.drainCipherBytes(buffer); assertThat(drained, is(expectedSize)); @@ -200,7 +201,7 @@ public class LowLevelQuicheTest { ForeignIncubatorQuicheConnection clientQuicheConnection = entry.getKey(); ForeignIncubatorQuicheConnection serverQuicheConnection = entry.getValue(); - ByteBuffer buffer = ByteBuffer.allocate(quiche_h.QUICHE_MIN_CLIENT_INITIAL_LEN); + ByteBuffer buffer = ByteBuffer.allocate(QUICHE_MIN_CLIENT_INITIAL_LEN); int drained = clientQuicheConnection.drainCipherBytes(buffer); assertThat(drained, is(expectedSize)); @@ -211,8 +212,8 @@ public class LowLevelQuicheTest private Map.Entry connectClientToServer() throws IOException { - ByteBuffer buffer = ByteBuffer.allocate(quiche_h.QUICHE_MIN_CLIENT_INITIAL_LEN); - ByteBuffer buffer2 = ByteBuffer.allocate(quiche_h.QUICHE_MIN_CLIENT_INITIAL_LEN); + ByteBuffer buffer = ByteBuffer.allocate(QUICHE_MIN_CLIENT_INITIAL_LEN); + ByteBuffer buffer2 = ByteBuffer.allocate(QUICHE_MIN_CLIENT_INITIAL_LEN); ForeignIncubatorQuicheConnection clientQuicheConnection = ForeignIncubatorQuicheConnection.connect(clientQuicheConfig, serverSocketAddress); connectionsToDisposeOf.add(clientQuicheConnection); 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 215b4a34683..dca9879af9a 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 @@ -22,6 +22,7 @@ import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; +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; @@ -29,6 +30,8 @@ import org.eclipse.jetty.util.thread.AutoLock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static org.eclipse.jetty.quic.quiche.Quiche.QUICHE_MAX_CONN_ID_LEN; + public class JnaQuicheConnection extends QuicheConnection { private static final Logger LOG = LoggerFactory.getLogger(JnaQuicheConnection.class); @@ -56,18 +59,18 @@ public class JnaQuicheConnection extends QuicheConnection uint32_t_pointer version = new uint32_t_pointer(); // Source Connection ID - byte[] scid = new byte[LibQuiche.QUICHE_MAX_CONN_ID_LEN]; + byte[] scid = new byte[QUICHE_MAX_CONN_ID_LEN]; size_t_pointer scidLen = new size_t_pointer(scid.length); // Destination Connection ID - byte[] dcid = new byte[LibQuiche.QUICHE_MAX_CONN_ID_LEN]; + byte[] dcid = new byte[QUICHE_MAX_CONN_ID_LEN]; size_t_pointer dcidLen = new size_t_pointer(dcid.length); byte[] token = new byte[QuicheConnection.TokenMinter.MAX_TOKEN_LENGTH]; size_t_pointer tokenLen = new size_t_pointer(token.length); LOG.debug("getting header info (fromPacket)..."); - int rc = LibQuiche.INSTANCE.quiche_header_info(packet, new size_t(packet.remaining()), new size_t(LibQuiche.QUICHE_MAX_CONN_ID_LEN), + int rc = LibQuiche.INSTANCE.quiche_header_info(packet, new size_t(packet.remaining()), new size_t(QUICHE_MAX_CONN_ID_LEN), version, type, scid, scidLen, dcid, dcidLen, @@ -98,13 +101,13 @@ public class JnaQuicheConnection extends QuicheConnection public static JnaQuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress peer) throws IOException { - return connect(quicheConfig, peer, LibQuiche.QUICHE_MAX_CONN_ID_LEN); + return connect(quicheConfig, peer, QUICHE_MAX_CONN_ID_LEN); } public static JnaQuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress peer, int connectionIdLength) throws IOException { - if (connectionIdLength > LibQuiche.QUICHE_MAX_CONN_ID_LEN) - throw new IOException("Connection ID length is too large: " + connectionIdLength + " > " + LibQuiche.QUICHE_MAX_CONN_ID_LEN); + if (connectionIdLength > QUICHE_MAX_CONN_ID_LEN) + throw new IOException("Connection ID length is too large: " + connectionIdLength + " > " + QUICHE_MAX_CONN_ID_LEN); byte[] scid = new byte[connectionIdLength]; SECURE_RANDOM.nextBytes(scid); LibQuiche.quiche_config libQuicheConfig = buildConfig(quicheConfig); @@ -196,17 +199,17 @@ public class JnaQuicheConnection extends QuicheConnection uint8_t_pointer type = new uint8_t_pointer(); uint32_t_pointer version = new uint32_t_pointer(); - byte[] scid = new byte[LibQuiche.QUICHE_MAX_CONN_ID_LEN]; + byte[] scid = new byte[QUICHE_MAX_CONN_ID_LEN]; size_t_pointer scid_len = new size_t_pointer(scid.length); - byte[] dcid = new byte[LibQuiche.QUICHE_MAX_CONN_ID_LEN]; + byte[] dcid = new byte[QUICHE_MAX_CONN_ID_LEN]; size_t_pointer dcid_len = new size_t_pointer(dcid.length); byte[] token = new byte[TokenMinter.MAX_TOKEN_LENGTH]; size_t_pointer token_len = new size_t_pointer(token.length); LOG.debug("getting header info (packetType)..."); - int rc = LibQuiche.INSTANCE.quiche_header_info(packet, new size_t(packet.remaining()), new size_t(LibQuiche.QUICHE_MAX_CONN_ID_LEN), + int rc = LibQuiche.INSTANCE.quiche_header_info(packet, new size_t(packet.remaining()), new size_t(QUICHE_MAX_CONN_ID_LEN), version, type, scid, scid_len, dcid, dcid_len, @@ -228,24 +231,24 @@ public class JnaQuicheConnection extends QuicheConnection uint32_t_pointer version = new uint32_t_pointer(); // Source Connection ID - byte[] scid = new byte[LibQuiche.QUICHE_MAX_CONN_ID_LEN]; + byte[] scid = new byte[QUICHE_MAX_CONN_ID_LEN]; size_t_pointer scid_len = new size_t_pointer(scid.length); // Destination Connection ID - byte[] dcid = new byte[LibQuiche.QUICHE_MAX_CONN_ID_LEN]; + byte[] dcid = new byte[QUICHE_MAX_CONN_ID_LEN]; size_t_pointer dcid_len = new size_t_pointer(dcid.length); byte[] token = new byte[TokenMinter.MAX_TOKEN_LENGTH]; size_t_pointer token_len = new size_t_pointer(token.length); LOG.debug("getting header info (negotiate)..."); - int rc = LibQuiche.INSTANCE.quiche_header_info(packetRead, new size_t(packetRead.remaining()), new size_t(LibQuiche.QUICHE_MAX_CONN_ID_LEN), + int rc = LibQuiche.INSTANCE.quiche_header_info(packetRead, new size_t(packetRead.remaining()), new size_t(QUICHE_MAX_CONN_ID_LEN), version, type, scid, scid_len, dcid, dcid_len, token, token_len); if (rc < 0) - throw new IOException("failed to parse header: " + LibQuiche.quiche_error.errToString(rc)); + throw new IOException("failed to parse header: " + quiche_error.errToString(rc)); packetRead.position(packetRead.limit()); LOG.debug("version: {}", version); @@ -261,7 +264,7 @@ public class JnaQuicheConnection extends QuicheConnection ssize_t generated = LibQuiche.INSTANCE.quiche_negotiate_version(scid, scid_len.getPointee(), dcid, dcid_len.getPointee(), packetToSend, new size_t(packetToSend.remaining())); packetToSend.position(packetToSend.position() + generated.intValue()); if (generated.intValue() < 0) - throw new IOException("failed to create vneg packet : " + LibQuiche.quiche_error.errToString(generated.intValue())); + throw new IOException("failed to create vneg packet : " + quiche_error.errToString(generated.intValue())); return true; } @@ -271,7 +274,7 @@ public class JnaQuicheConnection extends QuicheConnection token = tokenMinter.mint(dcid, (int)dcid_len.getValue()); - byte[] newCid = new byte[LibQuiche.QUICHE_MAX_CONN_ID_LEN]; + byte[] newCid = new byte[QUICHE_MAX_CONN_ID_LEN]; SECURE_RANDOM.nextBytes(newCid); ssize_t generated = LibQuiche.INSTANCE.quiche_retry(scid, scid_len.getPointee(), @@ -283,7 +286,7 @@ public class JnaQuicheConnection extends QuicheConnection ); packetToSend.position(packetToSend.position() + generated.intValue()); if (generated.intValue() < 0) - throw new IOException("failed to create retry packet: " + LibQuiche.quiche_error.errToString(generated.intValue())); + throw new IOException("failed to create retry packet: " + quiche_error.errToString(generated.intValue())); return true; } @@ -300,24 +303,24 @@ public class JnaQuicheConnection extends QuicheConnection uint32_t_pointer version = new uint32_t_pointer(); // Source Connection ID - byte[] scid = new byte[LibQuiche.QUICHE_MAX_CONN_ID_LEN]; + byte[] scid = new byte[QUICHE_MAX_CONN_ID_LEN]; size_t_pointer scid_len = new size_t_pointer(scid.length); // Destination Connection ID - byte[] dcid = new byte[LibQuiche.QUICHE_MAX_CONN_ID_LEN]; + byte[] dcid = new byte[QUICHE_MAX_CONN_ID_LEN]; size_t_pointer dcid_len = new size_t_pointer(dcid.length); byte[] token = new byte[TokenMinter.MAX_TOKEN_LENGTH]; size_t_pointer token_len = new size_t_pointer(token.length); LOG.debug("getting header info (tryAccept)..."); - int rc = LibQuiche.INSTANCE.quiche_header_info(packetRead, new size_t(packetRead.remaining()), new size_t(LibQuiche.QUICHE_MAX_CONN_ID_LEN), + int rc = LibQuiche.INSTANCE.quiche_header_info(packetRead, new size_t(packetRead.remaining()), new size_t(QUICHE_MAX_CONN_ID_LEN), version, type, scid, scid_len, dcid, dcid_len, token, token_len); if (rc < 0) - throw new IOException("failed to parse header: " + LibQuiche.quiche_error.errToString(rc)); + throw new IOException("failed to parse header: " + quiche_error.errToString(rc)); LOG.debug("version: {}", version); LOG.debug("type: {}", type); @@ -418,7 +421,7 @@ public class JnaQuicheConnection extends QuicheConnection info.from_len = s.getSize(); int received = LibQuiche.INSTANCE.quiche_conn_recv(quicheConn, buffer, new size_t(buffer.remaining()), info).intValue(); if (received < 0) - throw new IOException("failed to receive packet; err=" + LibQuiche.quiche_error.errToString(received)); + throw new IOException("failed to receive packet; err=" + quiche_error.errToString(received)); buffer.position(buffer.position() + received); return received; } @@ -442,10 +445,10 @@ public class JnaQuicheConnection extends QuicheConnection quiche_send_info.to = new sockaddr_storage(); quiche_send_info.to_len = new size_t(quiche_send_info.to.size()); int written = LibQuiche.INSTANCE.quiche_conn_send(quicheConn, buffer, new size_t(buffer.remaining()), quiche_send_info).intValue(); - if (written == LibQuiche.quiche_error.QUICHE_ERR_DONE) + if (written == quiche_error.QUICHE_ERR_DONE) return 0; if (written < 0L) - throw new IOException("failed to send packet; err=" + LibQuiche.quiche_error.errToString(written)); + throw new IOException("failed to send packet; err=" + quiche_error.errToString(written)); int prevPosition = buffer.position(); buffer.position(prevPosition + written); return written; @@ -535,10 +538,10 @@ public class JnaQuicheConnection extends QuicheConnection int rc = LibQuiche.INSTANCE.quiche_conn_close(quicheConn, true, new uint64_t(error), reason, new size_t(length)); if (rc == 0) return true; - if (rc == LibQuiche.quiche_error.QUICHE_ERR_DONE) + if (rc == quiche_error.QUICHE_ERR_DONE) return false; if (LOG.isDebugEnabled()) - LOG.debug("could not close connection: {}", LibQuiche.quiche_error.errToString(rc)); + LOG.debug("could not close connection: {}", quiche_error.errToString(rc)); return false; } } @@ -605,7 +608,7 @@ public class JnaQuicheConnection extends QuicheConnection if (value < 0) { if (LOG.isDebugEnabled()) - LOG.debug("could not read window capacity for stream {} err={}", streamId, LibQuiche.quiche_error.errToString(value)); + LOG.debug("could not read window capacity for stream {} err={}", streamId, quiche_error.errToString(value)); } return value; } @@ -620,9 +623,9 @@ public class JnaQuicheConnection extends QuicheConnection throw new IOException("connection was released"); int direction = writeSide ? LibQuiche.quiche_shutdown.QUICHE_SHUTDOWN_WRITE : LibQuiche.quiche_shutdown.QUICHE_SHUTDOWN_READ; int rc = LibQuiche.INSTANCE.quiche_conn_stream_shutdown(quicheConn, new uint64_t(streamId), direction, new uint64_t(error)); - if (rc == 0 || rc == LibQuiche.quiche_error.QUICHE_ERR_DONE) + if (rc == 0 || rc == quiche_error.QUICHE_ERR_DONE) return; - throw new IOException("failed to shutdown stream " + streamId + ": " + LibQuiche.quiche_error.errToString(rc)); + throw new IOException("failed to shutdown stream " + streamId + ": " + quiche_error.errToString(rc)); } } @@ -634,10 +637,10 @@ 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), buffer, new size_t(buffer.remaining()), last).intValue(); - if (written == LibQuiche.quiche_error.QUICHE_ERR_DONE) + if (written == quiche_error.QUICHE_ERR_DONE) return 0; if (written < 0L) - throw new IOException("failed to write to stream " + streamId + "; err=" + LibQuiche.quiche_error.errToString(written)); + throw new IOException("failed to write to stream " + streamId + "; err=" + quiche_error.errToString(written)); buffer.position(buffer.position() + written); return written; } @@ -652,10 +655,10 @@ public class JnaQuicheConnection extends QuicheConnection 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(); - if (read == LibQuiche.quiche_error.QUICHE_ERR_DONE) + if (read == quiche_error.QUICHE_ERR_DONE) return isStreamFinished(streamId) ? -1 : 0; if (read < 0L) - throw new IOException("failed to read from stream " + streamId + "; err=" + LibQuiche.quiche_error.errToString(read)); + throw new IOException("failed to read from stream " + streamId + "; err=" + quiche_error.errToString(read)); buffer.position(buffer.position() + read); return read; } 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 2b775f1c371..11f11ebe0de 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 @@ -61,112 +61,6 @@ public interface LibQuiche extends Library // QUIC transport API. - // The current QUIC wire version. - int QUICHE_PROTOCOL_VERSION = 0x00000001; - - // The maximum length of a connection ID. - int QUICHE_MAX_CONN_ID_LEN = 20; - - // The minimum length of Initial packets sent by a client. - int QUICHE_MIN_CLIENT_INITIAL_LEN = 1200; - - interface quiche_cc_algorithm - { - int QUICHE_CC_RENO = 0, - QUICHE_CC_CUBIC = 1; - } - - interface quiche_error - { - // There is no more work to do. - long QUICHE_ERR_DONE = -1, - - // The provided buffer is too short. - QUICHE_ERR_BUFFER_TOO_SHORT = -2, - - // The provided packet cannot be parsed because its version is unknown. - QUICHE_ERR_UNKNOWN_VERSION = -3, - - // The provided packet cannot be parsed because it contains an invalid - // frame. - QUICHE_ERR_INVALID_FRAME = -4, - - // The provided packet cannot be parsed. - QUICHE_ERR_INVALID_PACKET = -5, - - // The operation cannot be completed because the connection is in an - // invalid state. - QUICHE_ERR_INVALID_STATE = -6, - - // The operation cannot be completed because the stream is in an - // invalid state. - QUICHE_ERR_INVALID_STREAM_STATE = -7, - - // The peer's transport params cannot be parsed. - QUICHE_ERR_INVALID_TRANSPORT_PARAM = -8, - - // A cryptographic operation failed. - QUICHE_ERR_CRYPTO_FAIL = -9, - - // The TLS handshake failed. - QUICHE_ERR_TLS_FAIL = -10, - - // The peer violated the local flow control limits. - QUICHE_ERR_FLOW_CONTROL = -11, - - // The peer violated the local stream limits. - QUICHE_ERR_STREAM_LIMIT = -12, - - // The specified stream was stopped by the peer. - QUICHE_ERR_STREAM_STOPPED = -15, - - // The specified stream was reset by the peer. - QUICHE_ERR_STREAM_RESET = -16, - - // The received data exceeds the stream's final size. - QUICHE_ERR_FINAL_SIZE = -13, - - // Error in congestion control. - QUICHE_ERR_CONGESTION_CONTROL = -14; - - static String errToString(long err) - { - if (err == QUICHE_ERR_DONE) - return "QUICHE_ERR_DONE"; - if (err == QUICHE_ERR_BUFFER_TOO_SHORT) - return "QUICHE_ERR_BUFFER_TOO_SHORT"; - if (err == QUICHE_ERR_UNKNOWN_VERSION) - return "QUICHE_ERR_UNKNOWN_VERSION"; - if (err == QUICHE_ERR_INVALID_FRAME) - return "QUICHE_ERR_INVALID_FRAME"; - if (err == QUICHE_ERR_INVALID_PACKET) - return "QUICHE_ERR_INVALID_PACKET"; - if (err == QUICHE_ERR_INVALID_STATE) - return "QUICHE_ERR_INVALID_STATE"; - if (err == QUICHE_ERR_INVALID_STREAM_STATE) - return "QUICHE_ERR_INVALID_STREAM_STATE"; - if (err == QUICHE_ERR_INVALID_TRANSPORT_PARAM) - return "QUICHE_ERR_INVALID_TRANSPORT_PARAM"; - if (err == QUICHE_ERR_CRYPTO_FAIL) - return "QUICHE_ERR_CRYPTO_FAIL"; - if (err == QUICHE_ERR_TLS_FAIL) - return "QUICHE_ERR_TLS_FAIL"; - if (err == QUICHE_ERR_FLOW_CONTROL) - return "QUICHE_ERR_FLOW_CONTROL"; - if (err == QUICHE_ERR_STREAM_LIMIT) - return "QUICHE_ERR_STREAM_LIMIT"; - if (err == QUICHE_ERR_FINAL_SIZE) - return "QUICHE_ERR_FINAL_SIZE"; - if (err == QUICHE_ERR_CONGESTION_CONTROL) - return "QUICHE_ERR_CONGESTION_CONTROL"; - if (err == QUICHE_ERR_STREAM_STOPPED) - return "QUICHE_ERR_STREAM_STOPPED"; - if (err == QUICHE_ERR_STREAM_RESET) - return "QUICHE_ERR_STREAM_RESET"; - return "?? " + err; - } - } - // Returns a human readable string with the quiche version number. String quiche_version(); diff --git a/jetty-quic/quic-quiche/quic-quiche-jna/src/test/java/org/eclipse/jetty/quic/quiche/jna/LowLevelQuicheTest.java b/jetty-quic/quic-quiche/quic-quiche-jna/src/test/java/org/eclipse/jetty/quic/quiche/jna/LowLevelQuicheTest.java index 6d6a59df76a..874ff53eb42 100644 --- a/jetty-quic/quic-quiche/quic-quiche-jna/src/test/java/org/eclipse/jetty/quic/quiche/jna/LowLevelQuicheTest.java +++ b/jetty-quic/quic-quiche/quic-quiche-jna/src/test/java/org/eclipse/jetty/quic/quiche/jna/LowLevelQuicheTest.java @@ -32,6 +32,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static org.eclipse.jetty.quic.quiche.Quiche.QUICHE_MIN_CLIENT_INITIAL_LEN; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; @@ -186,7 +187,7 @@ public class LowLevelQuicheTest { JnaQuicheConnection clientQuicheConnection = entry.getKey(); JnaQuicheConnection serverQuicheConnection = entry.getValue(); - ByteBuffer buffer = ByteBuffer.allocate(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN); + ByteBuffer buffer = ByteBuffer.allocate(QUICHE_MIN_CLIENT_INITIAL_LEN); int drained = serverQuicheConnection.drainCipherBytes(buffer); assertThat(drained, is(expectedSize)); @@ -199,7 +200,7 @@ public class LowLevelQuicheTest { JnaQuicheConnection clientQuicheConnection = entry.getKey(); JnaQuicheConnection serverQuicheConnection = entry.getValue(); - ByteBuffer buffer = ByteBuffer.allocate(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN); + ByteBuffer buffer = ByteBuffer.allocate(QUICHE_MIN_CLIENT_INITIAL_LEN); int drained = clientQuicheConnection.drainCipherBytes(buffer); assertThat(drained, is(expectedSize)); @@ -210,8 +211,8 @@ public class LowLevelQuicheTest private Map.Entry connectClientToServer() throws IOException { - ByteBuffer buffer = ByteBuffer.allocate(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN); - ByteBuffer buffer2 = ByteBuffer.allocate(LibQuiche.QUICHE_MIN_CLIENT_INITIAL_LEN); + ByteBuffer buffer = ByteBuffer.allocate(QUICHE_MIN_CLIENT_INITIAL_LEN); + ByteBuffer buffer2 = ByteBuffer.allocate(QUICHE_MIN_CLIENT_INITIAL_LEN); JnaQuicheConnection clientQuicheConnection = JnaQuicheConnection.connect(clientQuicheConfig, serverSocketAddress); connectionsToDisposeOf.add(clientQuicheConnection);