diff --git a/vertx-core/pom.xml b/vertx-core/pom.xml
index c74063e3f7f..5ccb851cdf0 100644
--- a/vertx-core/pom.xml
+++ b/vertx-core/pom.xml
@@ -97,6 +97,10 @@
netty-transport-classes-kqueue
true
+
+ io.netty
+ netty-codec-http3
+
diff --git a/vertx-core/src/main/generated/io/vertx/core/http/Http3SettingsConverter.java b/vertx-core/src/main/generated/io/vertx/core/http/Http3SettingsConverter.java
new file mode 100644
index 00000000000..ec7cf71e10f
--- /dev/null
+++ b/vertx-core/src/main/generated/io/vertx/core/http/Http3SettingsConverter.java
@@ -0,0 +1,61 @@
+package io.vertx.core.http;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+
+/**
+ * Converter and mapper for {@link io.vertx.core.http.Http3Settings}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.http.Http3Settings} original class using Vert.x codegen.
+ */
+public class Http3SettingsConverter {
+
+ static void fromJson(Iterable> json, Http3Settings obj) {
+ for (java.util.Map.Entry member : json) {
+ switch (member.getKey()) {
+ case "qpackMaxTableCapacity":
+ if (member.getValue() instanceof Number) {
+ obj.setQpackMaxTableCapacity(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "maxFieldSectionSize":
+ if (member.getValue() instanceof Number) {
+ obj.setMaxFieldSectionSize(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "qpackMaxBlockedStreams":
+ if (member.getValue() instanceof Number) {
+ obj.setQpackMaxBlockedStreams(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "enableConnectProtocol":
+ if (member.getValue() instanceof Number) {
+ obj.setEnableConnectProtocol(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "h3Datagram":
+ if (member.getValue() instanceof Number) {
+ obj.setH3Datagram(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "enableMetadata":
+ if (member.getValue() instanceof Number) {
+ obj.setEnableMetadata(((Number)member.getValue()).longValue());
+ }
+ break;
+ }
+ }
+ }
+
+ static void toJson(Http3Settings obj, JsonObject json) {
+ toJson(obj, json.getMap());
+ }
+
+ static void toJson(Http3Settings obj, java.util.Map json) {
+ json.put("qpackMaxTableCapacity", obj.getQpackMaxTableCapacity());
+ json.put("maxFieldSectionSize", obj.getMaxFieldSectionSize());
+ json.put("qpackMaxBlockedStreams", obj.getQpackMaxBlockedStreams());
+ json.put("enableConnectProtocol", obj.getEnableConnectProtocol());
+ json.put("h3Datagram", obj.getH3Datagram());
+ json.put("enableMetadata", obj.getEnableMetadata());
+ }
+}
diff --git a/vertx-core/src/main/generated/io/vertx/core/http/HttpClientOptionsConverter.java b/vertx-core/src/main/generated/io/vertx/core/http/HttpClientOptionsConverter.java
index be792704237..93a6b0ae0e4 100644
--- a/vertx-core/src/main/generated/io/vertx/core/http/HttpClientOptionsConverter.java
+++ b/vertx-core/src/main/generated/io/vertx/core/http/HttpClientOptionsConverter.java
@@ -102,6 +102,11 @@ static void fromJson(Iterable> json, HttpCli
obj.setInitialSettings(new io.vertx.core.http.Http2Settings((io.vertx.core.json.JsonObject)member.getValue()));
}
break;
+ case "initialHttp3Settings":
+ if (member.getValue() instanceof JsonObject) {
+ obj.setInitialHttp3Settings(new io.vertx.core.http.Http3Settings((io.vertx.core.json.JsonObject)member.getValue()));
+ }
+ break;
case "alpnVersions":
if (member.getValue() instanceof JsonArray) {
java.util.ArrayList list = new java.util.ArrayList<>();
@@ -185,6 +190,9 @@ static void toJson(HttpClientOptions obj, java.util.Map json) {
if (obj.getInitialSettings() != null) {
json.put("initialSettings", obj.getInitialSettings().toJson());
}
+ if (obj.getInitialHttp3Settings() != null) {
+ json.put("initialHttp3Settings", obj.getInitialHttp3Settings().toJson());
+ }
if (obj.getAlpnVersions() != null) {
JsonArray array = new JsonArray();
obj.getAlpnVersions().forEach(item -> array.add(item.name()));
diff --git a/vertx-core/src/main/generated/io/vertx/core/http/HttpServerOptionsConverter.java b/vertx-core/src/main/generated/io/vertx/core/http/HttpServerOptionsConverter.java
index d7cf9aead53..3a97b65613a 100644
--- a/vertx-core/src/main/generated/io/vertx/core/http/HttpServerOptionsConverter.java
+++ b/vertx-core/src/main/generated/io/vertx/core/http/HttpServerOptionsConverter.java
@@ -92,6 +92,11 @@ static void fromJson(Iterable> json, HttpSer
obj.setInitialSettings(new io.vertx.core.http.Http2Settings((io.vertx.core.json.JsonObject)member.getValue()));
}
break;
+ case "initialHttp3Settings":
+ if (member.getValue() instanceof JsonObject) {
+ obj.setInitialHttp3Settings(new io.vertx.core.http.Http3Settings((io.vertx.core.json.JsonObject)member.getValue()));
+ }
+ break;
case "alpnVersions":
if (member.getValue() instanceof JsonArray) {
java.util.ArrayList list = new java.util.ArrayList<>();
@@ -217,6 +222,9 @@ static void toJson(HttpServerOptions obj, java.util.Map json) {
if (obj.getInitialSettings() != null) {
json.put("initialSettings", obj.getInitialSettings().toJson());
}
+ if (obj.getInitialHttp3Settings() != null) {
+ json.put("initialHttp3Settings", obj.getInitialHttp3Settings().toJson());
+ }
if (obj.getAlpnVersions() != null) {
JsonArray array = new JsonArray();
obj.getAlpnVersions().forEach(item -> array.add(item.name()));
diff --git a/vertx-core/src/main/generated/io/vertx/core/net/ClientOptionsBaseConverter.java b/vertx-core/src/main/generated/io/vertx/core/net/ClientOptionsBaseConverter.java
index b7af2bef561..f40c0118486 100644
--- a/vertx-core/src/main/generated/io/vertx/core/net/ClientOptionsBaseConverter.java
+++ b/vertx-core/src/main/generated/io/vertx/core/net/ClientOptionsBaseConverter.java
@@ -47,6 +47,11 @@ static void fromJson(Iterable> json, ClientO
obj.setLocalAddress((String)member.getValue());
}
break;
+ case "quicOptions":
+ if (member.getValue() instanceof JsonObject) {
+ obj.setQuicOptions(new io.vertx.core.net.QuicOptions((io.vertx.core.json.JsonObject)member.getValue()));
+ }
+ break;
}
}
}
@@ -72,5 +77,8 @@ static void toJson(ClientOptionsBase obj, java.util.Map json) {
if (obj.getLocalAddress() != null) {
json.put("localAddress", obj.getLocalAddress());
}
+ if (obj.getQuicOptions() != null) {
+ json.put("quicOptions", obj.getQuicOptions().toJson());
+ }
}
}
diff --git a/vertx-core/src/main/generated/io/vertx/core/net/NetServerOptionsConverter.java b/vertx-core/src/main/generated/io/vertx/core/net/NetServerOptionsConverter.java
index d1f2c81e358..b10730a8612 100644
--- a/vertx-core/src/main/generated/io/vertx/core/net/NetServerOptionsConverter.java
+++ b/vertx-core/src/main/generated/io/vertx/core/net/NetServerOptionsConverter.java
@@ -62,6 +62,11 @@ static void fromJson(Iterable> json, NetServ
obj.setRegisterWriteHandler((Boolean)member.getValue());
}
break;
+ case "quicOptions":
+ if (member.getValue() instanceof JsonObject) {
+ obj.setQuicOptions(new io.vertx.core.net.QuicOptions((io.vertx.core.json.JsonObject)member.getValue()));
+ }
+ break;
}
}
}
@@ -89,5 +94,8 @@ static void toJson(NetServerOptions obj, java.util.Map json) {
json.put("trafficShapingOptions", obj.getTrafficShapingOptions().toJson());
}
json.put("registerWriteHandler", obj.isRegisterWriteHandler());
+ if (obj.getQuicOptions() != null) {
+ json.put("quicOptions", obj.getQuicOptions().toJson());
+ }
}
}
diff --git a/vertx-core/src/main/generated/io/vertx/core/net/QuicOptionsConverter.java b/vertx-core/src/main/generated/io/vertx/core/net/QuicOptionsConverter.java
new file mode 100644
index 00000000000..c8837b6c2a8
--- /dev/null
+++ b/vertx-core/src/main/generated/io/vertx/core/net/QuicOptionsConverter.java
@@ -0,0 +1,75 @@
+package io.vertx.core.net;
+
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+
+/**
+ * Converter and mapper for {@link io.vertx.core.net.QuicOptions}.
+ * NOTE: This class has been automatically generated from the {@link io.vertx.core.net.QuicOptions} original class using Vert.x codegen.
+ */
+public class QuicOptionsConverter {
+
+ static void fromJson(Iterable> json, QuicOptions obj) {
+ for (java.util.Map.Entry member : json) {
+ switch (member.getKey()) {
+ case "http3InitialMaxStreamsBidirectional":
+ if (member.getValue() instanceof Number) {
+ obj.setHttp3InitialMaxStreamsBidirectional(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "http3InitialMaxData":
+ if (member.getValue() instanceof Number) {
+ obj.setHttp3InitialMaxData(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "http3InitialMaxStreamDataBidirectionalLocal":
+ if (member.getValue() instanceof Number) {
+ obj.setHttp3InitialMaxStreamDataBidirectionalLocal(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "http3InitialMaxStreamDataBidirectionalRemote":
+ if (member.getValue() instanceof Number) {
+ obj.setHttp3InitialMaxStreamDataBidirectionalRemote(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "http3InitialMaxStreamDataUnidirectional":
+ if (member.getValue() instanceof Number) {
+ obj.setHttp3InitialMaxStreamDataUnidirectional(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "http3InitialMaxStreamsUnidirectional":
+ if (member.getValue() instanceof Number) {
+ obj.setHttp3InitialMaxStreamsUnidirectional(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "sslHandshakeTimeout":
+ if (member.getValue() instanceof Number) {
+ obj.setSslHandshakeTimeout(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "sslHandshakeTimeoutUnit":
+ if (member.getValue() instanceof String) {
+ obj.setSslHandshakeTimeoutUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+ }
+ break;
+ }
+ }
+ }
+
+ static void toJson(QuicOptions obj, JsonObject json) {
+ toJson(obj, json.getMap());
+ }
+
+ static void toJson(QuicOptions obj, java.util.Map json) {
+ json.put("http3InitialMaxStreamsBidirectional", obj.getHttp3InitialMaxStreamsBidirectional());
+ json.put("http3InitialMaxData", obj.getHttp3InitialMaxData());
+ json.put("http3InitialMaxStreamDataBidirectionalLocal", obj.getHttp3InitialMaxStreamDataBidirectionalLocal());
+ json.put("http3InitialMaxStreamDataBidirectionalRemote", obj.getHttp3InitialMaxStreamDataBidirectionalRemote());
+ json.put("http3InitialMaxStreamDataUnidirectional", obj.getHttp3InitialMaxStreamDataUnidirectional());
+ json.put("http3InitialMaxStreamsUnidirectional", obj.getHttp3InitialMaxStreamsUnidirectional());
+ json.put("sslHandshakeTimeout", obj.getSslHandshakeTimeout());
+ if (obj.getSslHandshakeTimeoutUnit() != null) {
+ json.put("sslHandshakeTimeoutUnit", obj.getSslHandshakeTimeoutUnit().name());
+ }
+ }
+}
diff --git a/vertx-core/src/main/java/examples/HTTP2Examples.java b/vertx-core/src/main/java/examples/HTTP2Examples.java
index 34527cd1226..2daa413376b 100644
--- a/vertx-core/src/main/java/examples/HTTP2Examples.java
+++ b/vertx-core/src/main/java/examples/HTTP2Examples.java
@@ -230,7 +230,7 @@ public void example21(HttpConnection connection) {
}
public void example22(HttpConnection connection) {
- connection.remoteSettingsHandler(settings -> {
+ connection.remoteHttp3SettingsHandler(settings -> {
System.out.println("Received new settings");
});
}
diff --git a/vertx-core/src/main/java/examples/h3devexamples/HTTP2ClientExamplesVertxHandler.java b/vertx-core/src/main/java/examples/h3devexamples/HTTP2ClientExamplesVertxHandler.java
new file mode 100644
index 00000000000..7cd4c3574b3
--- /dev/null
+++ b/vertx-core/src/main/java/examples/h3devexamples/HTTP2ClientExamplesVertxHandler.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ */
+
+package examples.h3devexamples;
+
+import io.netty.buffer.ByteBuf;
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.core.internal.net.NetSocketInternal;
+import io.vertx.core.net.JdkSSLEngineOptions;
+import io.vertx.core.net.NetClient;
+import io.vertx.core.net.NetClientOptions;
+import io.vertx.core.net.SocketAddress;
+
+/**
+ * @author Iman Zolfaghari
+ */
+public class HTTP2ClientExamplesVertxHandler {
+ protected NetClientOptions createNetClientOptions() {
+ NetClientOptions options = new NetClientOptions();
+ options
+ .setSslEngineOptions(new JdkSSLEngineOptions())
+ .setUseAlpn(true)
+ .setSsl(true)
+ .setTrustAll(true)
+// .setHostnameVerificationAlgorithm("HTTPS")
+ .setHostnameVerificationAlgorithm("")
+// .setTrustOptions(Trust.SERVER_JKS.get())
+ ;
+
+ return options;
+ }
+
+ public void example02Local(Vertx vertx) {
+ String path = "/";
+ int port = 8090;
+ String host = "localhost";
+
+/*
+ AtomicInteger requests = new AtomicInteger();
+
+ int n = 5;
+
+ for (int i = 0; i < n; i++) {
+ int counter = i + 1;
+ client.request(HttpMethod.GET, port, host, path)
+ .compose(req -> req.send("Msg " + counter))
+ .compose(HttpClientResponse::body)
+ .onSuccess(body -> System.out.println(
+ "Msg" + counter + " response body is: " + body))
+ .onComplete(event -> requests.incrementAndGet())
+ .onFailure(Throwable::printStackTrace)
+ ;
+ }
+*/
+
+ NetClient client = vertx.createNetClient(createNetClientOptions().setConnectTimeout(1000));
+
+ client.connect(SocketAddress.inetSocketAddress(8090, "localhost")).onSuccess(so -> {
+ NetSocketInternal soi = (NetSocketInternal) so;
+ StringBuilder part1 = new StringBuilder();
+ part1.append("1".repeat(1200));
+ part1.append("2".repeat(1200));
+ part1.append("3".repeat(1200));
+ part1.append("4".repeat(1200));
+
+ StringBuilder part2 = new StringBuilder();
+ part2.append("3".repeat(1200));
+ part2.append("4".repeat(1200));
+
+ soi.write(Buffer.buffer(part1.toString()));
+// soi.write(Buffer.buffer(part2.toString()));
+ // soi.messageHandler(msg -> fail("Unexpected"));
+ soi.messageHandler(msg -> {
+ ByteBuf byteBuf = (ByteBuf) msg;
+
+ byte[]arr = new byte[byteBuf.readableBytes()];
+ byteBuf.copy().readBytes(arr);
+ System.out.println("received ByteBuf is: " + new String(arr));
+
+
+ if(!byteBuf.isDirect()) throw new RuntimeException();
+ if(1 != byteBuf.refCnt()) throw new RuntimeException();
+// if(!"Hello World".equals(byteBuf.toString(StandardCharsets.UTF_8))) throw new RuntimeException();
+ if(!byteBuf.release()) throw new RuntimeException();
+ if(0 != byteBuf.refCnt()) throw new RuntimeException();
+ System.out.println("OK");
+ });
+ }).onFailure(Throwable::printStackTrace);
+
+
+
+
+
+
+ int n = 10000;
+ int i = 0;
+ while (i != n) {
+ i++;
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ vertx.close();
+
+ }
+
+ public static void main(String[] args) {
+ Vertx vertx =
+ Vertx.vertx(new VertxOptions().setBlockedThreadCheckInterval(1_000_000_000));
+ new HTTP2ClientExamplesVertxHandler().example02Local(vertx);
+ }
+}
diff --git a/vertx-core/src/main/java/examples/h3devexamples/HTTP2ServerExamplesVertxHandler.java b/vertx-core/src/main/java/examples/h3devexamples/HTTP2ServerExamplesVertxHandler.java
new file mode 100644
index 00000000000..1516c19ac7e
--- /dev/null
+++ b/vertx-core/src/main/java/examples/h3devexamples/HTTP2ServerExamplesVertxHandler.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ */
+
+package examples.h3devexamples;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.handler.ssl.util.SelfSignedCertificate;
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.core.internal.net.NetSocketInternal;
+import io.vertx.core.net.NetServer;
+import io.vertx.core.net.NetServerOptions;
+import io.vertx.core.net.PemKeyCertOptions;
+
+import java.nio.charset.StandardCharsets;
+import java.security.cert.CertificateException;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Iman Zolfaghari
+ */
+public class HTTP2ServerExamplesVertxHandler {
+
+ protected NetServerOptions createNetServerOptions() {
+ NetServerOptions options = new NetServerOptions();
+ options.setPort(8090);
+
+ options.setUseAlpn(true).setSsl(true);
+
+ SelfSignedCertificate ssc = null;
+ try {
+ ssc = new SelfSignedCertificate();
+ } catch (CertificateException e) {
+ throw new RuntimeException(e);
+ }
+ options.setKeyCertOptions(new PemKeyCertOptions()
+ .setCertPath(ssc.certificate().getAbsolutePath())
+ .setKeyPath(ssc.privateKey().getAbsolutePath())
+ );
+
+
+ return options;
+ }
+
+ public void example02Server(Vertx vertx) throws Exception {
+ NetServer server = vertx.createNetServer(createNetServerOptions());
+
+
+ server.connectHandler(so -> {
+ NetSocketInternal soi = (NetSocketInternal) so;
+ soi.messageHandler(msg -> {
+ ByteBuf byteBuf = (ByteBuf) msg;
+ byte[]arr = new byte[byteBuf.readableBytes()];
+ byteBuf.readBytes(arr);
+ System.out.println("new String(arr) = " + new String(arr));
+ if (!byteBuf.isDirect()) throw new RuntimeException();
+ if (1 != byteBuf.refCnt()) throw new RuntimeException();
+ ByteBuf buffer = Unpooled.buffer();
+ buffer.writeCharSequence("OK", StandardCharsets.UTF_8);
+ soi.writeMessage(buffer).onSuccess(v -> {
+// if (0 != byteBuf.refCnt()) throw new RuntimeException();
+ System.out.println("OK");
+ });
+ });
+ });
+ server.exceptionHandler(Throwable::printStackTrace);
+
+ server.listen();
+ }
+
+ public static void main(String[] args) throws Exception {
+ VertxOptions options = new VertxOptions()
+ .setBlockedThreadCheckInterval(1_000_000_000);
+
+ Vertx vertx = Vertx.vertx(options);
+ new HTTP2ServerExamplesVertxHandler().example02Server(vertx);
+ }
+}
diff --git a/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientExamples.java b/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientExamples.java
new file mode 100644
index 00000000000..55184d59836
--- /dev/null
+++ b/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientExamples.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ */
+
+package examples.h3devexamples;
+
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.core.http.HttpClient;
+import io.vertx.core.http.HttpClientOptions;
+import io.vertx.core.http.HttpClientResponse;
+import io.vertx.core.http.HttpMethod;
+import io.vertx.core.http.HttpVersion;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author Iman Zolfaghari
+ */
+public class HTTP3ClientExamples {
+ public void example02Local(Vertx vertx) {
+
+ HttpClientOptions options = new HttpClientOptions().
+ setSsl(true).
+ setIdleTimeout(1).
+ setReadIdleTimeout(1).
+ setWriteIdleTimeout(1).
+ setIdleTimeoutUnit(TimeUnit.HOURS).
+ setUseAlpn(true).
+ setForceSni(true).
+ setVerifyHost(false).
+ setTrustAll(true).
+ setProtocolVersion(HttpVersion.HTTP_3);
+
+ options
+ .getSslOptions()
+ .setSslHandshakeTimeout(1)
+ .setSslHandshakeTimeoutUnit(TimeUnit.HOURS);
+ HttpClient client = vertx.createHttpClient(options);
+
+ String path = "/";
+ int port = 8090;
+ String host = "localhost";
+
+ AtomicInteger requests = new AtomicInteger();
+
+ int n = 5;
+
+ for (int i = 0; i < n; i++) {
+ int counter = i + 1;
+ client.request(HttpMethod.GET, port, host, path)
+ .compose(req -> req.send("Msg " + counter))
+ .compose(HttpClientResponse::body)
+ .onSuccess(body -> System.out.println(
+ "Msg" + counter + " response body is: " + body))
+ .onComplete(event -> requests.incrementAndGet())
+ .onFailure(Throwable::printStackTrace)
+ ;
+ }
+
+ while (requests.get() != n) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ vertx.close();
+
+ }
+
+ public static void main(String[] args) {
+ Vertx vertx =
+ Vertx.vertx(new VertxOptions().setBlockedThreadCheckInterval(1_000_000_000));
+ new HTTP3ClientExamples().example02Local(vertx);
+ }
+}
diff --git a/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientExamplesAsyncTestCase.java b/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientExamplesAsyncTestCase.java
new file mode 100644
index 00000000000..3ee09a39761
--- /dev/null
+++ b/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientExamplesAsyncTestCase.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ */
+
+package examples.h3devexamples;
+
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.core.http.HttpClient;
+import io.vertx.core.http.HttpClientOptions;
+import io.vertx.core.http.HttpMethod;
+import io.vertx.core.http.HttpVersion;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author Iman Zolfaghari
+ */
+public class HTTP3ClientExamplesAsyncTestCase {
+ public void example03Local(Vertx vertx) {
+
+ HttpClientOptions options = new HttpClientOptions().
+ setSsl(true).
+ setIdleTimeout(1).
+ setReadIdleTimeout(1).
+ setWriteIdleTimeout(1).
+ setIdleTimeoutUnit(TimeUnit.HOURS).
+ setUseAlpn(true).
+ setForceSni(true).
+ setVerifyHost(false).
+ setTrustAll(true).
+ setProtocolVersion(HttpVersion.HTTP_3);
+
+ options
+ .getSslOptions()
+ .setSslHandshakeTimeout(1)
+ .setSslHandshakeTimeoutUnit(TimeUnit.HOURS);
+ HttpClient client = vertx.createHttpClient(options);
+
+ String path = "/";
+ int port = 8090;
+ String host = "localhost";
+
+ AtomicInteger requests = new AtomicInteger();
+
+ int n = 1;
+
+ client.request(HttpMethod.GET, port, host, path)
+ .compose(req -> {
+ System.out.println("sending request ...");
+ return req.send();
+ })
+ .compose(resp -> {
+ System.out.println("receiving resp ...");
+ assert 200 == resp.statusCode();
+ return resp.end();
+ }
+ )
+ .onSuccess(event -> {
+ System.out.println("testComplete() called! ");
+ })
+ .onComplete(event -> requests.incrementAndGet())
+ .onFailure(Throwable::printStackTrace)
+ ;
+
+ while (requests.get() != n) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ vertx.close();
+
+ }
+
+ public static void main(String[] args) {
+ Vertx vertx =
+ Vertx.vertx(new VertxOptions().setBlockedThreadCheckInterval(1_000_000_000));
+ new HTTP3ClientExamplesAsyncTestCase().example03Local(vertx);
+ }
+}
diff --git a/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientExamplesSni.java b/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientExamplesSni.java
new file mode 100644
index 00000000000..b7086852c37
--- /dev/null
+++ b/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientExamplesSni.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ */
+
+package examples.h3devexamples;
+
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.core.http.HttpClient;
+import io.vertx.core.http.HttpClientOptions;
+import io.vertx.core.http.HttpClientResponse;
+import io.vertx.core.http.HttpMethod;
+import io.vertx.core.http.HttpVersion;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author Iman Zolfaghari
+ */
+public class HTTP3ClientExamplesSni {
+ public void example02Local(Vertx vertx) {
+
+ HttpClientOptions options = new HttpClientOptions().
+ setSsl(true).
+ setIdleTimeout(1).
+ setReadIdleTimeout(1).
+ setWriteIdleTimeout(1).
+ setIdleTimeoutUnit(TimeUnit.HOURS).
+ setUseAlpn(true).
+ setForceSni(true).
+ setVerifyHost(false).
+ setTrustAll(true).
+ setProtocolVersion(HttpVersion.HTTP_3);
+
+ options
+ .getSslOptions()
+ .setSslHandshakeTimeout(1)
+ .setSslHandshakeTimeoutUnit(TimeUnit.HOURS);
+ HttpClient client = vertx.createHttpClient(options);
+
+ String path = "/";
+ int port = 8090;
+ String host = "localhost";
+
+ AtomicInteger requests = new AtomicInteger();
+
+ int n = 1;
+
+ for (int i = 0; i < n; i++) {
+ int counter = i + 1;
+ client.request(HttpMethod.GET, port, host, path)
+ .compose(req -> req.send("Msg " + counter))
+ .compose(HttpClientResponse::body)
+ .onSuccess(body -> System.out.println(
+ "Msg" + counter + " response body is: " + body))
+ .onComplete(event -> requests.incrementAndGet())
+ .onFailure(Throwable::printStackTrace)
+ ;
+ }
+
+ while (requests.get() != n) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ vertx.close();
+
+ }
+
+ public static void main(String[] args) {
+ Vertx vertx =
+ Vertx.vertx(new VertxOptions().setBlockedThreadCheckInterval(1_000_000_000));
+ new HTTP3ClientExamplesSni().example02Local(vertx);
+ }
+}
diff --git a/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientExamplesVertxHandler.java b/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientExamplesVertxHandler.java
new file mode 100644
index 00000000000..4fee71fdb18
--- /dev/null
+++ b/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientExamplesVertxHandler.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ */
+
+package examples.h3devexamples;
+
+import io.netty.buffer.ByteBuf;
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.core.http.HttpVersion;
+import io.vertx.core.http.impl.http2.Http3Utils;
+import io.vertx.core.internal.net.NetSocketInternal;
+import io.vertx.core.net.JdkSSLEngineOptions;
+import io.vertx.core.net.NetClient;
+import io.vertx.core.net.NetClientOptions;
+import io.vertx.core.net.SocketAddress;
+
+/**
+ * @author Iman Zolfaghari
+ */
+public class HTTP3ClientExamplesVertxHandler {
+ protected NetClientOptions createNetClientOptions() {
+ NetClientOptions options = new NetClientOptions();
+ options
+ .getSslOptions()
+ .setApplicationLayerProtocols(Http3Utils.supportedApplicationProtocols());
+ options
+ .setSslEngineOptions(new JdkSSLEngineOptions())
+ .setUseAlpn(true)
+ .setSsl(true)
+ .setTrustAll(true)
+// .setHostnameVerificationAlgorithm("HTTPS")
+ .setHostnameVerificationAlgorithm("")
+// .setTrustOptions(Trust.SERVER_JKS.get())
+ ;
+
+
+ return options;
+ }
+
+ public void example02Local(Vertx vertx) {
+
+/*
+ HttpClientOptions options = new HttpClientOptions().
+ setSsl(true).
+ setIdleTimeout(1).
+ setReadIdleTimeout(1).
+ setWriteIdleTimeout(1).
+ setIdleTimeoutUnit(TimeUnit.HOURS).
+ setUseAlpn(true).
+ setForceSni(true).
+ setVerifyHost(false).
+ setTrustAll(true).
+ setProtocolVersion(HttpVersion.HTTP_3);
+
+ options
+ .getSslOptions()
+ .setSslHandshakeTimeout(1)
+ .setSslHandshakeTimeoutUnit(TimeUnit.HOURS);
+ HttpClient client = vertx.createHttpClient(options);
+*/
+
+ String path = "/";
+ int port = 8090;
+ String host = "localhost";
+
+/*
+ AtomicInteger requests = new AtomicInteger();
+
+ int n = 5;
+
+ for (int i = 0; i < n; i++) {
+ int counter = i + 1;
+ client.request(HttpMethod.GET, port, host, path)
+ .compose(req -> req.send("Msg " + counter))
+ .compose(HttpClientResponse::body)
+ .onSuccess(body -> System.out.println(
+ "Msg" + counter + " response body is: " + body))
+ .onComplete(event -> requests.incrementAndGet())
+ .onFailure(Throwable::printStackTrace)
+ ;
+ }
+*/
+
+ NetClient client = vertx.createNetClient(createNetClientOptions().setConnectTimeout(1000));
+
+
+ client.connect(SocketAddress.inetSocketAddress(8090, "localhost")).onSuccess(so -> {
+ NetSocketInternal soi = (NetSocketInternal) so;
+ StringBuilder part1 = new StringBuilder();
+ part1.append("1".repeat(1200));
+ part1.append("2".repeat(1200));
+ part1.append("3".repeat(1200));
+ part1.append("4".repeat(1200));
+
+ StringBuilder part2 = new StringBuilder();
+ part2.append("3".repeat(1200));
+ part2.append("4".repeat(1200));
+
+ soi.write(Buffer.buffer(part1.toString()));
+// soi.write(Buffer.buffer(part2.toString()));
+ // soi.messageHandler(msg -> fail("Unexpected"));
+ soi.messageHandler(msg -> {
+ ByteBuf byteBuf = (ByteBuf) msg;
+
+ byte[]arr = new byte[byteBuf.readableBytes()];
+ byteBuf.copy().readBytes(arr);
+ System.out.println("received ByteBuf is: " + new String(arr));
+
+
+ if(!byteBuf.isDirect()) throw new RuntimeException();
+ if(1 != byteBuf.refCnt()) throw new RuntimeException();
+// if(!"Hello World".equals(byteBuf.toString(StandardCharsets.UTF_8))) throw new RuntimeException();
+ if(!byteBuf.release()) throw new RuntimeException();
+ if(0 != byteBuf.refCnt()) throw new RuntimeException();
+ System.out.println("OK");
+ });
+ }).onFailure(Throwable::printStackTrace);
+
+
+
+
+
+
+ int n = 10000;
+ int i = 0;
+ while (i != n) {
+ i++;
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ vertx.close();
+
+ }
+
+ public static void main(String[] args) {
+ Vertx vertx =
+ Vertx.vertx(new VertxOptions().setBlockedThreadCheckInterval(1_000_000_000));
+ new HTTP3ClientExamplesVertxHandler().example02Local(vertx);
+ }
+}
diff --git a/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientGoogleExamples.java b/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientGoogleExamples.java
new file mode 100644
index 00000000000..79787c99f9e
--- /dev/null
+++ b/vertx-core/src/main/java/examples/h3devexamples/HTTP3ClientGoogleExamples.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ * which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ */
+
+package examples.h3devexamples;
+
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.core.http.HttpClient;
+import io.vertx.core.http.HttpClientOptions;
+import io.vertx.core.http.HttpClientResponse;
+import io.vertx.core.http.HttpMethod;
+import io.vertx.core.http.HttpVersion;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * @author Iman Zolfaghari
+ */
+public class HTTP3ClientGoogleExamples {
+ private final static String okText =
+ "\n ____ _ __ \n" +
+ " / __ \\ | |/ / \n" +
+ "| | | || < \n" +
+ "| | | || |\\ \\ \n" +
+ "| |__| || | \\ \\ \n" +
+ " \\____/ |_| \\_\\ \n";
+
+ public void example01(Vertx vertx) {
+
+ String path = "/";
+// String path = "/cdn-cgi/trace";
+ int port = 443;
+// int port = 9999;
+// int port = 8090;
+// String host = "http3.is";
+ String host = "www.google.com";
+// String host = "localhost";
+// String host = "quic.nginx.org";
+// String host = "www.cloudflare.com";
+// String host = NetUtil.LOCALHOST4.getHostAddress();
+// String host = "www.mozilla.org";
+// String host = "www.bing.com";
+// String host = "www.yahoo.com";
+
+ HttpClientOptions options = new HttpClientOptions().
+ setSsl(true).
+ setIdleTimeout(1).
+ setReadIdleTimeout(1).
+ setWriteIdleTimeout(1).
+ setIdleTimeoutUnit(TimeUnit.HOURS).
+ setUseAlpn(true).
+ setForceSni(true).
+ setDefaultHost(host).
+ setVerifyHost(false).
+ setTrustAll(true).
+ setProtocolVersion(HttpVersion.HTTP_3);
+
+ options
+ .getSslOptions()
+ .setSslHandshakeTimeout(1)
+ .setSslHandshakeTimeoutUnit(TimeUnit.HOURS);
+
+
+ HttpClient client = vertx.createHttpClient(options);
+
+ System.out.print(String.format("Trying to fetch %s:%s%s\n", host, port,
+ path));
+
+ AtomicBoolean finished = new AtomicBoolean(false);
+
+ client.request(HttpMethod.GET, port, host, path)
+ .compose(req -> {
+
+ req.connection().goAwayHandler(goAway -> {
+ System.out.println(" Received goAway from server! ");
+ });
+
+ req.connection().shutdownHandler(v -> {
+ System.out.println(" Received shutdown signal! ");
+ req.connection().close();
+ vertx.close();
+ });
+
+// try {
+// System.out.println("req = " + req.connection().peerCertificates());
+// } catch (SSLPeerUnverifiedException e) {
+// throw new RuntimeException(e);
+// }
+
+ return req
+ .end()
+ .compose(res -> req
+ .response()
+ .onSuccess(resp -> {
+// System.out.println("The returned headers are: " + resp
+// .headers());
+ System.out.println("The returned Alt-Svc is: " + resp.headers().get(
+ "Alt-Svc"));
+ }).compose(HttpClientResponse::body).onSuccess(body -> {
+ if (host.contains("google.com") && body.toString().endsWith(
+ "google.log(\"rcm\"," +
+ "\"&ei=\"+c+\"&tgtved=\"+f+\"&jsname=\"+(a||\"\"))}}else " +
+ "F=a,E=[c]}window.document.addEventListener" +
+ "(\"DOMContentLoaded\"," +
+ "function(){document.body.addEventListener(\"click\",G)})" +
+ ";" +
+ "}).call(this);