Skip to content

Commit

Permalink
#8695: fix inconsistencies between quiche's native API and its JNA/F…
Browse files Browse the repository at this point in the history
…oreign bindings

Signed-off-by: Ludovic Orban <[email protected]>
  • Loading branch information
lorban committed Oct 18, 2022
1 parent d6a101d commit 15e90ac
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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;
Expand Down Expand Up @@ -501,6 +502,13 @@ protected void configure(SelectableChannel selectable) throws IOException
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)
Expand Down
37 changes: 37 additions & 0 deletions jetty-quic/quic-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public void onOpen()
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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand All @@ -73,9 +73,9 @@ public static boolean negotiate(TokenMinter tokenMinter, ByteBuffer packetRead,
* 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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ public byte[] fromPacket(ByteBuffer packet)
}

@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
Expand All @@ -69,9 +69,9 @@ public boolean negotiate(QuicheConnection.TokenMinter tokenMinter, ByteBuffer pa
}

@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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -746,8 +746,8 @@ public long windowCapacity()
{
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);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -760,11 +760,11 @@ public static void quiche_conn_stats(MemoryAddress conn, MemoryAddress stats)
}
}

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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ public byte[] fromPacket(ByteBuffer packet)
}

@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
Expand All @@ -69,9 +69,9 @@ public boolean negotiate(QuicheConnection.TokenMinter tokenMinter, ByteBuffer pa
}

@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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,54 +231,54 @@ class quiche_stats extends Structure
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ protected QuicSession createSession(SocketAddress remoteAddress, ByteBuffer ciph
{
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);
Expand Down

0 comments on commit 15e90ac

Please sign in to comment.