@@ -131,6 +131,7 @@ public async Task InvalidFrameTypeOnControlStream_Aborts(int frameType)
131131 await AssertGoAwayAsync ( controlStream , 2 ) ;
132132 } , TestContext . Current . CancellationToken ) ;
133133 var clientControlStream = await fixture . ClientConnection . OpenOutboundStreamAsync ( QuicStreamType . Unidirectional , TestContext . Current . CancellationToken ) ;
134+ await WriteSettings ( clientControlStream ) ;
134135
135136 // StreamType: 0-control, FrameType: 1-Invalid, Length: 0
136137 byte [ ] data = [ 0 , ( byte ) frameType , 0 ] ;
@@ -158,20 +159,16 @@ public async Task UnknownFrameType_OnControlStream_ISgnored(int frameType)
158159 await AssertGoAwayAsync ( controlStream , 2 ) ;
159160 } , TestContext . Current . CancellationToken ) ;
160161 var clientControlStream = await fixture . ClientConnection . OpenOutboundStreamAsync ( QuicStreamType . Unidirectional , TestContext . Current . CancellationToken ) ;
162+ await WriteSettings ( clientControlStream ) ;
161163
162164 // StreamType: 0-control, FrameType, Length: 0
163165 Span < byte > buffer = stackalloc byte [ 8 ] ;
164166 VariableLenghtIntegerDecoder . TryWrite ( buffer , frameType , out var length ) ;
165-
166167 byte [ ] data = [ 0 , .. buffer [ ..length ] , 0 ] ;
167168 await clientControlStream . WriteAsync ( data , TestContext . Current . CancellationToken ) ;
168169 await clientControlStream . FlushAsync ( TestContext . Current . CancellationToken ) ;
169170
170- // Write GOAWAY FrameType: 7, Length: 1, StreamId: 0
171- data = [ 7 , 1 , 0 ] ;
172- await clientControlStream . WriteAsync ( data , TestContext . Current . CancellationToken ) ;
173- await clientControlStream . FlushAsync ( TestContext . Current . CancellationToken ) ;
174-
171+ await WriteGoAway ( clientControlStream ) ;
175172 await readServerControlStream ;
176173 await processing ;
177174 }
@@ -305,6 +302,32 @@ await sut.ProcessConnectionAsync(new TestBase.TestApplication(_ => Task.Complete
305302 await readServerControlStream ;
306303 }
307304
305+ [ Fact ]
306+ public async Task ChromiumProcessFrames ( )
307+ {
308+ await using var fixture = await QuicConnectionFixture . SetupConnectionAsync ( Port , TestContext . Current . CancellationToken ) ;
309+ Http3Connection sut = CreateHttp3Connection ( fixture . ServerConnection ) ;
310+ var processing = sut . ProcessConnectionAsync ( new TestBase . TestApplication ( _ => Task . CompletedTask ) )
311+ . WaitAsync ( TimeSpan . FromSeconds ( 10 ) , TestContext . Current . CancellationToken ) ;
312+ var readServerControlStream = Task . Run ( async ( ) =>
313+ {
314+ var controlStream = await fixture . ClientConnection . AcceptInboundStreamAsync ( TestContext . Current . CancellationToken ) ;
315+ await AssertReadSettigsAsync ( controlStream ) ;
316+ await AssertGoAwayAsync ( controlStream , 2 ) ;
317+ } , TestContext . Current . CancellationToken ) ;
318+ var clientControlStream = await fixture . ClientConnection . OpenOutboundStreamAsync ( QuicStreamType . Unidirectional , TestContext . Current . CancellationToken ) ;
319+
320+ // Chromium control stream data: Settings Frame, Grease, Priorty Frames (Unknown)
321+ byte [ ] data = [ 0 , 4 , 27 , 1 , 128 , 1 , 0 , 0 , 6 , 128 , 4 , 0 , 0 , 7 , 64 , 100 , 51 , 1 , 192 , 0 , 0 , 30 , 67 , 87 , 179 , 56 , 154 , 124 , 38 , 21 , 192 , 0 , 0 , 20 , 86 , 88 , 150 , 239 , 2 , 240 , 76 , 128 , 15 , 7 , 0 , 7 , 0 , 117 , 61 , 48 , 44 , 32 , 105 ] ;
322+ await clientControlStream . WriteAsync ( data , TestContext . Current . CancellationToken ) ;
323+ await clientControlStream . FlushAsync ( TestContext . Current . CancellationToken ) ;
324+
325+ await WriteGoAway ( clientControlStream ) ;
326+ await readServerControlStream ;
327+ await processing ;
328+ Assert . Equal ( 262144ul , sut . ClientMaxFieldSectionSize ) ;
329+ }
330+
308331 private static Http3Connection CreateHttp3Connection ( QuicConnection serverConnection , CHttpServerOptions ? options = null , CancellationTokenSource ? connectionCancellation = null )
309332 {
310333 var connectionContext = new CHttp3ConnectionContext ( )
@@ -343,12 +366,49 @@ private static async Task AssertReadSettigsAsync(Stream stream, byte expectedSet
343366 encodedValue . SequenceEqual ( buffer [ 4 ..] ) ;
344367 }
345368
369+ private static async Task < IEnumerable < KeyValuePair < long , long > > > ReadSettigsAsync ( Stream stream , CancellationToken token = default )
370+ {
371+ var headerBuffer = new byte [ 10 ] ;
372+ int readCount = await stream . ReadAtLeastAsync ( headerBuffer , headerBuffer . Length , true , token ) ;
373+ Assert . Equal ( 0x00 , headerBuffer [ 0 ] ) ; // Control Stream Type
374+ Assert . Equal ( 0x04 , headerBuffer [ 1 ] ) ; // Frame Type: SETTINGS
375+ if ( ! VariableLenghtIntegerDecoder . TryRead ( headerBuffer [ 2 ..readCount ] , out var payloadLength , out var bytesCount ) )
376+ Assert . Fail ( ) ;
377+
378+ var payloadBuffer = new byte [ payloadLength ] ;
379+ headerBuffer . AsSpan ( ) [ ( 2 + bytesCount ) ..readCount ] . CopyTo ( payloadBuffer ) ;
380+ var remainingPayloadLength = readCount - 2 - bytesCount ;
381+ await stream . ReadExactlyAsync ( payloadBuffer . AsMemory ( remainingPayloadLength ) ) ;
382+
383+ var data = payloadBuffer . AsSpan ( ) ;
384+ List < KeyValuePair < long , long > > result = [ ] ;
385+ while ( ! data . IsEmpty )
386+ {
387+ if ( ! VariableLenghtIntegerDecoder . TryRead ( data , out var settingIdentifier , out bytesCount ) )
388+ Assert . Fail ( ) ;
389+ data = data . Slice ( bytesCount ) ;
390+ if ( ! VariableLenghtIntegerDecoder . TryRead ( data , out var settingValue , out bytesCount ) )
391+ Assert . Fail ( ) ;
392+ data = data . Slice ( bytesCount ) ;
393+ result . Add ( new ( ( long ) settingIdentifier , ( long ) settingValue ) ) ;
394+ }
395+ return result ;
396+ }
397+
346398 private static async Task WriteSettings ( QuicStream clientControlStream )
347399 {
348400 // StreamType: 0-control, FrameType: 4-Settings, Length: 2, Setting Identifier: 33-Reserved, Value: 0
349401 byte [ ] data = [ 0 , 4 , 2 , 33 , 0 ] ;
350402 await clientControlStream . WriteAsync ( data , TestContext . Current . CancellationToken ) ;
351403 await clientControlStream . FlushAsync ( TestContext . Current . CancellationToken ) ;
352404 }
405+
406+ private static async Task WriteGoAway ( QuicStream clientControlStream )
407+ {
408+ // Write GOAWAY FrameType: 7, Length: 1, StreamId: 0
409+ byte [ ] data = [ 7 , 1 , 0 ] ;
410+ await clientControlStream . WriteAsync ( data , TestContext . Current . CancellationToken ) ;
411+ await clientControlStream . FlushAsync ( TestContext . Current . CancellationToken ) ;
412+ }
353413}
354414
0 commit comments