Skip to content

Commit 6eaadc8

Browse files
committed
Basic HTTP/3 server.
1 parent 1dcc793 commit 6eaadc8

File tree

14 files changed

+1063
-75
lines changed

14 files changed

+1063
-75
lines changed

vertx-core/src/main/java/io/vertx/core/Vertx.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,14 @@ default NetClient createNetClient() {
229229
*/
230230
HttpServer createHttpServer(HttpServerOptions options);
231231

232+
/**
233+
* Create an HTTP3 server using the specified options
234+
*
235+
* @param options the options to use
236+
* @return the server
237+
*/
238+
HttpServer createHttpServer(Http3ServerOptions options);
239+
232240
/**
233241
* Create an HTTP/HTTPS server using default options
234242
*
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package io.vertx.core.http;
2+
3+
import io.vertx.codegen.annotations.DataObject;
4+
import io.vertx.core.net.KeyCertOptions;
5+
import io.vertx.core.net.QLogConfig;
6+
import io.vertx.core.net.QuicServerOptions;
7+
8+
import java.time.Duration;
9+
10+
@DataObject
11+
public class Http3ServerOptions extends QuicServerOptions {
12+
13+
public Http3ServerOptions() {
14+
}
15+
16+
public Http3ServerOptions(Http3ServerOptions other) {
17+
super(other);
18+
}
19+
20+
@Override
21+
public Http3ServerOptions setQLogConfig(QLogConfig qLogConfig) {
22+
return (Http3ServerOptions)super.setQLogConfig(qLogConfig);
23+
}
24+
25+
@Override
26+
public Http3ServerOptions setLoadBalanced(boolean loadBalanced) {
27+
return (Http3ServerOptions)super.setLoadBalanced(loadBalanced);
28+
}
29+
30+
@Override
31+
public Http3ServerOptions setValidateClientAddress(boolean validateClientAddress) {
32+
return (Http3ServerOptions)super.setValidateClientAddress(validateClientAddress);
33+
}
34+
35+
@Override
36+
public Http3ServerOptions setClientAddressValidationTimeWindow(Duration clientAddressValidationTimeWindow) {
37+
return (Http3ServerOptions)super.setClientAddressValidationTimeWindow(clientAddressValidationTimeWindow);
38+
}
39+
40+
@Override
41+
public Http3ServerOptions setClientAddressValidationKey(KeyCertOptions validationKey) {
42+
return (Http3ServerOptions)super.setClientAddressValidationKey(validationKey);
43+
}
44+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package io.vertx.core.http.impl;
2+
3+
import io.netty.handler.codec.http3.*;
4+
import io.vertx.core.Future;
5+
import io.vertx.core.Handler;
6+
import io.vertx.core.http.*;
7+
import io.vertx.core.http.impl.http3.Http3ServerConnection;
8+
import io.vertx.core.internal.ContextInternal;
9+
import io.vertx.core.internal.VertxInternal;
10+
import io.vertx.core.internal.quic.QuicConnectionInternal;
11+
import io.vertx.core.net.*;
12+
13+
import java.time.Duration;
14+
import java.util.Arrays;
15+
import java.util.concurrent.TimeUnit;
16+
17+
public class Http3Server implements HttpServer {
18+
19+
private final VertxInternal vertx;
20+
private final Http3ServerOptions options;
21+
private volatile Handler<HttpServerRequest> requestHandler;
22+
private QuicServer quicServer;
23+
24+
public Http3Server(VertxInternal vertx, Http3ServerOptions options) {
25+
26+
options = new Http3ServerOptions(options);
27+
options.getSslOptions().setApplicationLayerProtocols(Arrays.asList(Http3.supportedApplicationProtocols()));
28+
options.getTransportOptions().setInitialMaxData(10000000L);
29+
options.getTransportOptions().setInitialMaxStreamDataBidirectionalLocal(1000000L);
30+
options.getTransportOptions().setInitialMaxStreamDataBidirectionalRemote(1000000L);
31+
options.getTransportOptions().setInitialMaxStreamDataUnidirectional(1000000L);
32+
options.getTransportOptions().setInitialMaxStreamsBidirectional(100L);
33+
options.getTransportOptions().setInitialMaxStreamsUnidirectional(100L);
34+
35+
this.vertx = vertx;
36+
this.options = options;
37+
}
38+
39+
@Override
40+
public HttpServer requestHandler(Handler<HttpServerRequest> handler) {
41+
this.requestHandler = handler;
42+
return this;
43+
}
44+
45+
@Override
46+
public Handler<HttpServerRequest> requestHandler() {
47+
return requestHandler;
48+
}
49+
50+
@Override
51+
public HttpServer invalidRequestHandler(Handler<HttpServerRequest> handler) {
52+
throw new UnsupportedOperationException();
53+
}
54+
55+
@Override
56+
public HttpServer connectionHandler(Handler<HttpConnection> handler) {
57+
throw new UnsupportedOperationException();
58+
}
59+
60+
@Override
61+
public HttpServer webSocketHandshakeHandler(Handler<ServerWebSocketHandshake> handler) {
62+
throw new UnsupportedOperationException();
63+
}
64+
65+
@Override
66+
public HttpServer exceptionHandler(Handler<Throwable> handler) {
67+
throw new UnsupportedOperationException();
68+
}
69+
70+
@Override
71+
public HttpServer webSocketHandler(Handler<ServerWebSocket> handler) {
72+
throw new UnsupportedOperationException();
73+
}
74+
75+
@Override
76+
public Handler<ServerWebSocket> webSocketHandler() {
77+
throw new UnsupportedOperationException();
78+
}
79+
80+
@Override
81+
public Future<Boolean> updateSSLOptions(ServerSSLOptions options, boolean force) {
82+
throw new UnsupportedOperationException();
83+
}
84+
85+
@Override
86+
public Future<Boolean> updateTrafficShapingOptions(TrafficShapingOptions options) {
87+
throw new UnsupportedOperationException();
88+
}
89+
90+
@Override
91+
public Future<HttpServer> listen() {
92+
return listen(SocketAddress.inetSocketAddress(443, "0.0.0.0"));
93+
}
94+
95+
private void handleConnection(QuicConnection connection) {
96+
String host = connection.localAddress().host();
97+
int port = connection.localAddress().port();
98+
String serverOrigin = "https://" + host + ":" + port;
99+
ContextInternal context = vertx.getOrCreateContext();
100+
101+
QuicConnectionInternal connectionInternal = (QuicConnectionInternal) connection;
102+
103+
Http3ServerConnection http3Connection = new Http3ServerConnection(context, connectionInternal);
104+
105+
http3Connection.init();
106+
107+
http3Connection.streamHandler(stream -> {
108+
HttpServerRequestImpl request = new HttpServerRequestImpl(requestHandler, stream, stream.context(),
109+
false, HttpServerOptions.DEFAULT_MAX_FORM_ATTRIBUTE_SIZE,
110+
HttpServerOptions.DEFAULT_MAX_FORM_FIELDS, HttpServerOptions.DEFAULT_MAX_FORM_BUFFERED_SIZE, serverOrigin);
111+
request.init();
112+
});
113+
}
114+
115+
@Override
116+
public Future<HttpServer> listen(SocketAddress address) {
117+
synchronized (this) {
118+
if (quicServer != null) {
119+
return vertx.getOrCreateContext().failedFuture("Already listening on port " + address.port());
120+
}
121+
quicServer = QuicServer.create(vertx, options);
122+
}
123+
quicServer.handler(this::handleConnection);
124+
return quicServer
125+
.bind(address)
126+
.map(this);
127+
}
128+
129+
@Override
130+
public Future<Void> shutdown(long timeout, TimeUnit unit) {
131+
QuicServer s;
132+
synchronized (this) {
133+
s = quicServer;
134+
if (s == null) {
135+
return vertx.getOrCreateContext().succeededFuture();
136+
}
137+
quicServer = null;
138+
}
139+
return s.shutdown(Duration.ofMillis(unit.toMillis(timeout)));
140+
}
141+
142+
@Override
143+
public int actualPort() {
144+
throw new UnsupportedOperationException();
145+
}
146+
}

0 commit comments

Comments
 (0)