@@ -158,17 +158,35 @@ struct HTTP1ConnectionStateMachine {
158158 head: HTTPRequestHead ,
159159 metadata: RequestFramingMetadata
160160 ) -> Action {
161- guard case . idle = self . state else {
161+ switch self . state {
162+ case . initialized, . closing, . inRequest:
163+ // These states are unreachable as the connection pool state machine has put the
164+ // connection into these states. In other words the connection pool state machine must
165+ // be aware about these states before the connection itself. For this reason the
166+ // connection pool state machine must not send a new request to the connection, if the
167+ // connection is `.initialized`, `.closing` or `.inRequest`
162168 preconditionFailure ( " Invalid state: \( self . state) " )
163- }
164169
165- var requestStateMachine = HTTPRequestStateMachine ( isChannelWritable: self . isChannelWritable)
166- let action = requestStateMachine. startRequest ( head: head, metadata: metadata)
170+ case . closed:
171+ // The remote may have closed the connection and the connection pool state machine
172+ // was not updated yet because of a race condition. New request vs. marking connection
173+ // as closed.
174+ //
175+ // TODO: AHC should support a fast rescheduling mechanism here.
176+ return . failRequest( HTTPClientError . remoteConnectionClosed, . none)
177+
178+ case . idle:
179+ var requestStateMachine = HTTPRequestStateMachine ( isChannelWritable: self . isChannelWritable)
180+ let action = requestStateMachine. startRequest ( head: head, metadata: metadata)
167181
168- // by default we assume a persistent connection. however in `requestVerified`, we read the
169- // "connection" header.
170- self . state = . inRequest( requestStateMachine, close: metadata. connectionClose)
171- return self . state. modify ( with: action)
182+ // by default we assume a persistent connection. however in `requestVerified`, we read the
183+ // "connection" header.
184+ self . state = . inRequest( requestStateMachine, close: metadata. connectionClose)
185+ return self . state. modify ( with: action)
186+
187+ case . modifying:
188+ preconditionFailure ( " Invalid state: \( self . state) " )
189+ }
172190 }
173191
174192 mutating func requestStreamPartReceived( _ part: IOData ) -> Action {
0 commit comments