@@ -177,6 +177,82 @@ public async Task Http2_ZeroLengthResponseBody_Success()
177177            } 
178178        } 
179179
180+         [ Fact ] 
181+         public  async  Task  Http2_DataFrameOnlyPadding_Success ( ) 
182+         { 
183+             using  ( Http2LoopbackServer  server  =  Http2LoopbackServer . CreateServer ( ) ) 
184+             using  ( HttpClient  client  =  CreateHttpClient ( ) ) 
185+             { 
186+                 Task < HttpResponseMessage >  sendTask  =  client . GetAsync ( server . Address ,  HttpCompletionOption . ResponseHeadersRead ) ; 
187+ 
188+                 Http2LoopbackConnection  connection  =  await  server . EstablishConnectionAsync ( ) ; 
189+ 
190+                 int  streamId  =  await  connection . ReadRequestHeaderAsync ( ) ; 
191+ 
192+                 await  connection . SendDefaultResponseHeadersAsync ( streamId ) ; 
193+ 
194+                 // Send zero-length DATA frame with padding 
195+                 byte  paddingLength  =  byte . MaxValue ; 
196+                 int  dataLength  =  1024 ; 
197+                 DataFrame  frame  =  new  DataFrame ( new  byte [ 0 ] ,  FrameFlags . Padded ,  paddingLength ,  streamId ) ; 
198+                 await  connection . WriteFrameAsync ( frame ) ; 
199+ 
200+                 HttpResponseMessage  response  =  await  sendTask ; 
201+                 Assert . Equal ( HttpStatusCode . OK ,  response . StatusCode ) ; 
202+ 
203+                 using  var  responseStream  =  response . Content . ReadAsStream ( ) ; 
204+ 
205+                 // The read must pend because we havent received any data yet. 
206+                 var  buffer  =  new  byte [ dataLength ] ; 
207+                 var  readTask  =  ReadAtLeastAsync ( responseStream ,  buffer ,  dataLength ) ; 
208+                 Assert . False ( readTask . IsCompleted ) ; 
209+ 
210+                 // Send DATA frame with padding 
211+                 frame  =  new  DataFrame ( new  byte [ dataLength ] ,  FrameFlags . Padded ,  paddingLength ,  streamId ) ; 
212+                 await  connection . WriteFrameAsync ( frame ) ; 
213+ 
214+                 Assert . Equal ( dataLength ,  await  readTask ) ; 
215+ 
216+                 // Send zero-length, end-stream DATA frame with padding 
217+                 frame  =  new  DataFrame ( new  byte [ 0 ] ,  FrameFlags . Padded  |  FrameFlags . EndStream ,  paddingLength ,  streamId ) ; 
218+                 await  connection . WriteFrameAsync ( frame ) ; 
219+ 
220+                 Assert . Equal ( 0 ,  await  responseStream . ReadAsync ( buffer ) ) ; 
221+             } 
222+         } 
223+ 
224+         private  static async  ValueTask < int >  ReadAtLeastAsync ( Stream  stream ,  Memory < byte >  buffer ,  int  minimumBytes ,  bool  throwOnEndOfStream  =  true ,  CancellationToken  cancellationToken  =  default ) 
225+         { 
226+             if  ( minimumBytes  <  0 ) 
227+             { 
228+                 throw  new  ArgumentOutOfRangeException ( nameof ( minimumBytes ) ) ; 
229+             } 
230+             if  ( buffer . Length  <  minimumBytes ) 
231+             { 
232+                 throw  new  ArgumentOutOfRangeException ( $ "{ nameof ( buffer ) } .{ nameof ( buffer . Length ) } ") ; 
233+             } 
234+ 
235+             int  totalRead  =  0 ; 
236+             while  ( totalRead  <  minimumBytes ) 
237+             { 
238+                 int  read  =  await  stream . ReadAsync ( buffer . Slice ( totalRead ) ,  cancellationToken ) . ConfigureAwait ( false ) ; 
239+                 if  ( read  ==  0 ) 
240+                 { 
241+                     if  ( throwOnEndOfStream ) 
242+                     { 
243+                         throw  new  EndOfStreamException ( ) ; 
244+                     } 
245+ 
246+                     return  totalRead ; 
247+                 } 
248+ 
249+                 totalRead  +=  read ; 
250+             } 
251+ 
252+             return  totalRead ; 
253+         } 
254+ 
255+ 
180256        [ Theory ] 
181257        [ InlineData ( "Client content" ,  null ) ] 
182258        [ InlineData ( "Client content" ,  "Server content" ) ] 
@@ -204,7 +280,7 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri =>
204280                Http2LoopbackConnection  connection  =  await  server . EstablishConnectionAsync ( ) ; 
205281                Assert . IsNotType < SslStream > ( connection . Stream ) ; 
206282
207-                 HttpRequestData  requestData  =  await  connection . ReadRequestDataAsync ( ) ;                  
283+                 HttpRequestData  requestData  =  await  connection . ReadRequestDataAsync ( ) ; 
208284                string  requestContent  =  requestData . Body  is  null  ?  ( string ) null  :  Encoding . ASCII . GetString ( requestData . Body ) ; 
209285                Assert . Equal ( clientContent ,  requestContent ) ; 
210286                await  connection . SendResponseAsync ( HttpStatusCode . OK ,  content :  serverContent ) ; 
0 commit comments