1 package software.amazon.awssdk.crt.http; 2 3 import java.util.List; 4 import java.util.ArrayList; 5 6 /** 7 * Contains all the configuration options for a Http2StreamManager 8 * instance 9 */ 10 public class Http2StreamManagerOptions { 11 public static final int DEFAULT_MAX_WINDOW_SIZE = Integer.MAX_VALUE; 12 public static final int DEFAULT_MAX = Integer.MAX_VALUE; 13 public static final int DEFAULT_MAX_CONNECTIONS = 2; 14 public static final int DEFAULT_CONNECTION_PING_TIMEOUT_MS = 3000; 15 16 private HttpClientConnectionManagerOptions connectionManagerOptions; 17 18 private int idealConcurrentStreamsPerConnection = 100; 19 private boolean connectionManualWindowManagement = false; 20 private int maxConcurrentStreamsPerConnection = DEFAULT_MAX; 21 22 private boolean priorKnowledge = false; 23 private boolean closeConnectionOnServerError = false; 24 private int connectionPingPeriodMs = 0; 25 private int connectionPingTimeoutMs = 0; 26 27 private List<Http2ConnectionSetting> initialSettingsList = new ArrayList<Http2ConnectionSetting>(); 28 29 /** 30 * Default constructor 31 */ Http2StreamManagerOptions()32 public Http2StreamManagerOptions() { 33 } 34 35 /** 36 * For HTTP/2 stream manager only. 37 * 38 * The initial settings for the HTTP/2 connections made by stream manger. 39 * `Http2ConnectionSettingListBuilder` can help to build the settings list. 40 * 41 * To control the initial stream-level flow-control window, set the 42 * INITIAL_WINDOW_SIZE setting in the initial settings. 43 * 44 * @param initialSettingsList The List of initial settings 45 * @return this 46 */ withInitialSettingsList(List<Http2ConnectionSetting> initialSettingsList)47 public Http2StreamManagerOptions withInitialSettingsList(List<Http2ConnectionSetting> initialSettingsList) { 48 this.initialSettingsList.addAll(initialSettingsList); 49 return this; 50 } 51 52 /** 53 * @return The List of initial settings 54 */ getInitialSettingsList()55 public List<Http2ConnectionSetting> getInitialSettingsList() { 56 return this.initialSettingsList; 57 } 58 59 /** 60 * For HTTP/2 stream manager only. 61 * 62 * The ideal number of concurrent streams for a connection. Stream manager will 63 * try to create a new connection if one connection reaches this number. But, if 64 * the max connections reaches, manager will reuse connections to create the 65 * acquired steams as much as possible. 66 * 67 * @param idealConcurrentStreamsPerConnection The ideal number of concurrent 68 * streams for a connection 69 * @return this 70 */ withIdealConcurrentStreamsPerConnection(int idealConcurrentStreamsPerConnection)71 public Http2StreamManagerOptions withIdealConcurrentStreamsPerConnection(int idealConcurrentStreamsPerConnection) { 72 this.idealConcurrentStreamsPerConnection = idealConcurrentStreamsPerConnection; 73 return this; 74 } 75 76 /** 77 * @return The ideal number of concurrent streams for a connection used for 78 * manager 79 */ getIdealConcurrentStreamsPerConnection()80 public int getIdealConcurrentStreamsPerConnection() { 81 return idealConcurrentStreamsPerConnection; 82 } 83 84 /** 85 * Default is no limit, which will use the limit from the server. 0 will be 86 * considered as using the default value. 87 * The real number of concurrent streams per connection will be controlled by 88 * the minimal value of the setting from other end and the value here. 89 * 90 * @param maxConcurrentStreamsPerConnection The max number of concurrent 91 * streams for a connection 92 * @return this 93 */ withMaxConcurrentStreamsPerConnection(int maxConcurrentStreamsPerConnection)94 public Http2StreamManagerOptions withMaxConcurrentStreamsPerConnection(int maxConcurrentStreamsPerConnection) { 95 this.maxConcurrentStreamsPerConnection = maxConcurrentStreamsPerConnection; 96 return this; 97 } 98 99 /** 100 * @return The max number of concurrent streams for a connection set for 101 * manager. 102 * It could be different than the real limits, which is the minimal set 103 * for manager and the settings from the other side. 104 */ getMaxConcurrentStreamsPerConnection()105 public int getMaxConcurrentStreamsPerConnection() { 106 return maxConcurrentStreamsPerConnection; 107 } 108 109 /** 110 * @return The connection level manual flow control enabled or not. 111 */ isConnectionManualWindowManagement()112 public boolean isConnectionManualWindowManagement() { 113 return connectionManualWindowManagement; 114 } 115 116 /** 117 * Set to true to manually manage the flow-control window of whole HTTP/2 118 * connection. 119 * The stream level flow-control window is controlled by the 120 * manualWindowManagement in connectionManagerOptions. 121 * 122 * @param connectionManualWindowManagement Enable connection level manual flow 123 * control or not. 124 * @return this 125 */ withConnectionManualWindowManagement(boolean connectionManualWindowManagement)126 public Http2StreamManagerOptions withConnectionManualWindowManagement(boolean connectionManualWindowManagement) { 127 this.connectionManualWindowManagement = connectionManualWindowManagement; 128 return this; 129 } 130 131 /** 132 * @return The connection manager options for the underlying connection manager. 133 */ getConnectionManagerOptions()134 public HttpClientConnectionManagerOptions getConnectionManagerOptions() { 135 return connectionManagerOptions; 136 } 137 138 /** 139 * Required. 140 * 141 * The configuration options for the connection manager under the hood. 142 * It controls the connection specific thing for the stream manager. See 143 * `HttpClientConnectionManagerOptions` for details. 144 * 145 * Note: 146 * 1. the windowSize of connection manager will be ignored, as the initial 147 * flow-control window size for HTTP/2 stream 148 * is controlled by the initial settings. 149 * 2. The expectedHttpVersion will also be ignored. 150 * 151 * @param connectionManagerOptions The connection manager options for the 152 * underlying connection manager 153 * @return this 154 */ withConnectionManagerOptions( HttpClientConnectionManagerOptions connectionManagerOptions)155 public Http2StreamManagerOptions withConnectionManagerOptions( 156 HttpClientConnectionManagerOptions connectionManagerOptions) { 157 this.connectionManagerOptions = connectionManagerOptions; 158 return this; 159 } 160 161 /** 162 * @return Prior knowledge is used or not 163 */ hasPriorKnowledge()164 public boolean hasPriorKnowledge() { 165 return priorKnowledge; 166 } 167 168 /** 169 * Set to true to use prior knowledge to setup connection. 170 * If any TLS was set, exception will be raised if prior knowledge is set during 171 * validation. 172 * If NO TLS was set, exception will be raised if prior knowledge is NOT set 173 * during validation. 174 * 175 * @param priorKnowledge Prior knowledge used or not. 176 * @return this 177 */ withPriorKnowledge(boolean priorKnowledge)178 public Http2StreamManagerOptions withPriorKnowledge(boolean priorKnowledge) { 179 this.priorKnowledge = priorKnowledge; 180 return this; 181 } 182 183 /** 184 * @return Connection closed or not when server error happened (500/502/503/504 185 * response status code received). 186 */ shouldCloseConnectionOnServerError()187 public boolean shouldCloseConnectionOnServerError() { 188 return closeConnectionOnServerError; 189 } 190 191 /** 192 * Set to true to inform stream manager to close connection when response with 193 * 500/502/503/504 received. 194 * Stream manager will stop using the connection with server error will start a 195 * new connection for other streams. 196 * 197 * @param closeConnectionOnServerError Connection closed or not when server 198 * error happened. 199 * @return this 200 */ withCloseConnectionOnServerError(boolean closeConnectionOnServerError)201 public Http2StreamManagerOptions withCloseConnectionOnServerError(boolean closeConnectionOnServerError) { 202 this.closeConnectionOnServerError = closeConnectionOnServerError; 203 return this; 204 } 205 206 /** 207 * Settings to control the period ping to be sent for connections held by stream 208 * manager. 209 * 210 * @param periodMs The period for all the connections held by stream manager to 211 * send a PING in milliseconds. If you specify 0, manager will 212 * NOT send any PING. 213 * @param timeoutMs Network connection will be closed if a ping response is not 214 * received within this amount of time (milliseconds). If you 215 * specify 0, a default value will be used. If this is larger 216 * than periodMs, it will be capped to be equal. 217 * @return this 218 */ withConnectionPing(int periodMs, int timeoutMs)219 public Http2StreamManagerOptions withConnectionPing(int periodMs, int timeoutMs) { 220 this.connectionPingPeriodMs = periodMs; 221 this.connectionPingTimeoutMs = timeoutMs == 0 ? DEFAULT_CONNECTION_PING_TIMEOUT_MS 222 : timeoutMs; 223 this.connectionPingTimeoutMs = Math.min(this.connectionPingPeriodMs, this.connectionPingTimeoutMs); 224 return this; 225 } 226 227 /** 228 * @return The period for all the connections held by stream manager to send a 229 * PING in milliseconds. 230 */ getConnectionPingPeriodMs()231 public int getConnectionPingPeriodMs() { 232 return connectionPingPeriodMs; 233 } 234 235 /** 236 * @return The time for closing connection if ping not received within this 237 * amount of time in milliseconds 238 */ getConnectionPingTimeoutMs()239 public int getConnectionPingTimeoutMs() { 240 return connectionPingTimeoutMs; 241 } 242 243 /** 244 * Validate the stream manager options are valid to use. Throw exceptions if 245 * not. 246 */ validateOptions()247 public void validateOptions() { 248 if (connectionManagerOptions == null) { 249 throw new IllegalArgumentException("Connection manager options are required."); 250 } 251 connectionManagerOptions.validateOptions(); 252 if ((connectionManagerOptions.getTlsConnectionOptions() != null 253 || connectionManagerOptions.getTlsContext() != null) && priorKnowledge) { 254 throw new IllegalArgumentException("HTTP/2 prior knowledge cannot be set when TLS is used."); 255 } 256 if ((connectionManagerOptions.getTlsConnectionOptions() == null 257 && connectionManagerOptions.getTlsContext() == null) && !priorKnowledge) { 258 throw new IllegalArgumentException( 259 "Prior knowledge must be used for cleartext HTTP/2 connections. Upgrade from HTTP/1.1 is not supported."); 260 } 261 if (maxConcurrentStreamsPerConnection <= 0) { 262 throw new IllegalArgumentException("Max Concurrent Streams Per Connection must be greater than zero."); 263 } 264 if (idealConcurrentStreamsPerConnection <= 0 265 || idealConcurrentStreamsPerConnection > maxConcurrentStreamsPerConnection) { 266 throw new IllegalArgumentException( 267 "Ideal Concurrent Streams Per Connection must be greater than zero and smaller than max."); 268 } 269 } 270 } 271