Skip to content

Commit cb07fb5

Browse files
committed
Quic API and implementation - this is a work in progress.
1 parent bf723e8 commit cb07fb5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3518
-119
lines changed

vertx-core/pom.xml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,16 @@
7070
<groupId>io.netty</groupId>
7171
<artifactId>netty-codec-http2</artifactId>
7272
</dependency>
73+
<dependency>
74+
<groupId>io.netty</groupId>
75+
<artifactId>netty-codec-http3</artifactId>
76+
<exclusions>
77+
<exclusion>
78+
<groupId>org.bouncycastle</groupId>
79+
<artifactId>*</artifactId>
80+
</exclusion>
81+
</exclusions>
82+
</dependency>
7383
<dependency>
7484
<groupId>io.netty</groupId>
7585
<artifactId>netty-resolver</artifactId>
@@ -98,6 +108,16 @@
98108
<artifactId>netty-transport-classes-kqueue</artifactId>
99109
<optional>true</optional>
100110
</dependency>
111+
<dependency>
112+
<groupId>io.netty</groupId>
113+
<artifactId>netty-codec-classes-quic</artifactId>
114+
<optional>true</optional>
115+
</dependency>
116+
<dependency>
117+
<groupId>io.netty</groupId>
118+
<artifactId>netty-codec-native-quic</artifactId>
119+
<optional>true</optional>
120+
</dependency>
101121

102122
<!-- Jackson -->
103123
<dependency>
@@ -880,6 +900,12 @@
880900
<classifier>linux-x86_64</classifier>
881901
<scope>test</scope>
882902
</dependency>
903+
<dependency>
904+
<groupId>io.netty</groupId>
905+
<artifactId>netty-codec-native-quic</artifactId>
906+
<classifier>linux-x86_64</classifier>
907+
<scope>test</scope>
908+
</dependency>
883909
</dependencies>
884910
</profile>
885911

@@ -904,6 +930,12 @@
904930
<classifier>linux-x86_64</classifier>
905931
<scope>test</scope>
906932
</dependency>
933+
<dependency>
934+
<groupId>io.netty</groupId>
935+
<artifactId>netty-codec-native-quic</artifactId>
936+
<classifier>linux-x86_64</classifier>
937+
<scope>test</scope>
938+
</dependency>
907939
</dependencies>
908940
</profile>
909941

@@ -928,6 +960,12 @@
928960
<classifier>linux-aarch_64</classifier>
929961
<scope>test</scope>
930962
</dependency>
963+
<dependency>
964+
<groupId>io.netty</groupId>
965+
<artifactId>netty-codec-native-quic</artifactId>
966+
<classifier>linux-aarch_64</classifier>
967+
<scope>test</scope>
968+
</dependency>
931969
</dependencies>
932970
</profile>
933971

@@ -952,6 +990,12 @@
952990
<classifier>osx-x86_64</classifier>
953991
<scope>test</scope>
954992
</dependency>
993+
<dependency>
994+
<groupId>io.netty</groupId>
995+
<artifactId>netty-codec-native-quic</artifactId>
996+
<classifier>osx-x86_64</classifier>
997+
<scope>test</scope>
998+
</dependency>
955999
</dependencies>
9561000
</profile>
9571001

@@ -976,6 +1020,12 @@
9761020
<classifier>osx-aarch_64</classifier>
9771021
<scope>test</scope>
9781022
</dependency>
1023+
<dependency>
1024+
<groupId>io.netty</groupId>
1025+
<artifactId>netty-codec-native-quic</artifactId>
1026+
<classifier>osx-aarch_64</classifier>
1027+
<scope>test</scope>
1028+
</dependency>
9791029
</dependencies>
9801030
</profile>
9811031

