@@ -238,12 +238,7 @@ public bool ParseHeaders(TRequestHandler handler, ref SequenceReader<byte> reade
238
238
// If not found length with be -1; casting to uint will turn it to uint.MaxValue
239
239
// which will be larger than any possible span.Length. This also serves to eliminate
240
240
// the bounds check for the next lookup of span[length]
241
- if ( ( uint ) length >= ( uint ) span . Length )
242
- {
243
- // Not enough data yet.
244
- goto Continue ;
245
- }
246
- else
241
+ if ( ( uint ) length < ( uint ) span . Length )
247
242
{
248
243
// Early memory read to hide latency
249
244
var expectedCR = span [ length ] ;
@@ -253,7 +248,7 @@ public bool ParseHeaders(TRequestHandler handler, ref SequenceReader<byte> reade
253
248
if ( expectedCR != ByteCR )
254
249
{
255
250
// Sequence needs to be CRLF not LF first.
256
- goto Reject ;
251
+ RejectRequestHeader ( span [ .. length ] ) ;
257
252
}
258
253
259
254
if ( ( uint ) length < ( uint ) span . Length )
@@ -263,48 +258,27 @@ public bool ParseHeaders(TRequestHandler handler, ref SequenceReader<byte> reade
263
258
// Correctly has a LF, move to next
264
259
length ++ ;
265
260
266
- if ( expectedLF != ByteLF )
261
+ if ( expectedLF != ByteLF ||
262
+ length < 5 ||
263
+ // Exclude the CRLF from the headerLine and parse the header name:value pair
264
+ ! TryTakeSingleHeader ( handler , span [ ..( length - 2 ) ] ) )
267
265
{
268
266
// Sequence needs to be CRLF and not contain an inner CR not part of terminator.
269
- goto Reject ;
270
- }
271
-
272
- if ( length < 5 )
273
- {
274
267
// Less than min possible headerSpan of 5 bytes a:b\r\n
275
- goto Reject ;
276
- }
277
-
278
- // Exclude the CRLF from the headerLine and parse the header name:value pair
279
- if ( ! TryTakeSingleHeader ( handler , span [ ..( length - 2 ) ] ) )
280
- {
281
268
// Not parsable as a valid name:value header pair.
282
- goto Reject ;
269
+ RejectRequestHeader ( span [ .. length ] ) ;
283
270
}
284
271
285
272
// Read the header successfully, skip the reader forward past the headerSpan.
286
273
span = span . Slice ( length ) ;
287
274
reader . Advance ( length ) ;
288
-
289
- goto Success ;
290
275
}
291
276
else
292
277
{
293
- // Not enough data yet .
294
- goto Continue ;
278
+ // No enough data, set length to 0 .
279
+ length = 0 ;
295
280
}
296
-
297
281
}
298
-
299
- // Reject and Continue are conditional jump forwards as we expect most headers to be processed first time,
300
- // so we want them to be unpredicted by an unprimied branch predictor.
301
- Reject :
302
- RejectRequestHeader ( span [ ..length ] ) ;
303
- Continue :
304
- // Not enough data, reset consumed length to 0
305
- length = 0 ;
306
- Success :
307
- ;
308
282
}
309
283
310
284
// End found in current span
@@ -349,7 +323,6 @@ private int ParseMultiSpanHeader(TRequestHandler handler, ref SequenceReader<byt
349
323
350
324
SequencePosition lineEnd ;
351
325
ReadOnlySpan < byte > headerSpan ;
352
- int length ;
353
326
if ( currentSlice . Slice ( reader . Position , lineEndPosition . Value ) . Length == currentSlice . Length - 1 )
354
327
{
355
328
// No enough data, so CRLF can't currently be there.
@@ -358,10 +331,9 @@ private int ParseMultiSpanHeader(TRequestHandler handler, ref SequenceReader<byt
358
331
// Advance 1 to include CR/LF in lineEnd
359
332
lineEnd = currentSlice . GetPosition ( 1 , lineEndPosition . Value ) ;
360
333
headerSpan = currentSlice . Slice ( reader . Position , lineEnd ) . ToSpan ( ) ;
361
- length = headerSpan . Length ;
362
334
if ( headerSpan [ ^ 1 ] != ByteCR )
363
335
{
364
- goto Reject ;
336
+ RejectRequestHeader ( headerSpan ) ;
365
337
}
366
338
return - 1 ;
367
339
}
@@ -370,42 +342,27 @@ private int ParseMultiSpanHeader(TRequestHandler handler, ref SequenceReader<byt
370
342
lineEnd = currentSlice . GetPosition ( 2 , lineEndPosition . Value ) ;
371
343
headerSpan = currentSlice . Slice ( reader . Position , lineEnd ) . ToSpan ( ) ;
372
344
373
- length = headerSpan . Length ;
374
- if ( length < 5 )
345
+ if ( headerSpan . Length < 5 )
375
346
{
376
347
// Less than min possible headerSpan is 5 bytes a:b\r\n
377
- goto Reject ;
348
+ RejectRequestHeader ( headerSpan ) ;
378
349
}
379
350
380
- // Sequence needs to be CRLF not LF first.
381
351
if ( headerSpan [ ^ 2 ] != ByteCR )
382
352
{
383
- goto RejectEarly ;
353
+ // Sequence needs to be CRLF not LF first.
354
+ RejectRequestHeader ( headerSpan [ ..^ 1 ] ) ;
384
355
}
385
356
386
- if ( headerSpan [ ^ 1 ] != ByteLF )
357
+ if ( headerSpan [ ^ 1 ] != ByteLF ||
358
+ // Exclude the CRLF from the headerLine and parse the header name:value pair
359
+ ! TryTakeSingleHeader ( handler , headerSpan [ ..^ 2 ] ) )
387
360
{
388
361
// Sequence needs to be CRLF and not contain an inner CR not part of terminator.
389
- goto Reject ;
390
- }
391
-
392
- // Exclude the CRLF from the headerLine and parse the header name:value pair
393
- if ( ! TryTakeSingleHeader ( handler , headerSpan [ ..^ 2 ] ) )
394
- {
395
362
// Not parsable as a valid name:value header pair.
396
- goto Reject ;
363
+ RejectRequestHeader ( headerSpan ) ;
397
364
}
398
365
399
- goto Success ;
400
-
401
- // Reject is a conditional jump forwards as we expect most headers to be processed first time,
402
- // so we want them to be unpredicted by an unprimied branch predictor.
403
- RejectEarly :
404
- length -- ;
405
- Reject :
406
- RejectRequestHeader ( headerSpan [ ..length ] ) ;
407
-
408
- Success :
409
366
return headerSpan . Length ;
410
367
}
411
368
0 commit comments