Skip to content

Commit

Permalink
Add HTTP/3 initial settings
Browse files Browse the repository at this point in the history
Related to #1531
  • Loading branch information
violetagg committed Apr 12, 2024
1 parent 263c4e6 commit 54e4471
Show file tree
Hide file tree
Showing 4 changed files with 353 additions and 0 deletions.
@@ -0,0 +1,217 @@
/*
* Copyright (c) 2024 VMware, Inc. or its affiliates, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package reactor.netty.http;

/**
* A configuration builder to fine tune the HTTP/3 settings.
*
* @author Violeta Georgieva
* @since 1.2.0
*/
public final class Http3SettingsSpec {

public interface Builder {

/**
* Build a new {@link Http3SettingsSpec}.
*
* @return a new {@link Http3SettingsSpec}
*/
Http3SettingsSpec build();

/**
* Set the initial maximum data limit.
* See <a href="https://docs.rs/quiche/0.6.0/quiche/struct.Config.html#method.set_initial_max_data">
* set_initial_max_data</a>.
* Default to {@link Build#DEFAULT_MAX_DATA}
*
* @param maxData the initial maximum data limit
* @return {@code this}
*/
Builder maxData(long maxData);

/**
* Set the initial maximum data limit for local bidirectional streams.
* See
* <a href="https://docs.rs/quiche/0.6.0/quiche/struct.Config.html#method.set_initial_max_stream_data_bidi_local">
* set_initial_max_stream_data_bidi_local</a>.
* Default to {@link Build#DEFAULT_MAX_STREAM_DATA_BIDIRECTIONAL_LOCAL}
*
* @param maxStreamDataBidirectionalLocal the initial maximum data limit for local bidirectional streams
* @return {@code this}
*/
Builder maxStreamDataBidirectionalLocal(long maxStreamDataBidirectionalLocal);

/**
* Set the initial maximum data limit for remote bidirectional streams.
* See
* <a href="https://docs.rs/quiche/0.6.0/quiche/struct.Config.html#method.set_initial_max_stream_data_bidi_remote">
* set_initial_max_stream_data_bidi_remote</a>.
* Default to {@link Build#DEFAULT_MAX_STREAM_DATA_BIDIRECTIONAL_REMOTE}
*
* @param maxStreamDataBidirectionalRemote the initial maximum data limit for remote bidirectional streams
* @return {@code this}
*/
Builder maxStreamDataBidirectionalRemote(long maxStreamDataBidirectionalRemote);

/**
* Set the initial maximum stream limit for bidirectional streams.
* See
* <a href="https://docs.rs/quiche/0.6.0/quiche/struct.Config.html#method.set_initial_max_streams_bidi">
* set_initial_max_streams_bidi</a>.
* Default to {@link Build#DEFAULT_MAX_STREAMS_BIDIRECTIONAL}
*
* @param maxStreamsBidirectional the initial maximum stream limit for bidirectional streams
* @return {@code this}
*/
Builder maxStreamsBidirectional(long maxStreamsBidirectional);
}

/**
* Creates a builder for {@link Http3SettingsSpec}.
*
* @return a new {@link Http3SettingsSpec.Builder}
*/
public static Http3SettingsSpec.Builder builder() {
return new Http3SettingsSpec.Build();
}

/**
* Return the configured initial maximum data limit.
*
* @return the configured initial maximum data limit
*/
public long maxData() {
return maxData;
}

/**
* Return the configured initial maximum data limit for local bidirectional streams.
*
* @return the configured initial maximum data limit for local bidirectional streams
*/
public long maxStreamDataBidirectionalLocal() {
return maxStreamDataBidirectionalLocal;
}

/**
* Return the configured initial maximum data limit for remote bidirectional streams.
*
* @return the configured initial maximum data limit for remote bidirectional streams
*/
public long maxStreamDataBidirectionalRemote() {
return maxStreamDataBidirectionalRemote;
}

/**
* Return the configured initial maximum stream limit for bidirectional streams.
*
* @return the configured initial maximum stream limit for bidirectional streams
*/
public long maxStreamsBidirectional() {
return maxStreamsBidirectional;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Http3SettingsSpec)) {
return false;
}
Http3SettingsSpec that = (Http3SettingsSpec) o;
return maxData == that.maxData &&
maxStreamDataBidirectionalLocal == that.maxStreamDataBidirectionalLocal &&
maxStreamDataBidirectionalRemote == that.maxStreamDataBidirectionalRemote &&
maxStreamsBidirectional == that.maxStreamsBidirectional;
}

