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.StandardProtocolFamily;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.NetworkChannel;
|
||||
import java.nio.channels.SelectableChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
@ -501,6 +502,13 @@ public class ClientConnector extends ContainerLifeCycle
|
||||
if (sendBufferSize >= 0)
|
||||
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)
|
||||
|
@ -61,6 +61,43 @@
|
||||
<artifactId>quic-quiche-foreign-incubator</artifactId>
|
||||
</dependency>
|
||||
</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>
|
||||
</profiles>
|
||||
</project>
|
||||
|
@ -96,7 +96,7 @@ public class ClientQuicConnection extends QuicConnection
|
||||
if (LOG.isDebugEnabled())
|
||||
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);
|
||||
pendingSessions.put(remoteAddress, session);
|
||||
if (LOG.isDebugEnabled())
|
||||
|
@ -24,7 +24,7 @@ public interface QuicheBinding
|
||||
int priority();
|
||||
|
||||
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;
|
||||
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());
|
||||
}
|
||||
|
||||
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.
|
||||
* @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()
|
||||
|
@ -57,9 +57,9 @@ public class ForeignIncubatorQuicheBinding implements QuicheBinding
|
||||
}
|
||||
|
||||
@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
|
||||
@ -69,9 +69,9 @@ public class ForeignIncubatorQuicheBinding implements QuicheBinding
|
||||
}
|
||||
|
||||
@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
|
||||
|
@ -746,8 +746,8 @@ public class ForeignIncubatorQuicheConnection extends QuicheConnection
|
||||
{
|
||||
if (quicheConn == null)
|
||||
throw new IllegalStateException("connection was released");
|
||||
quiche_h.quiche_conn_path_stats(quicheConn, pathStats.address());
|
||||
return quiche_path_stats.get_cwnd(stats);
|
||||
quiche_h.quiche_conn_path_stats(quicheConn, 0L, pathStats.address());
|
||||
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
|
||||
{
|
||||
return (int)quiche_conn_path_stats$MH.invokeExact(conn, stats);
|
||||
return (int)quiche_conn_path_stats$MH.invokeExact(conn, idx, stats);
|
||||
}
|
||||
catch (Throwable ex)
|
||||
{
|
||||
|
@ -57,9 +57,9 @@ public class JnaQuicheBinding implements QuicheBinding
|
||||
}
|
||||
|
||||
@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
|
||||
@ -69,9 +69,9 @@ public class JnaQuicheBinding implements QuicheBinding
|
||||
}
|
||||
|
||||
@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
|
||||
|
@ -231,54 +231,54 @@ public interface LibQuiche extends Library
|
||||
class quiche_path_stats extends Structure
|
||||
{
|
||||
// The local address used by this path.
|
||||
sockaddr_storage local_addr;
|
||||
size_t local_addr_len;
|
||||
public sockaddr_storage local_addr;
|
||||
public size_t local_addr_len;
|
||||
|
||||
// The peer address seen by this path.
|
||||
sockaddr_storage peer_addr;
|
||||
size_t peer_addr_len;
|
||||
public sockaddr_storage peer_addr;
|
||||
public size_t peer_addr_len;
|
||||
|
||||
// The validation state of the path.
|
||||
ssize_t validation_state;
|
||||
public ssize_t validation_state;
|
||||
|
||||
// Whether this path is active.
|
||||
boolean active;
|
||||
public boolean active;
|
||||
|
||||
// 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.
|
||||
size_t sent;
|
||||
public size_t sent;
|
||||
|
||||
// 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.
|
||||
size_t retrans;
|
||||
public size_t retrans;
|
||||
|
||||
// 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.
|
||||
size_t cwnd;
|
||||
public size_t cwnd;
|
||||
|
||||
// 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.
|
||||
uint64_t recv_bytes;
|
||||
public uint64_t recv_bytes;
|
||||
|
||||
// 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.
|
||||
uint64_t stream_retrans_bytes;
|
||||
public uint64_t stream_retrans_bytes;
|
||||
|
||||
// The current PMTU for the path.
|
||||
size_t pmtu;
|
||||
public size_t pmtu;
|
||||
|
||||
// The most recent data delivery rate estimate in bytes/s.
|
||||
uint64_t delivery_rate;
|
||||
public uint64_t delivery_rate;
|
||||
}
|
||||
|
||||
interface LoggingCallback extends Callback
|
||||
|
@ -62,7 +62,7 @@ public class ServerQuicConnection extends QuicConnection
|
||||
{
|
||||
ByteBufferPool byteBufferPool = getByteBufferPool();
|
||||
// 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)
|
||||
{
|
||||
ByteBuffer negotiationBuffer = byteBufferPool.acquire(getOutputBufferSize(), true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user