@@ -28,30 +28,46 @@ struct HTTP1ConnectionStateMachine {
2828
2929 enum Action {
3030 /// A action to execute, when we consider a request "done".
31- enum FinalStreamAction {
31+ enum FinalSuccessfulStreamAction {
3232 /// Close the connection
3333 case close
3434 /// If the server has replied, with a status of 200...300 before all data was sent, a request is considered succeeded,
3535 /// as soon as we wrote the request end onto the wire.
36- case sendRequestEnd
36+ ///
37+ /// The promise is an optional write promise.
38+ case sendRequestEnd( EventLoopPromise < Void > ? )
3739 /// Inform an observer that the connection has become idle
3840 case informConnectionIsIdle
41+ }
42+
43+ /// A action to execute, when we consider a request "done".
44+ enum FinalFailedStreamAction {
45+ /// Close the connection
46+ ///
47+ /// The promise is an optional write promise.
48+ case close( EventLoopPromise < Void > ? )
49+ /// Inform an observer that the connection has become idle
50+ case informConnectionIsIdle
51+ /// Fail the write promise
52+ case failWritePromise( EventLoopPromise < Void > ? )
3953 /// Do nothing.
4054 case none
4155 }
4256
4357 case sendRequestHead( HTTPRequestHead , startBody: Bool )
44- case sendBodyPart( IOData )
45- case sendRequestEnd
58+ case sendBodyPart( IOData , EventLoopPromise < Void > ? )
59+ case sendRequestEnd( EventLoopPromise < Void > ? )
60+ case failSendBodyPart( Error , EventLoopPromise < Void > ? )
61+ case failSendStreamFinished( Error , EventLoopPromise < Void > ? )
4662
4763 case pauseRequestBodyStream
4864 case resumeRequestBodyStream
4965
5066 case forwardResponseHead( HTTPResponseHead , pauseRequestBodyStream: Bool )
5167 case forwardResponseBodyParts( CircularBuffer < ByteBuffer > )
5268
53- case failRequest( Error , FinalStreamAction )
54- case succeedRequest( FinalStreamAction , CircularBuffer < ByteBuffer > )
69+ case failRequest( Error , FinalFailedStreamAction )
70+ case succeedRequest( FinalSuccessfulStreamAction , CircularBuffer < ByteBuffer > )
5571
5672 case read
5773 case close
@@ -189,25 +205,25 @@ struct HTTP1ConnectionStateMachine {
189205 }
190206 }
191207
192- mutating func requestStreamPartReceived( _ part: IOData ) -> Action {
208+ mutating func requestStreamPartReceived( _ part: IOData , promise : EventLoopPromise < Void > ? ) -> Action {
193209 guard case . inRequest( var requestStateMachine, let close) = self . state else {
194210 preconditionFailure ( " Invalid state: \( self . state) " )
195211 }
196212
197213 return self . avoidingStateMachineCoW { state -> Action in
198- let action = requestStateMachine. requestStreamPartReceived ( part)
214+ let action = requestStateMachine. requestStreamPartReceived ( part, promise : promise )
199215 state = . inRequest( requestStateMachine, close: close)
200216 return state. modify ( with: action)
201217 }
202218 }
203219
204- mutating func requestStreamFinished( ) -> Action {
220+ mutating func requestStreamFinished( promise : EventLoopPromise < Void > ? ) -> Action {
205221 guard case . inRequest( var requestStateMachine, let close) = self . state else {
206222 preconditionFailure ( " Invalid state: \( self . state) " )
207223 }
208224
209225 return self . avoidingStateMachineCoW { state -> Action in
210- let action = requestStateMachine. requestStreamFinished ( )
226+ let action = requestStateMachine. requestStreamFinished ( promise : promise )
211227 state = . inRequest( requestStateMachine, close: close)
212228 return state. modify ( with: action)
213229 }
@@ -377,10 +393,10 @@ extension HTTP1ConnectionStateMachine.State {
377393 return . pauseRequestBodyStream
378394 case . resumeRequestBodyStream:
379395 return . resumeRequestBodyStream
380- case . sendBodyPart( let part) :
381- return . sendBodyPart( part)
382- case . sendRequestEnd:
383- return . sendRequestEnd
396+ case . sendBodyPart( let part, let writePromise ) :
397+ return . sendBodyPart( part, writePromise )
398+ case . sendRequestEnd( let writePromise ) :
399+ return . sendRequestEnd( writePromise )
384400 case . forwardResponseHead( let head, let pauseRequestBodyStream) :
385401 return . forwardResponseHead( head, pauseRequestBodyStream: pauseRequestBodyStream)
386402 case . forwardResponseBodyParts( let parts) :
@@ -390,13 +406,13 @@ extension HTTP1ConnectionStateMachine.State {
390406 preconditionFailure ( " Invalid state: \( self ) " )
391407 }
392408
393- let newFinalAction : HTTP1ConnectionStateMachine . Action . FinalStreamAction
409+ let newFinalAction : HTTP1ConnectionStateMachine . Action . FinalSuccessfulStreamAction
394410 switch finalAction {
395411 case . close:
396412 self = . closing
397413 newFinalAction = . close
398- case . sendRequestEnd:
399- newFinalAction = . sendRequestEnd
414+ case . sendRequestEnd( let writePromise ) :
415+ newFinalAction = . sendRequestEnd( writePromise )
400416 case . none:
401417 self = . idle
402418 newFinalAction = close ? . close : . informConnectionIsIdle
@@ -410,9 +426,12 @@ extension HTTP1ConnectionStateMachine.State {
410426 case . idle:
411427 preconditionFailure ( " How can we fail a task, if we are idle " )
412428 case . inRequest( _, close: let close) :
413- if close || finalAction == . close {
429+ if case . close( let promise) = finalAction {
430+ self = . closing
431+ return . failRequest( error, . close( promise) )
432+ } else if close {
414433 self = . closing
415- return . failRequest( error, . close)
434+ return . failRequest( error, . close( nil ) )
416435 } else {
417436 self = . idle
418437 return . failRequest( error, . informConnectionIsIdle)
@@ -433,6 +452,12 @@ extension HTTP1ConnectionStateMachine.State {
433452
434453 case . wait:
435454 return . wait
455+
456+ case . failSendBodyPart( let error, let writePromise) :
457+ return . failSendBodyPart( error, writePromise)
458+
459+ case . failSendStreamFinished( let error, let writePromise) :
460+ return . failSendStreamFinished( error, writePromise)
436461 }
437462 }
438463}
0 commit comments