@Override
public int hashCode() {
int result = 1;
result = 31 * result + Long.hashCode(maxData);
result = 31 * result + Long.hashCode(maxStreamDataBidirectionalLocal);
result = 31 * result + Long.hashCode(maxStreamDataBidirectionalRemote);
result = 31 * result + Long.hashCode(maxStreamsBidirectional);
return result;
}

final long maxData;
final long maxStreamDataBidirectionalLocal;
final long maxStreamDataBidirectionalRemote;
final long maxStreamsBidirectional;

Http3SettingsSpec(Build build) {
this.maxData = build.maxData;
this.maxStreamDataBidirectionalLocal = build.maxStreamDataBidirectionalLocal;
this.maxStreamDataBidirectionalRemote = build.maxStreamDataBidirectionalRemote;
this.maxStreamsBidirectional = build.maxStreamsBidirectional;
}

static final class Build implements Builder {
static final long DEFAULT_MAX_DATA = 0L;
static final long DEFAULT_MAX_STREAM_DATA_BIDIRECTIONAL_LOCAL = 0L;
static final long DEFAULT_MAX_STREAM_DATA_BIDIRECTIONAL_REMOTE = 0L;
static final long DEFAULT_MAX_STREAMS_BIDIRECTIONAL = 0L;

long maxData = DEFAULT_MAX_DATA;
long maxStreamDataBidirectionalLocal = DEFAULT_MAX_STREAM_DATA_BIDIRECTIONAL_LOCAL;
long maxStreamDataBidirectionalRemote = DEFAULT_MAX_STREAM_DATA_BIDIRECTIONAL_REMOTE;
long maxStreamsBidirectional = DEFAULT_MAX_STREAMS_BIDIRECTIONAL;

@Override
public Http3SettingsSpec build() {
return new Http3SettingsSpec(this);
}

@Override
public Builder maxData(long maxData) {
if (maxData < 0) {
throw new IllegalArgumentException("maxData must be positive or zero");
}
this.maxData = maxData;
return this;
}

@Override
public Builder maxStreamDataBidirectionalLocal(long maxStreamDataBidirectionalLocal) {
if (maxStreamDataBidirectionalLocal < 0) {
throw new IllegalArgumentException("maxStreamDataBidirectionalLocal must be positive or zero");
}
this.maxStreamDataBidirectionalLocal = maxStreamDataBidirectionalLocal;
return this;
}

@Override
public Builder maxStreamDataBidirectionalRemote(long maxStreamDataBidirectionalRemote) {
if (maxStreamDataBidirectionalRemote < 0) {
throw new IllegalArgumentException("maxStreamDataBidirectionalRemote must be positive or zero");
}
this.maxStreamDataBidirectionalRemote = maxStreamDataBidirectionalRemote;
return this;
}

@Override
public Builder maxStreamsBidirectional(long maxStreamsBidirectional) {
if (maxStreamsBidirectional < 0) {
throw new IllegalArgumentException("maxStreamsBidirectional must be positive or zero");
}
this.maxStreamsBidirectional = maxStreamsBidirectional;
return this;
}
}
}
Expand Up @@ -41,6 +41,7 @@
import reactor.netty.ConnectionObserver;
import reactor.netty.channel.ChannelMetricsRecorder;
import reactor.netty.http.Http2SettingsSpec;
import reactor.netty.http.Http3SettingsSpec;
import reactor.netty.http.HttpProtocol;
import reactor.netty.http.logging.HttpMessageLogFactory;
import reactor.netty.http.logging.ReactorNettyHttpMessageLogFactory;
Expand Down Expand Up @@ -454,6 +455,26 @@ public final HttpServer http2Settings(Consumer<Http2SettingsSpec.Builder> http2S
return dup;
}

