@@ -28,30 +28,46 @@ struct HTTP1ConnectionStateMachine {
28
28
29
29
enum Action {
30
30
/// A action to execute, when we consider a request "done".
31
- enum FinalStreamAction {
31
+ enum FinalSuccessfulStreamAction {
32
32
/// Close the connection
33
33
case close
34
34
/// If the server has replied, with a status of 200...300 before all data was sent, a request is considered succeeded,
35
35
/// 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 > ? )
37
39
/// Inform an observer that the connection has become idle
38
40
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 > ? )
39
53
/// Do nothing.
40
54
case none
41
55
}
42
56
43
57
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 > ? )
46
62
47
63
case pauseRequestBodyStream
48
64
case resumeRequestBodyStream
49
65
50
66
case forwardResponseHead( HTTPResponseHead , pauseRequestBodyStream: Bool )
51
67
case forwardResponseBodyParts( CircularBuffer < ByteBuffer > )
52
68
53
- case failRequest( Error , FinalStreamAction )
54
- case succeedRequest( FinalStreamAction , CircularBuffer < ByteBuffer > )
69
+ case failRequest( Error , FinalFailedStreamAction )
70
+ case succeedRequest( FinalSuccessfulStreamAction , CircularBuffer < ByteBuffer > )
55
71
56
72
case read
57
73
case close
@@ -189,25 +205,25 @@ struct HTTP1ConnectionStateMachine {
189
205
}
190
206
}
191
207
192
- mutating func requestStreamPartReceived( _ part: IOData ) -> Action {
208
+ mutating func requestStreamPartReceived( _ part: IOData , promise : EventLoopPromise < Void > ? ) -> Action {
193
209
guard case . inRequest( var requestStateMachine, let close) = self . state else {
194
210
preconditionFailure ( " Invalid state: \( self . state) " )
195
211
}
196
212
197
213
return self . avoidingStateMachineCoW { state -> Action in
198
- let action = requestStateMachine. requestStreamPartReceived ( part)
214
+ let action = requestStateMachine. requestStreamPartReceived ( part, promise : promise )
199
215
state = . inRequest( requestStateMachine, close: close)
200
216
return state. modify ( with: action)
201
217
}
202
218
}
203
219
204
- mutating func requestStreamFinished( ) -> Action {
220
+ mutating func requestStreamFinished( promise : EventLoopPromise < Void > ? ) -> Action {
205
221
guard case . inRequest( var requestStateMachine, let close) = self . state else {
206
222
preconditionFailure ( " Invalid state: \( self . state) " )
207
223
}
208
224
209
225
return self . avoidingStateMachineCoW { state -> Action in
210
- let action = requestStateMachine. requestStreamFinished ( )
226
+ let action = requestStateMachine. requestStreamFinished ( promise : promise )
211
227
state = . inRequest( requestStateMachine, close: close)
212
228
return state. modify ( with: action)
213
229
}
@@ -377,10 +393,10 @@ extension HTTP1ConnectionStateMachine.State {
377
393
return . pauseRequestBodyStream
378
394
case . resumeRequestBodyStream:
379
395
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 )
384
400
case . forwardResponseHead( let head, let pauseRequestBodyStream) :
385
401
return . forwardResponseHead( head, pauseRequestBodyStream: pauseRequestBodyStream)
386
402
case . forwardResponseBodyParts( let parts) :
@@ -390,13 +406,13 @@ extension HTTP1ConnectionStateMachine.State {
390
406
preconditionFailure ( " Invalid state: \( self ) " )
391
407
}
392
408
393
- let newFinalAction : HTTP1ConnectionStateMachine . Action . FinalStreamAction
409
+ let newFinalAction : HTTP1ConnectionStateMachine . Action . FinalSuccessfulStreamAction
394
410
switch finalAction {
395
411
case . close:
396
412
self = . closing
397
413
newFinalAction = . close
398
- case . sendRequestEnd:
399
- newFinalAction = . sendRequestEnd
414
+ case . sendRequestEnd( let writePromise ) :
415
+ newFinalAction = . sendRequestEnd( writePromise )
400
416
case . none:
401
417
self = . idle
402
418
newFinalAction = close ? . close : . informConnectionIsIdle
@@ -410,9 +426,12 @@ extension HTTP1ConnectionStateMachine.State {
410
426
case . idle:
411
427
preconditionFailure ( " How can we fail a task, if we are idle " )
412
428
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 {
414
433
self = . closing
415
- return . failRequest( error, . close)
434
+ return . failRequest( error, . close( nil ) )
416
435
} else {
417
436
self = . idle
418
437
return . failRequest( error, . informConnectionIsIdle)
@@ -433,6 +452,12 @@ extension HTTP1ConnectionStateMachine.State {
433
452
434
453
case . wait:
435
454
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)
436
461
}
437
462
}
438
463
}
0 commit comments