vertx-core/src/main/java/io/vertx/core/internal/net/SslChannelProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ private SslHandler createServerSslHandler(boolean useAlpn, long sslHandshakeTime
8383

8484
private SniHandler createSniHandler(boolean useAlpn, long sslHandshakeTimeout, TimeUnit sslHandshakeTimeoutUnit, HostAndPort remoteAddress) {
8585
Executor delegatedTaskExec = sslContextProvider.useWorkerPool() ? workerPool : ImmediateExecutor.INSTANCE;
86-
return new VertxSniHandler(sslContextProvider.serverNameMapping(delegatedTaskExec, useAlpn), sslHandshakeTimeoutUnit.toMillis(sslHandshakeTimeout), delegatedTaskExec, remoteAddress);
86+
return new VertxSniHandler(sslContextProvider.serverNameAsyncMapping(delegatedTaskExec, useAlpn), sslHandshakeTimeoutUnit.toMillis(sslHandshakeTimeout), delegatedTaskExec, remoteAddress);
8787
}
8888

8989
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.vertx.core.internal.quic;
2+
3+
import io.netty.channel.ChannelHandlerContext;
4+
import io.vertx.core.quic.QuicConnection;
5+
6+
public interface QuicConnectionInternal extends QuicConnection {
7+
8+
ChannelHandlerContext channelHandlerContext();
9+
10+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package io.vertx.core.internal.quic;
2+
3+
import io.vertx.codegen.annotations.Nullable;
4+
import io.vertx.core.Handler;
5+
import io.vertx.core.buffer.Buffer;
6+
import io.vertx.core.internal.net.SocketInternal;
7+
import io.vertx.core.quic.QuicStream;
8+
9+
public interface QuicStreamInternal extends QuicStream, SocketInternal {
10+
11+
@Override
12+
QuicStreamInternal messageHandler(Handler<Object> handler);
13+
14+
@Override
15+
QuicStreamInternal readCompletionHandler(Handler<Void> handler);
16+
17+
@Override
18+
QuicStreamInternal eventHandler(Handler<Object> handler);
19+
20+
@Override
21+
QuicStreamInternal exceptionHandler(@Nullable Handler<Throwable> handler);
22+
23+
@Override
24+
QuicStreamInternal handler(@Nullable Handler<Buffer> handler);
25+
26+
@Override
27+
QuicStreamInternal pause();
28+
29+
@Override
30+
QuicStreamInternal resume();
31+
32+
@Override
33+
QuicStreamInternal fetch(long amount);
34+
35+
@Override
36+
QuicStreamInternal endHandler(@Nullable Handler<Void> endHandler);
37+
38+
@Override
39+
QuicStreamInternal setWriteQueueMaxSize(int maxSize);
40+
41+
@Override
42+
QuicStreamInternal drainHandler(@Nullable Handler<Void> handler);
43+
44+
@Override
45+
QuicStreamInternal closeHandler(@Nullable Handler<Void> handler);
46+
47+
}

vertx-core/src/main/java/io/vertx/core/internal/tls/SslContextProvider.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import io.netty.handler.ssl.SniHandler;
1414
import io.netty.handler.ssl.SslContext;
1515
import io.netty.util.AsyncMapping;
16+
import io.netty.util.Mapping;
1617
import io.vertx.core.VertxException;
1718
import io.vertx.core.http.ClientAuth;
1819
import io.vertx.core.spi.tls.SslContextFactory;
@@ -147,12 +148,28 @@ public SslContext sslServerContext(boolean useAlpn) {
147148
}
148149
}
149150

151+
/**
152+
*
153+
* @param useAlpn
154+
* @return
155+
*/
156+
public Mapping<? super String, ? extends SslContext> serverNameMapping(boolean useAlpn) {
157+
return (Mapping<String, SslContext>) serverName -> {
158+
try {
159+
return sslContext(serverName, useAlpn, true);
160+
} catch (Exception e) {
161+
// Log this
162+
return null;
163+
}
164+
};
165+
}
166+
150167
/**
151168
* Server name {@link AsyncMapping} for {@link SniHandler}, mapping happens on a Vert.x worker thread.
152169
*
153170
* @return the {@link AsyncMapping}
154171
*/
155-
public AsyncMapping<? super String, ? extends SslContext> serverNameMapping(Executor workerPool, boolean useAlpn) {
172+
public AsyncMapping<? super String, ? extends SslContext> serverNameAsyncMapping(Executor workerPool, boolean useAlpn) {
156173
return (AsyncMapping<String, SslContext>) (serverName, promise) -> {
157174
workerPool.execute(() -> {
158175
SslContext sslContext;

vertx-core/src/main/java/io/vertx/core/net/TcpOptions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ void init() {
5454
}
5555

5656
@Override
57-
TcpOptions copy() {
57+
protected TcpOptions copy() {
5858
return new TcpOptions(this);
5959
}
6060

vertx-core/src/main/java/io/vertx/core/net/TransportOptions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
*/
1616
public abstract class TransportOptions {
1717

18-
abstract TransportOptions copy();
18+
protected abstract TransportOptions copy();
1919

2020
}

vertx-core/src/main/java/io/vertx/core/net/impl/ConnectionBase.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313

1414
import io.netty.buffer.ByteBuf;
1515
import io.netty.channel.*;
16+
import io.netty.handler.codec.quic.QuicChannel;
1617
import io.netty.handler.ssl.SslHandler;
1718
import io.netty.handler.traffic.AbstractTrafficShapingHandler;
1819
import io.netty.util.AttributeKey;
19-
import io.netty.util.concurrent.EventExecutor;
2020
import io.netty.util.concurrent.FutureListener;
2121
import io.vertx.core.*;
2222
import io.vertx.core.internal.ContextInternal;
@@ -29,14 +29,14 @@
2929
import io.vertx.core.net.SocketAddress;
3030
import io.vertx.core.spi.metrics.NetworkMetrics;
3131
import io.vertx.core.spi.metrics.TCPMetrics;
32+
import io.vertx.core.spi.metrics.TransportMetrics;
3233

3334
import javax.net.ssl.SSLPeerUnverifiedException;
3435
import javax.net.ssl.SSLSession;
3536
import java.net.InetSocketAddress;
3637
import java.security.cert.Certificate;
3738
import java.util.Arrays;
3839
import java.util.List;
39-
import java.util.concurrent.TimeUnit;
4040

4141
/**
4242
* Abstract base class for connections managed by a vertx instance. This base implementation does not handle
@@ -187,8 +187,8 @@ protected void handleClosed() {
187187
if (metrics != null) {
188188
flushBytesRead();
189189
flushBytesWritten();
190-
if (metrics instanceof TCPMetrics) {
191-
((TCPMetrics) metrics).disconnected(metric(), remoteAddress());
190+
if (metrics instanceof TransportMetrics<?>) {
191+
((TransportMetrics<Object>) metrics).disconnected(metric(), remoteAddress());
192192
}
193193
}
194194
context.execute(() -> {
@@ -352,7 +352,12 @@ public String remoteName() {
352352
}
353353

354354
private SocketAddress channelRemoteAddress() {
355-
java.net.SocketAddress addr = channel.remoteAddress();
355+
java.net.SocketAddress addr;
356+
if (channel instanceof QuicChannel) {
357+
addr = ((QuicChannel)channel).remoteSocketAddress();
358+
} else {
359+
addr = channel.remoteAddress();
360+
}
356361
return addr != null ? vertx.transport().convert(addr) : null;
357362
}
358363

@@ -393,7 +398,12 @@ public SocketAddress remoteAddress(boolean real) {
393398
}
394399

395400
private SocketAddress channelLocalAddress() {
396-
java.net.SocketAddress addr = channel.localAddress();
401+
java.net.SocketAddress addr;
402+
if (channel instanceof QuicChannel) {
403+
addr = ((QuicChannel)channel).localSocketAddress();
404+
} else {
405+
addr = channel.localAddress();
406+
}
397407
return addr != null ? vertx.transport().convert(addr) : null;
398408
}
399409

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) 2011-2025 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
8+
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10+
*/
11+
package io.vertx.core.quic;
12+
13+
import io.vertx.core.buffer.Buffer;
14+
15+
/**
16+
* Details of a Quic connection close.
17+
*
18+
* @author <a href="mailto:[email protected]">Julien Viet</a>
19+
*/
20+
public class ConnectionClose {
21+
22+
private int error;
23+
private Buffer reason;
24+
25+
/**
26+
* @return the close error code
27+
*/
28+
public int getError() {
29+
return error;
30+
}
31+
32+
/**
33+
* Set the close error code.
34+
*
35+
* @param error the error code
36+
* @return this instance
37+
*/
38+
public ConnectionClose setError(int error) {
39+
this.error = error;
40+
return this;
41+
}
42+
43+
/**
44+
* @return the close reason
45+
*/
46+
public Buffer getReason() {
47+
return reason;
48+
}
49+
50+
/**
51+
* Set the close reason
52+
*
53+
* @param reason the close reason
54+
* @return this instance
55+
*/
56+
public ConnectionClose setReason(Buffer reason) {
57+
this.reason = reason;
58+
return this;
59+
}
60+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2011-2025 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
8+
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10+
*/
11+
package io.vertx.core.quic;
12+
13+
import io.vertx.core.Future;
14+
import io.vertx.core.Handler;
15+
import io.vertx.core.Vertx;
16+
import io.vertx.core.internal.VertxInternal;
17+
import io.vertx.core.net.SocketAddress;
18+
import io.vertx.core.quic.impl.QuicClientImpl;
19+
import io.vertx.core.quic.impl.QuicServerImpl;
20+
21+
/**
22+
* A Quic client.
23+
*
24+
* @author <a href="mailto:[email protected]">Julien Viet</a>
25+
*/
26+
public interface QuicClient extends QuicEndpoint {
27+
28+
/**
29+
* <p>Create a configured Quic client.</p>
30+
*
31+
* <p>The returned client must be bound, prior {@link #connect(SocketAddress) connecting} to a server.</p>
32+
*
33+
* @param vertx the vertx instance
34+
* @param options the client configuration options
35+
* @return the client
36+
*/
37+
static QuicClient create(Vertx vertx, QuicClientOptions options) {
38+
return QuicClientImpl.create((VertxInternal) vertx, options);
39+
}
40+
41+
/**
42+
* Connect to a Quic server.
43+
*
44+
* @param address the server address
45+
* @return a Quic connection as a future
46+
*/
47+
Future<QuicConnection> connect(SocketAddress address);
48+
49+
}

0 commit comments

Comments
 (0)