/**
* Apply HTTP/3 configuration.
*
* @param http3Settings configures {@link Http3SettingsSpec} before requesting
* @return a new {@link HttpServer}
* @since 1.2.0
*/
public final HttpServer http3Settings(Consumer<Http3SettingsSpec.Builder> http3Settings) {
Objects.requireNonNull(http3Settings, "http3Settings");
Http3SettingsSpec.Builder builder = Http3SettingsSpec.builder();
http3Settings.accept(builder);
Http3SettingsSpec settings = builder.build();
if (settings.equals(configuration().http3Settings)) {
return this;
}
HttpServer dup = duplicate();
dup.configuration().http3Settings = settings;
return dup;
}

/**
* Apply HTTP form decoder configuration.
* The configuration is used when {@link HttpServerRequest#receiveForm()} is invoked.
Expand Down
Expand Up @@ -59,6 +59,7 @@
import reactor.netty.channel.ChannelMetricsRecorder;
import reactor.netty.channel.ChannelOperations;
import reactor.netty.http.Http2SettingsSpec;
import reactor.netty.http.Http3SettingsSpec;
import reactor.netty.http.HttpProtocol;
import reactor.netty.http.HttpResources;
import reactor.netty.http.logging.HttpMessageLogFactory;
Expand Down Expand Up @@ -159,6 +160,16 @@ public Http2SettingsSpec http2SettingsSpec() {
return http2Settings;
}

/**
* Return the HTTP/3 configuration.
*
* @return the HTTP/3 configuration
* @since 1.2.0
*/
public Http3SettingsSpec http3SettingsSpec() {
return http3Settings;
}

/**
* Return the configured idle timeout for the connection when it is waiting for an HTTP request or null.
*
Expand Down Expand Up @@ -299,6 +310,7 @@ public Function<String, String> uriTagValue() {
HttpServerFormDecoderProvider formDecoderProvider;
BiFunction<ConnectionInfo, HttpRequest, ConnectionInfo> forwardedHeaderHandler;
Http2SettingsSpec http2Settings;
Http3SettingsSpec http3Settings;
HttpMessageLogFactory httpMessageLogFactory;
Duration idleTimeout;
BiFunction<? super Mono<Void>, ? super Connection, ? extends Mono<Void>>
Expand Down Expand Up @@ -341,6 +353,7 @@ public Function<String, String> uriTagValue() {
this.formDecoderProvider = parent.formDecoderProvider;
this.forwardedHeaderHandler = parent.forwardedHeaderHandler;
this.http2Settings = parent.http2Settings;
this.http3Settings = parent.http3Settings;
this.httpMessageLogFactory = parent.httpMessageLogFactory;
this.idleTimeout = parent.idleTimeout;
this.mapHandle = parent.mapHandle;
Expand Down Expand Up @@ -1214,6 +1227,7 @@ static final class HttpServerChannelInitializer implements ChannelPipelineConfig
final HttpServerFormDecoderProvider formDecoderProvider;
final BiFunction<ConnectionInfo, HttpRequest, ConnectionInfo> forwardedHeaderHandler;
final Http2SettingsSpec http2SettingsSpec;
final Http3SettingsSpec http3SettingsSpec;
final HttpMessageLogFactory httpMessageLogFactory;
final Duration idleTimeout;
final BiFunction<? super Mono<Void>, ? super Connection, ? extends Mono<Void>>
Expand Down Expand Up @@ -1242,6 +1256,7 @@ static final class HttpServerChannelInitializer implements ChannelPipelineConfig
this.formDecoderProvider = config.formDecoderProvider;
this.forwardedHeaderHandler = config.forwardedHeaderHandler;
this.http2SettingsSpec = config.http2Settings;
this.http3SettingsSpec = config.http3Settings;
this.httpMessageLogFactory = config.httpMessageLogFactory;
this.idleTimeout = config.idleTimeout;
this.mapHandle = config.mapHandle;
Expand Down

0 comments on commit 54e4471

Please sign in to comment.