12
12
using Microsoft . AspNetCore . Server . Kestrel . Core . Internal . Http ;
13
13
using Microsoft . AspNetCore . Server . Kestrel . Core . Internal . Http2 . FlowControl ;
14
14
using Microsoft . AspNetCore . Server . Kestrel . Core . Internal . Infrastructure ;
15
+ using Microsoft . AspNetCore . Server . Kestrel . Core . Internal . Infrastructure . PipeWriterHelpers ;
15
16
using Microsoft . Extensions . Logging ;
16
17
17
18
namespace Microsoft . AspNetCore . Server . Kestrel . Core . Internal . Http2
@@ -29,7 +30,8 @@ internal class Http2OutputProducer : IHttpOutputProducer, IHttpOutputAborter
29
30
private readonly MemoryPool < byte > _memoryPool ;
30
31
private readonly Http2Stream _stream ;
31
32
private readonly object _dataWriterLock = new object ( ) ;
32
- private readonly Pipe _dataPipe ;
33
+ private readonly PipeWriter _pipeWriter ;
34
+ private readonly PipeReader _pipeReader ;
33
35
private readonly ValueTask < FlushResult > _dataWriteProcessingTask ;
34
36
private bool _startedWritingDataFrames ;
35
37
private bool _completed ;
@@ -43,7 +45,6 @@ public Http2OutputProducer(
43
45
int streamId ,
44
46
Http2FrameWriter frameWriter ,
45
47
StreamOutputFlowControl flowControl ,
46
- ITimeoutControl timeoutControl ,
47
48
MemoryPool < byte > pool ,
48
49
Http2Stream stream ,
49
50
IKestrelTrace log )
@@ -55,8 +56,14 @@ public Http2OutputProducer(
55
56
_stream = stream ;
56
57
_log = log ;
57
58
58
- _dataPipe = CreateDataPipe ( pool ) ;
59
- _flusher = new TimingPipeFlusher ( _dataPipe . Writer , timeoutControl , log ) ;
59
+ var pipe = CreateDataPipe ( pool ) ;
60
+
61
+ _pipeWriter = new ConcurrentPipeWriter ( pipe . Writer , pool ) ;
62
+ _pipeReader = pipe . Reader ;
63
+
64
+ // No need to pass in timeoutControl here, since no minDataRates are passed to the TimingPipeFlusher.
65
+ // The minimum output data rate is enforced at the connection level by Http2FrameWriter.
66
+ _flusher = new TimingPipeFlusher ( _pipeWriter , timeoutControl : null , log ) ;
60
67
_dataWriteProcessingTask = ProcessDataWrites ( ) ;
61
68
}
62
69
@@ -193,7 +200,7 @@ public Task WriteDataAsync(ReadOnlySpan<byte> data, CancellationToken cancellati
193
200
194
201
_startedWritingDataFrames = true ;
195
202
196
- _dataPipe . Writer . Write ( data ) ;
203
+ _pipeWriter . Write ( data ) ;
197
204
return _flusher . FlushAsync ( this , cancellationToken ) . GetAsTask ( ) ;
198
205
}
199
206
}
@@ -210,7 +217,7 @@ public ValueTask<FlushResult> WriteStreamSuffixAsync()
210
217
_completed = true ;
211
218
_suffixSent = true ;
212
219
213
- _dataPipe . Writer . Complete ( ) ;
220
+ _pipeWriter . Complete ( ) ;
214
221
return _dataWriteProcessingTask ;
215
222
}
216
223
}
@@ -239,7 +246,7 @@ public void Advance(int bytes)
239
246
240
247
_startedWritingDataFrames = true ;
241
248
242
- _dataPipe . Writer . Advance ( bytes ) ;
249
+ _pipeWriter . Advance ( bytes ) ;
243
250
}
244
251
}
245
252
@@ -254,7 +261,7 @@ public Span<byte> GetSpan(int sizeHint = 0)
254
261
return GetFakeMemory ( sizeHint ) . Span ;
255
262
}
256
263
257
- return _dataPipe . Writer . GetSpan ( sizeHint ) ;
264
+ return _pipeWriter . GetSpan ( sizeHint ) ;
258
265
}
259
266
}
260
267
@@ -269,7 +276,7 @@ public Memory<byte> GetMemory(int sizeHint = 0)
269
276
return GetFakeMemory ( sizeHint ) ;
270
277
}
271
278
272
- return _dataPipe . Writer . GetMemory ( sizeHint ) ;
279
+ return _pipeWriter . GetMemory ( sizeHint ) ;
273
280
}
274
281
}
275
282
@@ -282,7 +289,7 @@ public void CancelPendingFlush()
282
289
return ;
283
290
}
284
291
285
- _dataPipe . Writer . CancelPendingFlush ( ) ;
292
+ _pipeWriter . CancelPendingFlush ( ) ;
286
293
}
287
294
}
288
295
@@ -306,7 +313,7 @@ public ValueTask<FlushResult> WriteDataToPipeAsync(ReadOnlySpan<byte> data, Canc
306
313
307
314
_startedWritingDataFrames = true ;
308
315
309
- _dataPipe . Writer . Write ( data ) ;
316
+ _pipeWriter . Write ( data ) ;
310
317
return _flusher . FlushAsync ( this , cancellationToken ) ;
311
318
}
312
319
}
@@ -345,7 +352,7 @@ public void Stop()
345
352
// Complete with an exception to prevent an end of stream data frame from being sent without an
346
353
// explicit call to WriteStreamSuffixAsync. ConnectionAbortedExceptions are swallowed, so the
347
354
// message doesn't matter
348
- _dataPipe . Writer . Complete ( new OperationCanceledException ( ) ) ;
355
+ _pipeWriter . Complete ( new OperationCanceledException ( ) ) ;
349
356
350
357
_frameWriter . AbortPendingStreamDataWrites ( _flowControl ) ;
351
358
}
@@ -364,7 +371,7 @@ private async ValueTask<FlushResult> ProcessDataWrites()
364
371
365
372
do
366
373
{
367
- readResult = await _dataPipe . Reader . ReadAsync ( ) ;
374
+ readResult = await _pipeReader . ReadAsync ( ) ;
368
375
369
376
if ( readResult . IsCompleted && _stream . ResponseTrailers ? . Count > 0 )
370
377
{
@@ -393,7 +400,7 @@ private async ValueTask<FlushResult> ProcessDataWrites()
393
400
flushResult = await _frameWriter . WriteDataAsync ( _streamId , _flowControl , readResult . Buffer , endStream : readResult . IsCompleted ) ;
394
401
}
395
402
396
- _dataPipe . Reader . AdvanceTo ( readResult . Buffer . End ) ;
403
+ _pipeReader . AdvanceTo ( readResult . Buffer . End ) ;
397
404
} while ( ! readResult . IsCompleted ) ;
398
405
}
399
406
catch ( OperationCanceledException )
@@ -405,7 +412,7 @@ private async ValueTask<FlushResult> ProcessDataWrites()
405
412
_log . LogCritical ( ex , nameof ( Http2OutputProducer ) + "." + nameof ( ProcessDataWrites ) + " observed an unexpected exception." ) ;
406
413
}
407
414
408
- _dataPipe . Reader . Complete ( ) ;
415
+ _pipeReader . Complete ( ) ;
409
416
410
417
return flushResult ;
411
418
0 commit comments