package software.amazon.awssdk.crt.http; import java.util.List; import java.util.ArrayList; /** * Contains all the configuration options for a Http2StreamManager * instance */ public class Http2StreamManagerOptions { public static final int DEFAULT_MAX_WINDOW_SIZE = Integer.MAX_VALUE; public static final int DEFAULT_MAX = Integer.MAX_VALUE; public static final int DEFAULT_MAX_CONNECTIONS = 2; public static final int DEFAULT_CONNECTION_PING_TIMEOUT_MS = 3000; private HttpClientConnectionManagerOptions connectionManagerOptions; private int idealConcurrentStreamsPerConnection = 100; private boolean connectionManualWindowManagement = false; private int maxConcurrentStreamsPerConnection = DEFAULT_MAX; private boolean priorKnowledge = false; private boolean closeConnectionOnServerError = false; private int connectionPingPeriodMs = 0; private int connectionPingTimeoutMs = 0; private List initialSettingsList = new ArrayList(); /** * Default constructor */ public Http2StreamManagerOptions() { } /** * For HTTP/2 stream manager only. * * The initial settings for the HTTP/2 connections made by stream manger. * `Http2ConnectionSettingListBuilder` can help to build the settings list. * * To control the initial stream-level flow-control window, set the * INITIAL_WINDOW_SIZE setting in the initial settings. * * @param initialSettingsList The List of initial settings * @return this */ public Http2StreamManagerOptions withInitialSettingsList(List initialSettingsList) { this.initialSettingsList.addAll(initialSettingsList); return this; } /** * @return The List of initial settings */ public List getInitialSettingsList() { return this.initialSettingsList; } /** * For HTTP/2 stream manager only. * * The ideal number of concurrent streams for a connection. Stream manager will * try to create a new connection if one connection reaches this number. But, if * the max connections reaches, manager will reuse connections to create the * acquired steams as much as possible. * * @param idealConcurrentStreamsPerConnection The ideal number of concurrent * streams for a connection * @return this */ public Http2StreamManagerOptions withIdealConcurrentStreamsPerConnection(int idealConcurrentStreamsPerConnection) { this.idealConcurrentStreamsPerConnection = idealConcurrentStreamsPerConnection; return this; } /** * @return The ideal number of concurrent streams for a connection used for * manager */ public int getIdealConcurrentStreamsPerConnection() { return idealConcurrentStreamsPerConnection; } /** * Default is no limit, which will use the limit from the server. 0 will be * considered as using the default value. * The real number of concurrent streams per connection will be controlled by * the minimal value of the setting from other end and the value here. * * @param maxConcurrentStreamsPerConnection The max number of concurrent * streams for a connection * @return this */ public Http2StreamManagerOptions withMaxConcurrentStreamsPerConnection(int maxConcurrentStreamsPerConnection) { this.maxConcurrentStreamsPerConnection = maxConcurrentStreamsPerConnection; return this; } /** * @return The max number of concurrent streams for a connection set for * manager. * It could be different than the real limits, which is the minimal set * for manager and the settings from the other side. */ public int getMaxConcurrentStreamsPerConnection() { return maxConcurrentStreamsPerConnection; } /** * @return The connection level manual flow control enabled or not. */ public boolean isConnectionManualWindowManagement() { return connectionManualWindowManagement; } /** * Set to true to manually manage the flow-control window of whole HTTP/2 * connection. * The stream level flow-control window is controlled by the * manualWindowManagement in connectionManagerOptions. * * @param connectionManualWindowManagement Enable connection level manual flow * control or not. * @return this */ public Http2StreamManagerOptions withConnectionManualWindowManagement(boolean connectionManualWindowManagement) { this.connectionManualWindowManagement = connectionManualWindowManagement; return this; } /** * @return The connection manager options for the underlying connection manager. */ public HttpClientConnectionManagerOptions getConnectionManagerOptions() { return connectionManagerOptions; } /** * Required. * * The configuration options for the connection manager under the hood. * It controls the connection specific thing for the stream manager. See * `HttpClientConnectionManagerOptions` for details. * * Note: * 1. the windowSize of connection manager will be ignored, as the initial * flow-control window size for HTTP/2 stream * is controlled by the initial settings. * 2. The expectedHttpVersion will also be ignored. * * @param connectionManagerOptions The connection manager options for the * underlying connection manager * @return this */ public Http2StreamManagerOptions withConnectionManagerOptions( HttpClientConnectionManagerOptions connectionManagerOptions) { this.connectionManagerOptions = connectionManagerOptions; return this; } /** * @return Prior knowledge is used or not */ public boolean hasPriorKnowledge() { return priorKnowledge; } /** * Set to true to use prior knowledge to setup connection. * If any TLS was set, exception will be raised if prior knowledge is set during * validation. * If NO TLS was set, exception will be raised if prior knowledge is NOT set * during validation. * * @param priorKnowledge Prior knowledge used or not. * @return this */ public Http2StreamManagerOptions withPriorKnowledge(boolean priorKnowledge) { this.priorKnowledge = priorKnowledge; return this; } /** * @return Connection closed or not when server error happened (500/502/503/504 * response status code received). */ public boolean shouldCloseConnectionOnServerError() { return closeConnectionOnServerError; } /** * Set to true to inform stream manager to close connection when response with * 500/502/503/504 received. * Stream manager will stop using the connection with server error will start a * new connection for other streams. * * @param closeConnectionOnServerError Connection closed or not when server * error happened. * @return this */ public Http2StreamManagerOptions withCloseConnectionOnServerError(boolean closeConnectionOnServerError) { this.closeConnectionOnServerError = closeConnectionOnServerError; return this; } /** * Settings to control the period ping to be sent for connections held by stream * manager. * * @param periodMs The period for all the connections held by stream manager to * send a PING in milliseconds. If you specify 0, manager will * NOT send any PING. * @param timeoutMs Network connection will be closed if a ping response is not * received within this amount of time (milliseconds). If you * specify 0, a default value will be used. If this is larger * than periodMs, it will be capped to be equal. * @return this */ public Http2StreamManagerOptions withConnectionPing(int periodMs, int timeoutMs) { this.connectionPingPeriodMs = periodMs; this.connectionPingTimeoutMs = timeoutMs == 0 ? DEFAULT_CONNECTION_PING_TIMEOUT_MS : timeoutMs; this.connectionPingTimeoutMs = Math.min(this.connectionPingPeriodMs, this.connectionPingTimeoutMs); return this; } /** * @return The period for all the connections held by stream manager to send a * PING in milliseconds. */ public int getConnectionPingPeriodMs() { return connectionPingPeriodMs; } /** * @return The time for closing connection if ping not received within this * amount of time in milliseconds */ public int getConnectionPingTimeoutMs() { return connectionPingTimeoutMs; } /** * Validate the stream manager options are valid to use. Throw exceptions if * not. */ public void validateOptions() { if (connectionManagerOptions == null) { throw new IllegalArgumentException("Connection manager options are required."); } connectionManagerOptions.validateOptions(); if ((connectionManagerOptions.getTlsConnectionOptions() != null || connectionManagerOptions.getTlsContext() != null) && priorKnowledge) { throw new IllegalArgumentException("HTTP/2 prior knowledge cannot be set when TLS is used."); } if ((connectionManagerOptions.getTlsConnectionOptions() == null && connectionManagerOptions.getTlsContext() == null) && !priorKnowledge) { throw new IllegalArgumentException( "Prior knowledge must be used for cleartext HTTP/2 connections. Upgrade from HTTP/1.1 is not supported."); } if (maxConcurrentStreamsPerConnection <= 0) { throw new IllegalArgumentException("Max Concurrent Streams Per Connection must be greater than zero."); } if (idealConcurrentStreamsPerConnection <= 0 || idealConcurrentStreamsPerConnection > maxConcurrentStreamsPerConnection) { throw new IllegalArgumentException( "Ideal Concurrent Streams Per Connection must be greater than zero and smaller than max."); } } }