// DEPS tech.kwik:kwik:0.10.7 // DEPS tech.kwik:kwik-qlog:0.10.7 // DEPS tech.kwik:flupke:0.9 // Install mkcert with Chocolatey == choco install mkcert // Install CA root ================= mkcert -install // Create cert for localhost ======= mkcert localhost 127.0.0.1 ::1 // Find CA root path =============== mkcert -caroot // // Create PKCS12 keystore for Java ================================ // openssl pkcs12 -export -out "keystore.p12" -inkey "${KEY_FILE}" -in "${CERT_FILE}" // -name "somealias" -certfile "$(mkcert -CAROOT)/rootCA.pem" // ================================================================ // import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.file.Files.newInputStream; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpClient.Version; import java.net.http.HttpRequest; import java.net.http.HttpResponse.BodyHandlers; import java.nio.file.Path; import java.security.KeyStore; import java.time.Duration; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import tech.kwik.core.log.SysOutLogger; import tech.kwik.core.server.ServerConnectionConfig; import tech.kwik.core.server.ServerConnector; import tech.kwik.flupke.server.Http3ApplicationProtocolFactory; public class Timeout { void main() throws Exception { var keystore = KeyStore.getInstance("PKCS12"); var password = "password"; keystore.load(newInputStream(Path.of("keystore.p12")), password.toCharArray()); var certificateAlias = keystore.aliases().nextElement(); var config = ServerConnectionConfig.builder() .maxIdleTimeoutInSeconds(50) .maxUnidirectionalStreamBufferSize(1_000_000) .maxBidirectionalStreamBufferSize(1_000_000) .maxConnectionBufferSize(10_000_000) .maxOpenPeerInitiatedUnidirectionalStreams(10) .maxOpenPeerInitiatedBidirectionalStreams(100) .connectionIdLength(8) .retryRequired(true) .build(); // http3 server on udp 8080 var connector = ServerConnector.builder() .withConfiguration(config) .withLogger(new SysOutLogger()) .withPort(8080) .withKeyStore(keystore, certificateAlias, password.toCharArray()) .build(); var factory = new Http3ApplicationProtocolFactory( (request, response) -> { try { Thread.sleep(Duration.ofSeconds(40)); } catch (InterruptedException e) { Thread.interrupted(); } response.setStatus(200); var stream = response.getOutputStream(); stream.write("Hello, world!".getBytes(UTF_8)); stream.flush(); }); connector.registerApplicationProtocol("h3", factory); connector.start(); try { var kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(keystore, password.toCharArray()); var sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(), null, null); var response = HttpClient.newBuilder() .version(Version.valueOf("HTTP_3")) .sslContext(sslContext) .build() .send( HttpRequest.newBuilder() .timeout(Duration.ofSeconds(45)) .uri(URI.create("https://localhost:8080")) .GET() .build(), BodyHandlers.ofString()) .body(); assert "Hello, world!".equals(response); } finally { connector.close(); } } }