@@ -18,7 +18,9 @@ internal sealed partial class Http3Stream
1818 private enum StreamReadingStatus
1919 {
2020 ReadingFrameHeader ,
21- ReadingPayload ,
21+ ReadingPayloadHeader ,
22+ ReadingPayloadData ,
23+ ReadingPayloadReserved ,
2224 }
2325
2426 private QuicStream ? _quicStream ;
@@ -96,7 +98,6 @@ public async void ProcessStream<TContext>(IHttpApplication<TContext> application
9698 public async Task ProcessStreamAsync < TContext > ( IHttpApplication < TContext > application , CancellationToken token )
9799 where TContext : notnull
98100 {
99- ulong frameType = 0 ;
100101 long payloadRemainingLength = 0 ;
101102 Task ? applicationProcessing = null ;
102103 var streamReadingState = StreamReadingStatus . ReadingFrameHeader ;
@@ -112,7 +113,7 @@ public async Task ProcessStreamAsync<TContext>(IHttpApplication<TContext> applic
112113
113114 while ( ! buffer . IsEmpty )
114115 {
115- long bufferConsumed = ProcessStreamAsync ( application , ref frameType , ref payloadRemainingLength , ref applicationProcessing , ref streamReadingState , buffer , token ) ;
116+ long bufferConsumed = ProcessStreamAsync ( application , ref payloadRemainingLength , ref applicationProcessing , ref streamReadingState , buffer , token ) ;
116117
117118 // Could not further process. Break the inner loop to read more data
118119 if ( bufferConsumed == 0 )
@@ -130,6 +131,11 @@ public async Task ProcessStreamAsync<TContext>(IHttpApplication<TContext> applic
130131 {
131132 // Ignore
132133 }
134+ catch ( Http3ConnectionException connectionError )
135+ {
136+ _connection ? . StreamError ( connectionError . ErrorCode ) ;
137+ throw ;
138+ }
133139 catch ( Exception ex )
134140 {
135141 Debug . WriteLine ( ex ) ;
@@ -141,7 +147,6 @@ public async Task ProcessStreamAsync<TContext>(IHttpApplication<TContext> applic
141147 }
142148
143149 private long ProcessStreamAsync < TContext > ( IHttpApplication < TContext > application ,
144- ref ulong frameType ,
145150 ref long payloadRemainingLength ,
146151 ref Task ? applicationProcessing ,
147152 ref StreamReadingStatus streamReadingState ,
@@ -153,7 +158,7 @@ private long ProcessStreamAsync<TContext>(IHttpApplication<TContext> application
153158 if ( streamReadingState == StreamReadingStatus . ReadingFrameHeader )
154159 {
155160 // FrameType is a single byte.
156- if ( ! VariableLenghtIntegerDecoder . TryRead ( buffer . FirstSpan , out frameType , out int bytesReadFrameType ) )
161+ if ( ! VariableLenghtIntegerDecoder . TryRead ( buffer . FirstSpan , out var frameType , out int bytesReadFrameType ) )
157162 {
158163 // Not enough data to read payload length.
159164 return 0 ;
@@ -165,49 +170,59 @@ private long ProcessStreamAsync<TContext>(IHttpApplication<TContext> application
165170 return 0 ;
166171 }
167172 payloadRemainingLength = checked ( ( long ) payloadLength ) ;
168- streamReadingState = StreamReadingStatus . ReadingPayload ;
173+ streamReadingState = NextRequestReadingState ( applicationProcessing , frameType ) ;
169174 buffer = buffer . Slice ( bytesReadPayloadLength ) ;
170175 bufferConsumed += bytesReadFrameType + bytesReadPayloadLength ;
171176 return bufferConsumed ;
172177 }
173178
174- if ( streamReadingState == StreamReadingStatus . ReadingPayload )
179+ if ( payloadRemainingLength < buffer . Length )
180+ buffer = buffer . Slice ( 0 , payloadRemainingLength ) ;
181+
182+ if ( streamReadingState == StreamReadingStatus . ReadingPayloadHeader )
175183 {
176- switch ( frameType )
177- {
178- case 0x0 : // DATA
179- if ( payloadRemainingLength < buffer . Length )
180- buffer = buffer . Slice ( 0 , payloadRemainingLength ) ;
181- bufferConsumed = ProcessDataFrame ( buffer ) ;
182- payloadRemainingLength -= bufferConsumed ;
183- break ;
184- case 0x1 : // HEADERS
185- if ( payloadRemainingLength < buffer . Length )
186- buffer = buffer . Slice ( 0 , payloadRemainingLength ) ;
187- bufferConsumed = ProcessHeaderFrame ( buffer ) ;
188- payloadRemainingLength -= bufferConsumed ;
189- if ( payloadRemainingLength == 0 )
190- applicationProcessing = Task . Run ( ( ) => StartApplicationProcessing ( application , token ) , token ) ;
191- break ;
192- default :
193- if ( ( frameType - 0x21 ) % 0x1f != 0 )
194- {
195- _connection ? . StreamError ( ErrorCodes . H3FrameUnexpected ) ;
196- throw new Http3ConnectionException ( ErrorCodes . H3FrameUnexpected ) ;
197- }
198-
199- // Read the complete reserved frame.
200- bufferConsumed = payloadRemainingLength > buffer . Length ? buffer . Length : payloadRemainingLength ;
201- payloadRemainingLength -= bufferConsumed ;
202- break ;
203- }
204- if ( payloadRemainingLength == 0 )
205- streamReadingState = StreamReadingStatus . ReadingFrameHeader ;
184+ bufferConsumed = ProcessHeaderFrame ( buffer ) ;
185+ if ( payloadRemainingLength == bufferConsumed )
186+ applicationProcessing = Task . Run ( ( ) => StartApplicationProcessing ( application , token ) , token ) ;
206187 }
207188
189+ if ( streamReadingState == StreamReadingStatus . ReadingPayloadData )
190+ bufferConsumed = ProcessDataFrame ( buffer ) ;
191+
192+ if ( streamReadingState == StreamReadingStatus . ReadingPayloadReserved )
193+ bufferConsumed = buffer . Length ; // Read the complete reserved frame.
194+
195+ payloadRemainingLength -= bufferConsumed ;
196+ if ( payloadRemainingLength == 0 )
197+ streamReadingState = StreamReadingStatus . ReadingFrameHeader ;
208198 return bufferConsumed ;
209199 }
210200
201+ private StreamReadingStatus NextRequestReadingState ( Task ? applicationProcessing , ulong frameType )
202+ {
203+ StreamReadingStatus streamReadingState ;
204+ switch ( frameType )
205+ {
206+ case 0x0 : // DATA
207+ if ( applicationProcessing == null )
208+ throw new Http3ConnectionException ( ErrorCodes . H3FrameUnexpected ) ;
209+ streamReadingState = StreamReadingStatus . ReadingPayloadData ;
210+ break ;
211+ case 0x1 : // HEADERS
212+ if ( applicationProcessing != null )
213+ throw new Http3ConnectionException ( ErrorCodes . H3FrameUnexpected ) ;
214+ streamReadingState = StreamReadingStatus . ReadingPayloadHeader ;
215+ break ;
216+ default :
217+ if ( ( frameType - 0x21 ) % 0x1f != 0 )
218+ throw new Http3ConnectionException ( ErrorCodes . H3FrameUnexpected ) ;
219+ streamReadingState = StreamReadingStatus . ReadingPayloadReserved ;
220+ break ;
221+ }
222+
223+ return streamReadingState ;
224+ }
225+
211226 private async Task CloseStreamAsync ( )
212227 {
213228 await _dataReader . CompleteAsync ( ) ;
@@ -221,7 +236,7 @@ private async Task CloseStreamAsync()
221236 private long ProcessDataFrame ( ReadOnlySequence < byte > buffer )
222237 {
223238 // 'Copy' to Body
224- return 0 ;
239+ return buffer . Length ;
225240
226241 }
227242
@@ -337,4 +352,4 @@ internal partial class Http3Stream : IHttpResponseTrailersFeature
337352{
338353 private readonly Http3ResponseHeaderCollection _responseTrailers ;
339354 public IHeaderDictionary Trailers { get => _responseTrailers ; set => throw new PlatformNotSupportedException ( ) ; }
340- }
355+ }
0 commit comments