mirror of
https://github.com/jetty/jetty.project.git
synced 2025-03-03 12:29:31 +00:00
#8695: fix inconsistencies between quiche's native API and its JNA/Foreign bindings
Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
parent
d6a101d463
commit
15e90acab6
@ -21,6 +21,7 @@ import java.net.SocketException;
|
|||||||
import java.net.SocketOption;
|
import java.net.SocketOption;
|
||||||
import java.net.StandardProtocolFamily;
|
import java.net.StandardProtocolFamily;
|
||||||
import java.net.StandardSocketOptions;
|
import java.net.StandardSocketOptions;
|
||||||
|
import java.nio.channels.DatagramChannel;
|
||||||
import java.nio.channels.NetworkChannel;
|
import java.nio.channels.NetworkChannel;
|
||||||
import java.nio.channels.SelectableChannel;
|
import java.nio.channels.SelectableChannel;
|
||||||
import java.nio.channels.SelectionKey;
|
import java.nio.channels.SelectionKey;
|
||||||
@ -501,6 +502,13 @@ public class ClientConnector extends ContainerLifeCycle
|
|||||||
if (sendBufferSize >= 0)
|
if (sendBufferSize >= 0)
|
||||||
setSocketOption(channel, StandardSocketOptions.SO_SNDBUF, sendBufferSize);
|
setSocketOption(channel, StandardSocketOptions.SO_SNDBUF, sendBufferSize);
|
||||||
}
|
}
|
||||||
|
if (selectable instanceof DatagramChannel)
|
||||||
|
{
|
||||||
|
// QUIC must know the local address, but it is non-null on datagram sockets only if it has been bound,
|
||||||
|
// so implicitly bind to 0.0.0.0:0 when no bind address has been set.
|
||||||
|
if (getBindAddress() == null)
|
||||||
|
setBindAddress(new InetSocketAddress("0.0.0.0", 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> void setSocketOption(NetworkChannel channel, SocketOption<T> option, T value)
|
private <T> void setSocketOption(NetworkChannel channel, SocketOption<T> option, T value)
|
||||||
|
@ -61,6 +61,43 @@
|
|||||||
<artifactId>quic-quiche-foreign-incubator</artifactId>
|
<artifactId>quic-quiche-foreign-incubator</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- Make sure to use the Foreign binding by adding and opening the jdk.incubator.foreign module. -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<argLine>
|
||||||
|
@{argLine}
|
||||||
|
${jetty.surefire.argLine}
|
||||||
|
--add-modules=jdk.incubator.foreign
|
||||||
|
--add-opens jdk.incubator.foreign/jdk.incubator.foreign=ALL-UNNAMED
|
||||||
|
--enable-native-access ALL-UNNAMED
|
||||||
|
</argLine>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<!-- Don't use the Foreign binding if the JDK version != 17. -->
|
||||||
|
<id>jdk18+</id>
|
||||||
|
<activation>
|
||||||
|
<jdk>[18,)</jdk>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<argLine>
|
||||||
|
@{argLine}
|
||||||
|
${jetty.surefire.argLine}
|
||||||
|
</argLine>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
</project>
|
</project>
|
||||||
|
@ -96,7 +96,7 @@ public class ClientQuicConnection extends QuicConnection
|
|||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("connecting to {} with protocols {}", remoteAddress, protocols);
|
LOG.debug("connecting to {} with protocols {}", remoteAddress, protocols);
|
||||||
|
|
||||||
QuicheConnection quicheConnection = QuicheConnection.connect(quicheConfig, remoteAddress);
|
QuicheConnection quicheConnection = QuicheConnection.connect(quicheConfig, getEndPoint().getLocalAddress(), remoteAddress);
|
||||||
ClientQuicSession session = new ClientQuicSession(getExecutor(), getScheduler(), getByteBufferPool(), quicheConnection, this, remoteAddress, context);
|
ClientQuicSession session = new ClientQuicSession(getExecutor(), getScheduler(), getByteBufferPool(), quicheConnection, this, remoteAddress, context);
|
||||||
pendingSessions.put(remoteAddress, session);
|
pendingSessions.put(remoteAddress, session);
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
|
@ -24,7 +24,7 @@ public interface QuicheBinding
|
|||||||
int priority();
|
int priority();
|
||||||
|
|
||||||
byte[] fromPacket(ByteBuffer packet);
|
byte[] fromPacket(ByteBuffer packet);
|
||||||
QuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress peer, int connectionIdLength) throws IOException;
|
QuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress local, InetSocketAddress peer, int connectionIdLength) throws IOException;
|
||||||
boolean negotiate(QuicheConnection.TokenMinter tokenMinter, ByteBuffer packetRead, ByteBuffer packetToSend) throws IOException;
|
boolean negotiate(QuicheConnection.TokenMinter tokenMinter, ByteBuffer packetRead, ByteBuffer packetToSend) throws IOException;
|
||||||
QuicheConnection tryAccept(QuicheConfig quicheConfig, QuicheConnection.TokenValidator tokenValidator, ByteBuffer packetRead, SocketAddress peer) throws IOException;
|
QuicheConnection tryAccept(QuicheConfig quicheConfig, QuicheConnection.TokenValidator tokenValidator, ByteBuffer packetRead, SocketAddress local, SocketAddress peer) throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -49,14 +49,14 @@ public abstract class QuicheConnection
|
|||||||
LOG.debug("using quiche binding implementation: {}", QUICHE_BINDING.getClass().getName());
|
LOG.debug("using quiche binding implementation: {}", QUICHE_BINDING.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static QuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress peer) throws IOException
|
public static QuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress local, InetSocketAddress peer) throws IOException
|
||||||
{
|
{
|
||||||
return connect(quicheConfig, peer, Quiche.QUICHE_MAX_CONN_ID_LEN);
|
return connect(quicheConfig, local, peer, Quiche.QUICHE_MAX_CONN_ID_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static QuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress peer, int connectionIdLength) throws IOException
|
public static QuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress local, InetSocketAddress peer, int connectionIdLength) throws IOException
|
||||||
{
|
{
|
||||||
return QUICHE_BINDING.connect(quicheConfig, peer, connectionIdLength);
|
return QUICHE_BINDING.connect(quicheConfig, local, peer, connectionIdLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,9 +73,9 @@ public abstract class QuicheConnection
|
|||||||
* Fully consumes the {@code packetRead} buffer if the connection was accepted.
|
* Fully consumes the {@code packetRead} buffer if the connection was accepted.
|
||||||
* @return an established connection if accept succeeded, null if accept failed and negotiation should be tried.
|
* @return an established connection if accept succeeded, null if accept failed and negotiation should be tried.
|
||||||
*/
|
*/
|
||||||
public static QuicheConnection tryAccept(QuicheConfig quicheConfig, TokenValidator tokenValidator, ByteBuffer packetRead, SocketAddress peer) throws IOException
|
public static QuicheConnection tryAccept(QuicheConfig quicheConfig, TokenValidator tokenValidator, ByteBuffer packetRead, SocketAddress local, SocketAddress peer) throws IOException
|
||||||
{
|
{
|
||||||
return QUICHE_BINDING.tryAccept(quicheConfig, tokenValidator, packetRead, peer);
|
return QUICHE_BINDING.tryAccept(quicheConfig, tokenValidator, packetRead, local, peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final List<Long> readableStreamIds()
|
public final List<Long> readableStreamIds()
|
||||||
|
@ -57,9 +57,9 @@ public class ForeignIncubatorQuicheBinding implements QuicheBinding
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress peer, int connectionIdLength) throws IOException
|
public QuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress local, InetSocketAddress peer, int connectionIdLength) throws IOException
|
||||||
{
|
{
|
||||||
return ForeignIncubatorQuicheConnection.connect(quicheConfig, peer, connectionIdLength);
|
return ForeignIncubatorQuicheConnection.connect(quicheConfig, local, peer, connectionIdLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -69,9 +69,9 @@ public class ForeignIncubatorQuicheBinding implements QuicheBinding
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QuicheConnection tryAccept(QuicheConfig quicheConfig, QuicheConnection.TokenValidator tokenValidator, ByteBuffer packetRead, SocketAddress peer) throws IOException
|
public QuicheConnection tryAccept(QuicheConfig quicheConfig, QuicheConnection.TokenValidator tokenValidator, ByteBuffer packetRead, SocketAddress local, SocketAddress peer) throws IOException
|
||||||
{
|
{
|
||||||
return ForeignIncubatorQuicheConnection.tryAccept(quicheConfig, tokenValidator, packetRead, peer);
|
return ForeignIncubatorQuicheConnection.tryAccept(quicheConfig, tokenValidator, packetRead, local, peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -746,8 +746,8 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection
|
|||||||
{
|
{
|
||||||
if (quicheConn == null)
|
if (quicheConn == null)
|
||||||
throw new IllegalStateException("connection was released");
|
throw new IllegalStateException("connection was released");
|
||||||
quiche_h.quiche_conn_path_stats(quicheConn, pathStats.address());
|
quiche_h.quiche_conn_path_stats(quicheConn, 0L, pathStats.address());
|
||||||
return quiche_path_stats.get_cwnd(stats);
|
return quiche_path_stats.get_cwnd(pathStats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -760,11 +760,11 @@ public class quiche_h
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int quiche_conn_path_stats(MemoryAddress conn, MemoryAddress stats)
|
public static int quiche_conn_path_stats(MemoryAddress conn, long idx, MemoryAddress stats)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return (int)quiche_conn_path_stats$MH.invokeExact(conn, stats);
|
return (int)quiche_conn_path_stats$MH.invokeExact(conn, idx, stats);
|
||||||
}
|
}
|
||||||
catch (Throwable ex)
|
catch (Throwable ex)
|
||||||
{
|
{
|
||||||
|
@ -57,9 +57,9 @@ public class JnaQuicheBinding implements QuicheBinding
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress peer, int connectionIdLength) throws IOException
|
public QuicheConnection connect(QuicheConfig quicheConfig, InetSocketAddress local, InetSocketAddress peer, int connectionIdLength) throws IOException
|
||||||
{
|
{
|
||||||
return JnaQuicheConnection.connect(quicheConfig, peer, connectionIdLength);
|
return JnaQuicheConnection.connect(quicheConfig, local, peer, connectionIdLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -69,9 +69,9 @@ public class JnaQuicheBinding implements QuicheBinding
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QuicheConnection tryAccept(QuicheConfig quicheConfig, QuicheConnection.TokenValidator tokenValidator, ByteBuffer packetRead, SocketAddress peer) throws IOException
|
public QuicheConnection tryAccept(QuicheConfig quicheConfig, QuicheConnection.TokenValidator tokenValidator, ByteBuffer packetRead, SocketAddress local, SocketAddress peer) throws IOException
|
||||||
{
|
{
|
||||||
return JnaQuicheConnection.tryAccept(quicheConfig, tokenValidator, packetRead, peer);
|
return JnaQuicheConnection.tryAccept(quicheConfig, tokenValidator, packetRead, local, peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -231,54 +231,54 @@ public interface LibQuiche extends Library
|
|||||||
class quiche_path_stats extends Structure
|
class quiche_path_stats extends Structure
|
||||||
{
|
{
|
||||||
// The local address used by this path.
|
// The local address used by this path.
|
||||||
sockaddr_storage local_addr;
|
public sockaddr_storage local_addr;
|
||||||
size_t local_addr_len;
|
public size_t local_addr_len;
|
||||||
|
|
||||||
// The peer address seen by this path.
|
// The peer address seen by this path.
|
||||||
sockaddr_storage peer_addr;
|
public sockaddr_storage peer_addr;
|
||||||
size_t peer_addr_len;
|
public size_t peer_addr_len;
|
||||||
|
|
||||||
// The validation state of the path.
|
// The validation state of the path.
|
||||||
ssize_t validation_state;
|
public ssize_t validation_state;
|
||||||
|
|
||||||
// Whether this path is active.
|
// Whether this path is active.
|
||||||
boolean active;
|
public boolean active;
|
||||||
|
|
||||||
// The number of QUIC packets received on this path.
|
// The number of QUIC packets received on this path.
|
||||||
size_t recv;
|
public size_t recv;
|
||||||
|
|
||||||
// The number of QUIC packets sent on this path.
|
// The number of QUIC packets sent on this path.
|
||||||
size_t sent;
|
public size_t sent;
|
||||||
|
|
||||||
// The number of QUIC packets that were lost on this path.
|
// The number of QUIC packets that were lost on this path.
|
||||||
size_t lost;
|
public size_t lost;
|
||||||
|
|
||||||
// The number of sent QUIC packets with retransmitted data on this path.
|
// The number of sent QUIC packets with retransmitted data on this path.
|
||||||
size_t retrans;
|
public size_t retrans;
|
||||||
|
|
||||||
// The estimated round-trip time of the path (in nanoseconds).
|
// The estimated round-trip time of the path (in nanoseconds).
|
||||||
uint64_t rtt;
|
public uint64_t rtt;
|
||||||
|
|
||||||
// The size of the path's congestion window in bytes.
|
// The size of the path's congestion window in bytes.
|
||||||
size_t cwnd;
|
public size_t cwnd;
|
||||||
|
|
||||||
// The number of sent bytes on this path.
|
// The number of sent bytes on this path.
|
||||||
uint64_t sent_bytes;
|
public uint64_t sent_bytes;
|
||||||
|
|
||||||
// The number of received bytes on this path.
|
// The number of received bytes on this path.
|
||||||
uint64_t recv_bytes;
|
public uint64_t recv_bytes;
|
||||||
|
|
||||||
// The number of bytes lost on this path.
|
// The number of bytes lost on this path.
|
||||||
uint64_t lost_bytes;
|
public uint64_t lost_bytes;
|
||||||
|
|
||||||
// The number of stream bytes retransmitted on this path.
|
// The number of stream bytes retransmitted on this path.
|
||||||
uint64_t stream_retrans_bytes;
|
public uint64_t stream_retrans_bytes;
|
||||||
|
|
||||||
// The current PMTU for the path.
|
// The current PMTU for the path.
|
||||||
size_t pmtu;
|
public size_t pmtu;
|
||||||
|
|
||||||
// The most recent data delivery rate estimate in bytes/s.
|
// The most recent data delivery rate estimate in bytes/s.
|
||||||
uint64_t delivery_rate;
|
public uint64_t delivery_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LoggingCallback extends Callback
|
interface LoggingCallback extends Callback
|
||||||
|
@ -62,7 +62,7 @@ public class ServerQuicConnection extends QuicConnection
|
|||||||
{
|
{
|
||||||
ByteBufferPool byteBufferPool = getByteBufferPool();
|
ByteBufferPool byteBufferPool = getByteBufferPool();
|
||||||
// TODO make the token validator configurable
|
// TODO make the token validator configurable
|
||||||
QuicheConnection quicheConnection = QuicheConnection.tryAccept(connector.newQuicheConfig(), new SimpleTokenValidator((InetSocketAddress)remoteAddress), cipherBuffer, remoteAddress);
|
QuicheConnection quicheConnection = QuicheConnection.tryAccept(connector.newQuicheConfig(), new SimpleTokenValidator((InetSocketAddress)remoteAddress), cipherBuffer, getEndPoint().getLocalAddress(), remoteAddress);
|
||||||
if (quicheConnection == null)
|
if (quicheConnection == null)
|
||||||
{
|
{
|
||||||
ByteBuffer negotiationBuffer = byteBufferPool.acquire(getOutputBufferSize(), true);
|
ByteBuffer negotiationBuffer = byteBufferPool.acquire(getOutputBufferSize(), true);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user