@@ -27,9 +27,20 @@ import Logging
2727/// The connection is initially setup with a handler to verify that TLS was established
2828/// successfully (assuming TLS is being used).
2929///
30- /// ▲ |
31- /// HTTP2Frame│ │HTTP2Frame
32- /// ┌─┴───────────────────────▼─┐
30+ /// ┌──────────────────────────┐
31+ /// │ DelegatingErrorHandler │
32+ /// └──────────▲───────────────┘
33+ /// HTTP2Frame│
34+ /// ┌──────────┴───────────────┐
35+ /// │ SettingsObservingHandler │
36+ /// └──────────▲───────────────┘
37+ /// HTTP2Frame│
38+ /// │ ⠇ ⠇ ⠇ ⠇
39+ /// │ ┌┴─▼┐ ┌┴─▼┐
40+ /// │ │ | │ | HTTP/2 streams
41+ /// │ └▲─┬┘ └▲─┬┘
42+ /// │ │ │ │ │ HTTP2Frame
43+ /// ┌─┴────── ─────────┴─▼───┴─▼┐
3344/// │ HTTP2StreamMultiplexer |
3445/// └─▲───────────────────────┬─┘
3546/// HTTP2Frame│ │HTTP2Frame
@@ -49,11 +60,13 @@ import Logging
4960///
5061/// The `TLSVerificationHandler` observes the outcome of the SSL handshake and determines
5162/// whether a `ClientConnection` should be returned to the user. In either eventuality, the
52- /// handler removes itself from the pipeline once TLS has been verified. There is also a delegated
53- /// error handler after the `HTTPStreamMultiplexer` in the main channel which uses the error
54- /// delegate associated with this connection (see `DelegatingErrorHandler`).
63+ /// handler removes itself from the pipeline once TLS has been verified. There is also a handler
64+ /// after the multiplexer for observing the initial settings frame, after which it determines that
65+ /// the connection state is `.ready` and removes itself from the channel. Finally there is a
66+ /// delegated error handler which uses the error delegate associated with this connection
67+ /// (see `DelegatingErrorHandler`).
5568///
56- /// See `BaseClientCall` for a description of the remainder of the client pipeline .
69+ /// See `BaseClientCall` for a description of the pipelines assoicated with each HTTP/2 stream .
5770public class ClientConnection {
5871 internal let logger : Logger
5972 /// The UUID of this connection, used for logging.
@@ -144,6 +157,7 @@ public class ClientConnection {
144157 channel,
145158 tls: configuration. tls? . configuration,
146159 serverHostname: configuration. tls? . hostnameOverride ?? configuration. target. host,
160+ connectivityMonitor: self . connectivity,
147161 errorDelegate: configuration. errorDelegate
148162 ) . flatMap {
149163 channel. connect ( to: socketAddress)
@@ -224,14 +238,8 @@ extension ClientConnection {
224238 ///
225239 /// - Parameter channel: The channel that was set.
226240 private func didSetChannel( to channel: EventLoopFuture < Channel > ) {
227- channel. whenComplete { result in
228- switch result {
229- case . success:
230- self . connectivity. state = . ready
231-
232- case . failure:
233- self . connectivity. state = . shutdown
234- }
241+ channel. whenFailure { _ in
242+ self . connectivity. state = . shutdown
235243 }
236244 }
237245
@@ -260,6 +268,7 @@ extension ClientConnection {
260268 configuration: configuration,
261269 group: configuration. eventLoopGroup,
262270 timeout: timeoutAndBackoff? . timeout,
271+ connectivityMonitor: connectivity,
263272 logger: logger
264273 )
265274
@@ -327,10 +336,12 @@ extension ClientConnection {
327336 /// - Parameter configuration: The configuration to prepare the bootstrap with.
328337 /// - Parameter group: The `EventLoopGroup` to use for the bootstrap.
329338 /// - Parameter timeout: The connection timeout in seconds.
339+ /// - Parameter connectivityMonitor: The connectivity state monitor for the created channel.
330340 private class func makeBootstrap(
331341 configuration: Configuration ,
332342 group: EventLoopGroup ,
333343 timeout: TimeInterval ? ,
344+ connectivityMonitor: ConnectivityStateMonitor ,
334345 logger: Logger
335346 ) -> ClientBootstrapProtocol {
336347 // Provide a server hostname if we're using TLS. Prefer the override.
@@ -354,6 +365,7 @@ extension ClientConnection {
354365 channel,
355366 tls: configuration. tls? . configuration,
356367 serverHostname: serverHostname,
368+ connectivityMonitor: connectivityMonitor,
357369 errorDelegate: configuration. errorDelegate
358370 )
359371 }
@@ -376,6 +388,7 @@ extension ClientConnection {
376388 _ channel: Channel ,
377389 tls: TLSConfiguration ? ,
378390 serverHostname: String ? ,
391+ connectivityMonitor: ConnectivityStateMonitor ,
379392 errorDelegate: ClientErrorDelegate ?
380393 ) -> EventLoopFuture < Void > {
381394 let tlsConfigured = tls. map {
@@ -385,8 +398,9 @@ extension ClientConnection {
385398 return ( tlsConfigured ?? channel. eventLoop. makeSucceededFuture ( ( ) ) ) . flatMap {
386399 channel. configureHTTP2Pipeline ( mode: . client)
387400 } . flatMap { _ in
401+ let settingsObserver = InitialSettingsObservingHandler ( connectivityStateMonitor: connectivityMonitor)
388402 let errorHandler = DelegatingErrorHandler ( delegate: errorDelegate)
389- return channel. pipeline. addHandler ( errorHandler)
403+ return channel. pipeline. addHandlers ( settingsObserver , errorHandler)
390404 }
391405 }
392406}
0 commit comments