@@ -68,6 +68,23 @@ extension HTTPConnectionPool {
68
68
69
69
enum HTTPVersionState {
70
70
case http1( HTTP1StateMachine )
71
+ case http2( HTTP2StateMachine )
72
+
73
+ mutating func modify< ReturnValue> (
74
+ http1: ( inout HTTP1StateMachine ) -> ReturnValue ,
75
+ http2: ( inout HTTP2StateMachine ) -> ReturnValue
76
+ ) -> ReturnValue {
77
+ let returnValue : ReturnValue
78
+ switch self {
79
+ case . http1( var http1State) :
80
+ returnValue = http1 ( & http1State)
81
+ self = . http1( http1State)
82
+ case . http2( var http2State) :
83
+ returnValue = http2 ( & http2State)
84
+ self = . http2( http2State)
85
+ }
86
+ return returnValue
87
+ }
71
88
}
72
89
73
90
var state : HTTPVersionState
@@ -87,12 +104,11 @@ extension HTTPConnectionPool {
87
104
}
88
105
89
106
mutating func executeRequest( _ request: Request ) -> Action {
90
- switch self . state {
91
- case . http1( var http1StateMachine) :
92
- let action = http1StateMachine. executeRequest ( request)
93
- self . state = . http1( http1StateMachine)
94
- return action
95
- }
107
+ self . state. modify ( http1: { http1 in
108
+ http1. executeRequest ( request)
109
+ } , http2: { http2 in
110
+ http2. executeRequest ( request)
111
+ } )
96
112
}
97
113
98
114
mutating func newHTTP1ConnectionCreated( _ connection: Connection ) -> Action {
@@ -101,28 +117,100 @@ extension HTTPConnectionPool {
101
117
let action = http1StateMachine. newHTTP1ConnectionEstablished ( connection)
102
118
self . state = . http1( http1StateMachine)
103
119
return action
120
+
121
+ case . http2( let http2StateMachine) :
122
+ var http1StateMachine = HTTP1StateMachine (
123
+ idGenerator: self . idGenerator,
124
+ maximumConcurrentConnections: self . maximumConcurrentHTTP1Connections
125
+ )
126
+
127
+ let newConnectionAction = http1StateMachine. migrateFromHTTP2 (
128
+ http2State: http2StateMachine,
129
+ newHTTP1Connection: connection
130
+ )
131
+ self . state = . http1( http1StateMachine)
132
+ return newConnectionAction
104
133
}
105
134
}
106
135
107
- mutating func failedToCreateNewConnection ( _ error : Error , connectionID : Connection . ID ) -> Action {
136
+ mutating func newHTTP2ConnectionCreated ( _ connection : Connection , maxConcurrentStreams : Int ) -> Action {
108
137
switch self . state {
109
- case . http1( var http1StateMachine) :
110
- let action = http1StateMachine. failedToCreateNewConnection (
138
+ case . http1( let http1StateMachine) :
139
+
140
+ var http2StateMachine = HTTP2StateMachine (
141
+ idGenerator: self . idGenerator
142
+ )
143
+ let migrationAction = http2StateMachine. migrateFromHTTP1 (
144
+ http1State: http1StateMachine,
145
+ newHTTP2Connection: connection,
146
+ maxConcurrentStreams: maxConcurrentStreams
147
+ )
148
+
149
+ self . state = . http2( http2StateMachine)
150
+ return migrationAction
151
+
152
+ case . http2( var http2StateMachine) :
153
+ let newConnectionAction = http2StateMachine. newHTTP2ConnectionEstablished (
154
+ connection,
155
+ maxConcurrentStreams: maxConcurrentStreams
156
+ )
157
+ self . state = . http2( http2StateMachine)
158
+ return newConnectionAction
159
+ }
160
+ }
161
+
162
+ mutating func newHTTP2MaxConcurrentStreamsReceived( _ connectionID: Connection . ID , newMaxStreams: Int ) -> Action {
163
+ self . state. modify ( http1: { http1 in
164
+ http1. newHTTP2MaxConcurrentStreamsReceived ( connectionID, newMaxStreams: newMaxStreams)
165
+ } , http2: { http2 in
166
+ http2. newHTTP2MaxConcurrentStreamsReceived ( connectionID, newMaxStreams: newMaxStreams)
167
+ } )
168
+ }
169
+
170
+ mutating func http2ConnectionGoAwayReceived( _ connectionID: Connection . ID ) -> Action {
171
+ self . state. modify ( http1: { http1 in
172
+ http1. http2ConnectionGoAwayReceived ( connectionID)
173
+ } , http2: { http2 in
174
+ http2. http2ConnectionGoAwayReceived ( connectionID)
175
+ } )
176
+ }
177
+
178
+ mutating func http2ConnectionClosed( _ connectionID: Connection . ID ) -> Action {
179
+ self . state. modify ( http1: { http1 in
180
+ http1. http2ConnectionClosed ( connectionID)
181
+ } , http2: { http2 in
182
+ http2. http2ConnectionClosed ( connectionID)
183
+ } )
184
+ }
185
+
186
+ mutating func http2ConnectionStreamClosed( _ connectionID: Connection . ID ) -> Action {
187
+ self . state. modify ( http1: { http1 in
188
+ http1. http2ConnectionStreamClosed ( connectionID)
189
+ } , http2: { http2 in
190
+ http2. http2ConnectionStreamClosed ( connectionID)
191
+ } )
192
+ }
193
+
194
+ mutating func failedToCreateNewConnection( _ error: Error , connectionID: Connection . ID ) -> Action {
195
+ self . state. modify ( http1: { http1 in
196
+ http1. failedToCreateNewConnection (
111
197
error,
112
198
connectionID: connectionID
113
199
)
114
- self . state = . http1( http1StateMachine)
115
- return action
116
- }
200
+ } , http2: { http2 in
201
+ http2. failedToCreateNewConnection (
202
+ error,
203
+ connectionID: connectionID
204
+ )
205
+ } )
117
206
}
118
207
119
208
mutating func connectionCreationBackoffDone( _ connectionID: Connection . ID ) -> Action {
120
- switch self . state {
121
- case . http1( var http1StateMachine) :
122
- let action = http1StateMachine. connectionCreationBackoffDone ( connectionID)
123
- self . state = . http1( http1StateMachine)
124
- return action
125
- }
209
+ self . state. modify ( http1: { http1 in
210
+ http1. connectionCreationBackoffDone ( connectionID)
211
+ } , http2: { http2 in
212
+ http2. connectionCreationBackoffDone ( connectionID)
213
+ } )
126
214
}
127
215
128
216
/// A request has timed out.
@@ -131,12 +219,11 @@ extension HTTPConnectionPool {
131
219
/// request, but don't need to cancel the timer (it already triggered). If a request is cancelled
132
220
/// we don't need to fail it but we need to cancel its timeout timer.
133
221
mutating func timeoutRequest( _ requestID: Request . ID ) -> Action {
134
- switch self . state {
135
- case . http1( var http1StateMachine) :
136
- let action = http1StateMachine. timeoutRequest ( requestID)
137
- self . state = . http1( http1StateMachine)
138
- return action
139
- }
222
+ self . state. modify ( http1: { http1 in
223
+ http1. timeoutRequest ( requestID)
224
+ } , http2: { http2 in
225
+ http2. timeoutRequest ( requestID)
226
+ } )
140
227
}
141
228
142
229
/// A request was cancelled.
@@ -145,53 +232,48 @@ extension HTTPConnectionPool {
145
232
/// need to cancel its timeout timer. If a request times out, we need to fail the request, but don't
146
233
/// need to cancel the timer (it already triggered).
147
234
mutating func cancelRequest( _ requestID: Request . ID ) -> Action {
148
- switch self . state {
149
- case . http1( var http1StateMachine) :
150
- let action = http1StateMachine. cancelRequest ( requestID)
151
- self . state = . http1( http1StateMachine)
152
- return action
153
- }
235
+ self . state. modify ( http1: { http1 in
236
+ http1. cancelRequest ( requestID)
237
+ } , http2: { http2 in
238
+ http2. cancelRequest ( requestID)
239
+ } )
154
240
}
155
241
156
242
mutating func connectionIdleTimeout( _ connectionID: Connection . ID ) -> Action {
157
- switch self . state {
158
- case . http1( var http1StateMachine) :
159
- let action = http1StateMachine. connectionIdleTimeout ( connectionID)
160
- self . state = . http1( http1StateMachine)
161
- return action
162
- }
243
+ self . state. modify ( http1: { http1 in
244
+ http1. connectionIdleTimeout ( connectionID)
245
+ } , http2: { http2 in
246
+ http2. connectionIdleTimeout ( connectionID)
247
+ } )
163
248
}
164
249
165
250
/// A connection has been closed
166
251
mutating func http1ConnectionClosed( _ connectionID: Connection . ID ) -> Action {
167
- switch self . state {
168
- case . http1( var http1StateMachine) :
169
- let action = http1StateMachine. http1ConnectionClosed ( connectionID)
170
- self . state = . http1( http1StateMachine)
171
- return action
172
- }
252
+ self . state. modify ( http1: { http1 in
253
+ http1. http1ConnectionClosed ( connectionID)
254
+ } , http2: { http2 in
255
+ http2. http1ConnectionClosed ( connectionID)
256
+ } )
173
257
}
174
258
175
259
mutating func http1ConnectionReleased( _ connectionID: Connection . ID ) -> Action {
176
- switch self . state {
177
- case . http1( var http1StateMachine) :
178
- let action = http1StateMachine. http1ConnectionReleased ( connectionID)
179
- self . state = . http1( http1StateMachine)
180
- return action
181
- }
260
+ self . state. modify ( http1: { http1 in
261
+ http1. http1ConnectionReleased ( connectionID)
262
+ } , http2: { http2 in
263
+ http2. http1ConnectionReleased ( connectionID)
264
+ } )
182
265
}
183
266
184
267
mutating func shutdown( ) -> Action {
185
268
precondition ( !self . isShuttingDown, " Shutdown must only be called once " )
186
269
187
270
self . isShuttingDown = true
188
271
189
- switch self . state {
190
- case . http1( var http1StateMachine) :
191
- let action = http1StateMachine. shutdown ( )
192
- self . state = . http1( http1StateMachine)
193
- return action
194
- }
272
+ return self . state. modify ( http1: { http1 in
273
+ http1. shutdown ( )
274
+ } , http2: { http2 in
275
+ http2. shutdown ( )
276
+ } )
195
277
}
196
278
}
197
279
}
@@ -221,6 +303,8 @@ extension HTTPConnectionPool.StateMachine: CustomStringConvertible {
221
303
switch self . state {
222
304
case . http1( let http1) :
223
305
return " .http1( \( http1) ) "
306
+ case . http2( let http2) :
307
+ return " .http2( \( http2) ) "
224
308
}
225
309
}
226
310
}
0 commit comments