From 11ed34f229ac178db8fecbf45c14db4954219a2a Mon Sep 17 00:00:00 2001 From: Nathan Anderson Date: Thu, 29 Sep 2016 15:56:47 -0700 Subject: [PATCH] add header ordering and short circuits to known headers refactor known header changes - create template string from Append switch - add a check to ClearFast to bail out if too many headers are set --- .../Internal/Http/FrameHeaders.Generated.cs | 1796 ++++++++++++++--- .../KnownHeaders.cs | 151 +- 2 files changed, 1578 insertions(+), 369 deletions(-) diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/FrameHeaders.Generated.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/FrameHeaders.Generated.cs index 82931f5681..217f47e7ba 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/FrameHeaders.Generated.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/FrameHeaders.Generated.cs @@ -3694,11 +3694,457 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http return MaybeUnknown?.Remove(key) ?? false; } protected override void ClearFast() - { - _bits = 0; - _headers = default(HeaderReferences); - + { MaybeUnknown?.Clear(); + + if(FrameHeaders.BitCount(_bits) > 12) + { + _headers = default(HeaderReferences); + _bits = 0; + return; + } + + + if (((_bits & 1048576L) != 0)) + { + _headers._Accept = default(StringValues); + _bits &= ~1048576L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 268435456L) != 0)) + { + _headers._Host = default(StringValues); + _bits &= ~268435456L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 1099511627776L) != 0)) + { + _headers._UserAgent = default(StringValues); + _bits &= ~1099511627776L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 1L) != 0)) + { + _headers._CacheControl = default(StringValues); + _bits &= ~1L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 2L) != 0)) + { + _headers._Connection = default(StringValues); + _bits &= ~2L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 4L) != 0)) + { + _headers._Date = default(StringValues); + _bits &= ~4L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 8L) != 0)) + { + _headers._KeepAlive = default(StringValues); + _bits &= ~8L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 16L) != 0)) + { + _headers._Pragma = default(StringValues); + _bits &= ~16L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 32L) != 0)) + { + _headers._Trailer = default(StringValues); + _bits &= ~32L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 64L) != 0)) + { + _headers._TransferEncoding = default(StringValues); + _bits &= ~64L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 128L) != 0)) + { + _headers._Upgrade = default(StringValues); + _bits &= ~128L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 256L) != 0)) + { + _headers._Via = default(StringValues); + _bits &= ~256L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 512L) != 0)) + { + _headers._Warning = default(StringValues); + _bits &= ~512L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 1024L) != 0)) + { + _headers._Allow = default(StringValues); + _bits &= ~1024L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 2048L) != 0)) + { + _headers._ContentLength = default(StringValues); + _bits &= ~2048L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 4096L) != 0)) + { + _headers._ContentType = default(StringValues); + _bits &= ~4096L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 8192L) != 0)) + { + _headers._ContentEncoding = default(StringValues); + _bits &= ~8192L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 16384L) != 0)) + { + _headers._ContentLanguage = default(StringValues); + _bits &= ~16384L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 32768L) != 0)) + { + _headers._ContentLocation = default(StringValues); + _bits &= ~32768L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 65536L) != 0)) + { + _headers._ContentMD5 = default(StringValues); + _bits &= ~65536L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 131072L) != 0)) + { + _headers._ContentRange = default(StringValues); + _bits &= ~131072L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 262144L) != 0)) + { + _headers._Expires = default(StringValues); + _bits &= ~262144L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 524288L) != 0)) + { + _headers._LastModified = default(StringValues); + _bits &= ~524288L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 2097152L) != 0)) + { + _headers._AcceptCharset = default(StringValues); + _bits &= ~2097152L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 4194304L) != 0)) + { + _headers._AcceptEncoding = default(StringValues); + _bits &= ~4194304L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 8388608L) != 0)) + { + _headers._AcceptLanguage = default(StringValues); + _bits &= ~8388608L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 16777216L) != 0)) + { + _headers._Authorization = default(StringValues); + _bits &= ~16777216L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 33554432L) != 0)) + { + _headers._Cookie = default(StringValues); + _bits &= ~33554432L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 67108864L) != 0)) + { + _headers._Expect = default(StringValues); + _bits &= ~67108864L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 134217728L) != 0)) + { + _headers._From = default(StringValues); + _bits &= ~134217728L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 536870912L) != 0)) + { + _headers._IfMatch = default(StringValues); + _bits &= ~536870912L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 1073741824L) != 0)) + { + _headers._IfModifiedSince = default(StringValues); + _bits &= ~1073741824L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 2147483648L) != 0)) + { + _headers._IfNoneMatch = default(StringValues); + _bits &= ~2147483648L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 4294967296L) != 0)) + { + _headers._IfRange = default(StringValues); + _bits &= ~4294967296L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 8589934592L) != 0)) + { + _headers._IfUnmodifiedSince = default(StringValues); + _bits &= ~8589934592L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 17179869184L) != 0)) + { + _headers._MaxForwards = default(StringValues); + _bits &= ~17179869184L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 34359738368L) != 0)) + { + _headers._ProxyAuthorization = default(StringValues); + _bits &= ~34359738368L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 68719476736L) != 0)) + { + _headers._Referer = default(StringValues); + _bits &= ~68719476736L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 137438953472L) != 0)) + { + _headers._Range = default(StringValues); + _bits &= ~137438953472L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 274877906944L) != 0)) + { + _headers._TE = default(StringValues); + _bits &= ~274877906944L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 549755813888L) != 0)) + { + _headers._Translate = default(StringValues); + _bits &= ~549755813888L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 2199023255552L) != 0)) + { + _headers._Origin = default(StringValues); + _bits &= ~2199023255552L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 4398046511104L) != 0)) + { + _headers._AccessControlRequestMethod = default(StringValues); + _bits &= ~4398046511104L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 8796093022208L) != 0)) + { + _headers._AccessControlRequestHeaders = default(StringValues); + _bits &= ~8796093022208L; + if(_bits == 0) + { + return; + } + } + } protected override void CopyToFast(KeyValuePair[] array, int arrayIndex) @@ -4197,6 +4643,86 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string value) + { + fixed (byte* ptr = &keyBytes[keyOffset]) + { + var pUB = ptr; + var pUL = (ulong*)pUB; + var pUI = (uint*)pUB; + var pUS = (ushort*)pUB; + switch (keyLength) + { + case 6: + { + if ((((pUI[0] & 3755991007u) == 1162036033u) && ((pUS[2] & 57311u) == 21584u))) + { + if (((_bits & 1048576L) != 0)) + { + _headers._Accept = AppendValue(_headers._Accept, value); + } + else + { + _bits |= 1048576L; + _headers._Accept = new StringValues(value); + } + return; + + } + } + break; + + + + case 4: + { + if ((((pUI[0] & 3755991007u) == 1414745928u))) + { + if (((_bits & 268435456L) != 0)) + { + _headers._Host = AppendValue(_headers._Host, value); + } + else + { + _bits |= 268435456L; + _headers._Host = new StringValues(value); + } + return; + + } + } + break; + + + + case 10: + { + if ((((pUL[0] & 16131858680330051551uL) == 4992030374873092949uL) && ((pUS[4] & 57311u) == 21582u))) + { + if (((_bits & 1099511627776L) != 0)) + { + _headers._UserAgent = AppendValue(_headers._UserAgent, value); + } + else + { + _bits |= 1099511627776L; + _headers._UserAgent = new StringValues(value); + } + return; + + } + } + break; + + + } + + + } + + AppendNonPrimaryHeaders(keyBytes, keyOffset, keyLength, value); + } + + private unsafe void AppendNonPrimaryHeaders(byte[] keyBytes, int keyOffset, int keyLength, string value) { string key; fixed (byte* ptr = &keyBytes[keyOffset]) @@ -4221,6 +4747,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._CacheControl = new StringValues(value); } return; + } if ((((pUL[0] & 18437701552104792031uL) == 3266321689424580419uL) && ((pUI[2] & 3755991007u) == 1196310866u) && ((pUB[12] & 223u) == 69u))) @@ -4235,6 +4762,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._ContentRange = new StringValues(value); } return; + } if ((((pUL[0] & 16131858680330051551uL) == 4922237774822850892uL) && ((pUI[2] & 3755991007u) == 1162430025u) && ((pUB[12] & 223u) == 68u))) @@ -4249,6 +4777,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._LastModified = new StringValues(value); } return; + } if ((((pUL[0] & 16131858542891098079uL) == 6505821637182772545uL) && ((pUI[2] & 3755991007u) == 1330205761u) && ((pUB[12] & 223u) == 78u))) @@ -4263,6 +4792,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Authorization = new StringValues(value); } return; + } if ((((pUL[0] & 18437701552106889183uL) == 3262099607620765257uL) && ((pUI[2] & 3755991007u) == 1129595213u) && ((pUB[12] & 223u) == 72u))) @@ -4277,9 +4807,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._IfNoneMatch = new StringValues(value); } return; + } } break; + + case 10: { @@ -4295,6 +4828,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Connection = new StringValues(value); } return; + } if ((((pUL[0] & 16131858680330051551uL) == 5281668125874799947uL) && ((pUS[4] & 57311u) == 17750u))) @@ -4309,23 +4843,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._KeepAlive = new StringValues(value); } return; - } - - if ((((pUL[0] & 16131858680330051551uL) == 4992030374873092949uL) && ((pUS[4] & 57311u) == 21582u))) - { - if (((_bits & 1099511627776L) != 0)) - { - _headers._UserAgent = AppendValue(_headers._UserAgent, value); - } - else - { - _bits |= 1099511627776L; - _headers._UserAgent = new StringValues(value); - } - return; + } } break; + + case 4: { @@ -4341,6 +4864,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Date = new StringValues(value); } return; + } if ((((pUI[0] & 3755991007u) == 1297044038u))) @@ -4355,23 +4879,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._From = new StringValues(value); } return; - } - - if ((((pUI[0] & 3755991007u) == 1414745928u))) - { - if (((_bits & 268435456L) != 0)) - { - _headers._Host = AppendValue(_headers._Host, value); - } - else - { - _bits |= 268435456L; - _headers._Host = new StringValues(value); - } - return; + } } break; + + case 6: { @@ -4387,20 +4900,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Pragma = new StringValues(value); } return; - } - - if ((((pUI[0] & 3755991007u) == 1162036033u) && ((pUS[2] & 57311u) == 21584u))) - { - if (((_bits & 1048576L) != 0)) - { - _headers._Accept = AppendValue(_headers._Accept, value); - } - else - { - _bits |= 1048576L; - _headers._Accept = new StringValues(value); - } - return; + } if ((((pUI[0] & 3755991007u) == 1263488835u) && ((pUS[2] & 57311u) == 17737u))) @@ -4415,6 +4915,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Cookie = new StringValues(value); } return; + } if ((((pUI[0] & 3755991007u) == 1162893381u) && ((pUS[2] & 57311u) == 21571u))) @@ -4429,6 +4930,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Expect = new StringValues(value); } return; + } if ((((pUI[0] & 3755991007u) == 1195987535u) && ((pUS[2] & 57311u) == 20041u))) @@ -4443,9 +4945,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Origin = new StringValues(value); } return; + } } break; + + case 7: { @@ -4461,6 +4966,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Trailer = new StringValues(value); } return; + } if ((((pUI[0] & 3755991007u) == 1380405333u) && ((pUS[2] & 57311u) == 17473u) && ((pUB[6] & 223u) == 69u))) @@ -4475,6 +4981,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Upgrade = new StringValues(value); } return; + } if ((((pUI[0] & 3755991007u) == 1314013527u) && ((pUS[2] & 57311u) == 20041u) && ((pUB[6] & 223u) == 71u))) @@ -4489,6 +4996,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Warning = new StringValues(value); } return; + } if ((((pUI[0] & 3755991007u) == 1230002245u) && ((pUS[2] & 57311u) == 17746u) && ((pUB[6] & 223u) == 83u))) @@ -4503,6 +5011,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Expires = new StringValues(value); } return; + } if ((((pUI[0] & 3755991007u) == 1162233170u) && ((pUS[2] & 57311u) == 17746u) && ((pUB[6] & 223u) == 82u))) @@ -4517,9 +5026,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Referer = new StringValues(value); } return; + } } break; + + case 17: { @@ -4535,6 +5047,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._TransferEncoding = new StringValues(value); } return; + } if ((((pUL[0] & 16131858542893195231uL) == 5064654363342751305uL) && ((pUL[1] & 16131858543427968991uL) == 4849894470315165001uL) && ((pUB[16] & 223u) == 69u))) @@ -4549,9 +5062,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._IfModifiedSince = new StringValues(value); } return; + } } break; + + case 3: { @@ -4567,9 +5083,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Via = new StringValues(value); } return; + } } break; + + case 5: { @@ -4585,6 +5104,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Allow = new StringValues(value); } return; + } if ((((pUI[0] & 3755991007u) == 1196310866u) && ((pUB[4] & 223u) == 69u))) @@ -4599,9 +5119,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Range = new StringValues(value); } return; + } } break; + + case 14: { @@ -4617,6 +5140,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._ContentLength = new StringValues(value); } return; + } if ((((pUL[0] & 16140865742145839071uL) == 4840617878229304129uL) && ((pUI[2] & 3755991007u) == 1397899592u) && ((pUS[6] & 57311u) == 21573u))) @@ -4631,9 +5155,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._AcceptCharset = new StringValues(value); } return; + } } break; + + case 12: { @@ -4649,6 +5176,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._ContentType = new StringValues(value); } return; + } if ((((pUL[0] & 16131858543427968991uL) == 6292178792217067853uL) && ((pUI[2] & 3755991007u) == 1396986433u))) @@ -4663,9 +5191,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._MaxForwards = new StringValues(value); } return; + } } break; + + case 16: { @@ -4681,6 +5212,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._ContentEncoding = new StringValues(value); } return; + } if ((((pUL[0] & 18437701552104792031uL) == 3266321689424580419uL) && ((pUL[1] & 16131858542891098079uL) == 4992030546487820620uL))) @@ -4695,6 +5227,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._ContentLanguage = new StringValues(value); } return; + } if ((((pUL[0] & 18437701552104792031uL) == 3266321689424580419uL) && ((pUL[1] & 16131858542891098079uL) == 5642809484339531596uL))) @@ -4709,9 +5242,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._ContentLocation = new StringValues(value); } return; + } } break; + + case 11: { @@ -4727,9 +5263,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._ContentMD5 = new StringValues(value); } return; + } } break; + + case 15: { @@ -4745,6 +5284,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._AcceptEncoding = new StringValues(value); } return; + } if ((((pUL[0] & 16140865742145839071uL) == 5489136224570655553uL) && ((pUI[2] & 3755991007u) == 1430736449u) && ((pUS[6] & 57311u) == 18241u) && ((pUB[14] & 223u) == 69u))) @@ -4759,9 +5299,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._AcceptLanguage = new StringValues(value); } return; + } } break; + + case 8: { @@ -4777,6 +5320,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._IfMatch = new StringValues(value); } return; + } if ((((pUL[0] & 16131858542893195231uL) == 4992044754422023753uL))) @@ -4791,9 +5335,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._IfRange = new StringValues(value); } return; + } } break; + + case 19: { @@ -4809,6 +5356,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._IfUnmodifiedSince = new StringValues(value); } return; + } if ((((pUL[0] & 16131893727263186911uL) == 6143241228466999888uL) && ((pUL[1] & 16131858542891098079uL) == 6071233043632179284uL) && ((pUS[8] & 57311u) == 20297u) && ((pUB[18] & 223u) == 78u))) @@ -4823,9 +5371,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._ProxyAuthorization = new StringValues(value); } return; + } } break; + + case 2: { @@ -4841,9 +5392,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._TE = new StringValues(value); } return; + } } break; + + case 9: { @@ -4859,9 +5413,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._Translate = new StringValues(value); } return; + } } break; + + case 29: { @@ -4877,9 +5434,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._AccessControlRequestMethod = new StringValues(value); } return; + } } break; + + case 30: { @@ -4895,19 +5455,24 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http _headers._AccessControlRequestHeaders = new StringValues(value); } return; + } } break; + + } - key = new string('\0', keyLength); - fixed(char *keyBuffer = key) - { - if (!AsciiUtilities.TryGetAsciiString(ptr, keyBuffer, keyLength)) + + key = new string('\0', keyLength); + fixed(char *keyBuffer = key) { - throw BadHttpRequestException.GetException(RequestRejectionReason.InvalidCharactersInHeaderName); + if (!AsciiUtilities.TryGetAsciiString(ptr, keyBuffer, keyLength)) + { + throw BadHttpRequestException.GetException(RequestRejectionReason.InvalidCharactersInHeaderName); + } } - } + } StringValues existing; @@ -8604,11 +9169,377 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http return MaybeUnknown?.Remove(key) ?? false; } protected override void ClearFast() - { - _bits = 0; - _headers = default(HeaderReferences); - _contentLength = null; + { MaybeUnknown?.Clear(); + _contentLength = null; + if(FrameHeaders.BitCount(_bits) > 12) + { + _headers = default(HeaderReferences); + _bits = 0; + return; + } + + + if (((_bits & 2L) != 0)) + { + _headers._Connection = default(StringValues); + _bits &= ~2L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 4L) != 0)) + { + _headers._Date = default(StringValues); + _bits &= ~4L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 2048L) != 0)) + { + _headers._ContentLength = default(StringValues); + _bits &= ~2048L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 4096L) != 0)) + { + _headers._ContentType = default(StringValues); + _bits &= ~4096L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 67108864L) != 0)) + { + _headers._Server = default(StringValues); + _bits &= ~67108864L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 1L) != 0)) + { + _headers._CacheControl = default(StringValues); + _bits &= ~1L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 8L) != 0)) + { + _headers._KeepAlive = default(StringValues); + _bits &= ~8L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 16L) != 0)) + { + _headers._Pragma = default(StringValues); + _bits &= ~16L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 32L) != 0)) + { + _headers._Trailer = default(StringValues); + _bits &= ~32L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 64L) != 0)) + { + _headers._TransferEncoding = default(StringValues); + _bits &= ~64L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 128L) != 0)) + { + _headers._Upgrade = default(StringValues); + _bits &= ~128L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 256L) != 0)) + { + _headers._Via = default(StringValues); + _bits &= ~256L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 512L) != 0)) + { + _headers._Warning = default(StringValues); + _bits &= ~512L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 1024L) != 0)) + { + _headers._Allow = default(StringValues); + _bits &= ~1024L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 8192L) != 0)) + { + _headers._ContentEncoding = default(StringValues); + _bits &= ~8192L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 16384L) != 0)) + { + _headers._ContentLanguage = default(StringValues); + _bits &= ~16384L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 32768L) != 0)) + { + _headers._ContentLocation = default(StringValues); + _bits &= ~32768L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 65536L) != 0)) + { + _headers._ContentMD5 = default(StringValues); + _bits &= ~65536L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 131072L) != 0)) + { + _headers._ContentRange = default(StringValues); + _bits &= ~131072L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 262144L) != 0)) + { + _headers._Expires = default(StringValues); + _bits &= ~262144L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 524288L) != 0)) + { + _headers._LastModified = default(StringValues); + _bits &= ~524288L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 1048576L) != 0)) + { + _headers._AcceptRanges = default(StringValues); + _bits &= ~1048576L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 2097152L) != 0)) + { + _headers._Age = default(StringValues); + _bits &= ~2097152L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 4194304L) != 0)) + { + _headers._ETag = default(StringValues); + _bits &= ~4194304L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 8388608L) != 0)) + { + _headers._Location = default(StringValues); + _bits &= ~8388608L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 16777216L) != 0)) + { + _headers._ProxyAutheticate = default(StringValues); + _bits &= ~16777216L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 33554432L) != 0)) + { + _headers._RetryAfter = default(StringValues); + _bits &= ~33554432L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 134217728L) != 0)) + { + _headers._SetCookie = default(StringValues); + _bits &= ~134217728L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 268435456L) != 0)) + { + _headers._Vary = default(StringValues); + _bits &= ~268435456L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 536870912L) != 0)) + { + _headers._WWWAuthenticate = default(StringValues); + _bits &= ~536870912L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 1073741824L) != 0)) + { + _headers._AccessControlAllowCredentials = default(StringValues); + _bits &= ~1073741824L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 2147483648L) != 0)) + { + _headers._AccessControlAllowHeaders = default(StringValues); + _bits &= ~2147483648L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 4294967296L) != 0)) + { + _headers._AccessControlAllowMethods = default(StringValues); + _bits &= ~4294967296L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 8589934592L) != 0)) + { + _headers._AccessControlAllowOrigin = default(StringValues); + _bits &= ~8589934592L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 17179869184L) != 0)) + { + _headers._AccessControlExposeHeaders = default(StringValues); + _bits &= ~17179869184L; + if(_bits == 0) + { + return; + } + } + + if (((_bits & 34359738368L) != 0)) + { + _headers._AccessControlMaxAge = default(StringValues); + _bits &= ~34359738368L; + if(_bits == 0) + { + return; + } + } + } protected override void CopyToFast(KeyValuePair[] array, int arrayIndex) @@ -9019,18 +9950,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http protected void CopyToFast(ref MemoryPoolIterator output) { - - if (((_bits & 1L) != 0)) - { - foreach (var value in _headers._CacheControl) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 0, 17); - output.CopyFromAscii(value); - } - } - } + var tempBits = _bits; if (((_bits & 2L) != 0)) { @@ -9047,6 +9967,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } + + tempBits &= ~2L; + if(tempBits == 0) + { + return; + } } if (((_bits & 4L) != 0)) @@ -9064,107 +9990,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } - } - - if (((_bits & 8L) != 0)) - { - foreach (var value in _headers._KeepAlive) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 39, 14); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 16L) != 0)) - { - foreach (var value in _headers._Pragma) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 53, 10); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 32L) != 0)) - { - foreach (var value in _headers._Trailer) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 63, 11); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 64L) != 0)) - { - if (_headers._rawTransferEncoding != null) + + tempBits &= ~4L; + if(tempBits == 0) { - output.CopyFrom(_headers._rawTransferEncoding, 0, _headers._rawTransferEncoding.Length); + return; } - else - foreach (var value in _headers._TransferEncoding) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 74, 21); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 128L) != 0)) - { - foreach (var value in _headers._Upgrade) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 95, 11); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 256L) != 0)) - { - foreach (var value in _headers._Via) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 106, 7); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 512L) != 0)) - { - foreach (var value in _headers._Warning) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 113, 11); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 1024L) != 0)) - { - foreach (var value in _headers._Allow) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 124, 9); - output.CopyFromAscii(value); - } - } } if (((_bits & 2048L) != 0)) @@ -9182,6 +10013,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } + + tempBits &= ~2048L; + if(tempBits == 0) + { + return; + } } if (((_bits & 4096L) != 0)) @@ -9194,162 +10031,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } - } - - if (((_bits & 8192L) != 0)) - { - foreach (var value in _headers._ContentEncoding) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 167, 20); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 16384L) != 0)) - { - foreach (var value in _headers._ContentLanguage) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 187, 20); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 32768L) != 0)) - { - foreach (var value in _headers._ContentLocation) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 207, 20); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 65536L) != 0)) - { - foreach (var value in _headers._ContentMD5) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 227, 15); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 131072L) != 0)) - { - foreach (var value in _headers._ContentRange) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 242, 17); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 262144L) != 0)) - { - foreach (var value in _headers._Expires) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 259, 11); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 524288L) != 0)) - { - foreach (var value in _headers._LastModified) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 270, 17); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 1048576L) != 0)) - { - foreach (var value in _headers._AcceptRanges) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 287, 17); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 2097152L) != 0)) - { - foreach (var value in _headers._Age) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 304, 7); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 4194304L) != 0)) - { - foreach (var value in _headers._ETag) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 311, 8); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 8388608L) != 0)) - { - foreach (var value in _headers._Location) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 319, 12); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 16777216L) != 0)) - { - foreach (var value in _headers._ProxyAutheticate) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 331, 21); - output.CopyFromAscii(value); - } - } - } - - if (((_bits & 33554432L) != 0)) - { - foreach (var value in _headers._RetryAfter) - { - if (value != null) - { - output.CopyFrom(_headerBytes, 352, 15); - output.CopyFromAscii(value); - } - } + + tempBits &= ~4096L; + if(tempBits == 0) + { + return; + } } if (((_bits & 67108864L) != 0)) @@ -9367,6 +10054,413 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } + + tempBits &= ~67108864L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 1L) != 0)) + { + foreach (var value in _headers._CacheControl) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 0, 17); + output.CopyFromAscii(value); + } + } + + tempBits &= ~1L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 8L) != 0)) + { + foreach (var value in _headers._KeepAlive) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 39, 14); + output.CopyFromAscii(value); + } + } + + tempBits &= ~8L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 16L) != 0)) + { + foreach (var value in _headers._Pragma) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 53, 10); + output.CopyFromAscii(value); + } + } + + tempBits &= ~16L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 32L) != 0)) + { + foreach (var value in _headers._Trailer) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 63, 11); + output.CopyFromAscii(value); + } + } + + tempBits &= ~32L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 64L) != 0)) + { + if (_headers._rawTransferEncoding != null) + { + output.CopyFrom(_headers._rawTransferEncoding, 0, _headers._rawTransferEncoding.Length); + } + else + foreach (var value in _headers._TransferEncoding) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 74, 21); + output.CopyFromAscii(value); + } + } + + tempBits &= ~64L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 128L) != 0)) + { + foreach (var value in _headers._Upgrade) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 95, 11); + output.CopyFromAscii(value); + } + } + + tempBits &= ~128L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 256L) != 0)) + { + foreach (var value in _headers._Via) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 106, 7); + output.CopyFromAscii(value); + } + } + + tempBits &= ~256L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 512L) != 0)) + { + foreach (var value in _headers._Warning) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 113, 11); + output.CopyFromAscii(value); + } + } + + tempBits &= ~512L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 1024L) != 0)) + { + foreach (var value in _headers._Allow) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 124, 9); + output.CopyFromAscii(value); + } + } + + tempBits &= ~1024L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 8192L) != 0)) + { + foreach (var value in _headers._ContentEncoding) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 167, 20); + output.CopyFromAscii(value); + } + } + + tempBits &= ~8192L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 16384L) != 0)) + { + foreach (var value in _headers._ContentLanguage) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 187, 20); + output.CopyFromAscii(value); + } + } + + tempBits &= ~16384L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 32768L) != 0)) + { + foreach (var value in _headers._ContentLocation) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 207, 20); + output.CopyFromAscii(value); + } + } + + tempBits &= ~32768L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 65536L) != 0)) + { + foreach (var value in _headers._ContentMD5) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 227, 15); + output.CopyFromAscii(value); + } + } + + tempBits &= ~65536L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 131072L) != 0)) + { + foreach (var value in _headers._ContentRange) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 242, 17); + output.CopyFromAscii(value); + } + } + + tempBits &= ~131072L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 262144L) != 0)) + { + foreach (var value in _headers._Expires) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 259, 11); + output.CopyFromAscii(value); + } + } + + tempBits &= ~262144L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 524288L) != 0)) + { + foreach (var value in _headers._LastModified) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 270, 17); + output.CopyFromAscii(value); + } + } + + tempBits &= ~524288L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 1048576L) != 0)) + { + foreach (var value in _headers._AcceptRanges) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 287, 17); + output.CopyFromAscii(value); + } + } + + tempBits &= ~1048576L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 2097152L) != 0)) + { + foreach (var value in _headers._Age) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 304, 7); + output.CopyFromAscii(value); + } + } + + tempBits &= ~2097152L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 4194304L) != 0)) + { + foreach (var value in _headers._ETag) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 311, 8); + output.CopyFromAscii(value); + } + } + + tempBits &= ~4194304L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 8388608L) != 0)) + { + foreach (var value in _headers._Location) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 319, 12); + output.CopyFromAscii(value); + } + } + + tempBits &= ~8388608L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 16777216L) != 0)) + { + foreach (var value in _headers._ProxyAutheticate) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 331, 21); + output.CopyFromAscii(value); + } + } + + tempBits &= ~16777216L; + if(tempBits == 0) + { + return; + } + } + + if (((_bits & 33554432L) != 0)) + { + foreach (var value in _headers._RetryAfter) + { + if (value != null) + { + output.CopyFrom(_headerBytes, 352, 15); + output.CopyFromAscii(value); + } + } + + tempBits &= ~33554432L; + if(tempBits == 0) + { + return; + } } if (((_bits & 134217728L) != 0)) @@ -9379,6 +10473,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } + + tempBits &= ~134217728L; + if(tempBits == 0) + { + return; + } } if (((_bits & 268435456L) != 0)) @@ -9391,6 +10491,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } + + tempBits &= ~268435456L; + if(tempBits == 0) + { + return; + } } if (((_bits & 536870912L) != 0)) @@ -9403,6 +10509,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } + + tempBits &= ~536870912L; + if(tempBits == 0) + { + return; + } } if (((_bits & 1073741824L) != 0)) @@ -9415,6 +10527,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } + + tempBits &= ~1073741824L; + if(tempBits == 0) + { + return; + } } if (((_bits & 2147483648L) != 0)) @@ -9427,6 +10545,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } + + tempBits &= ~2147483648L; + if(tempBits == 0) + { + return; + } } if (((_bits & 4294967296L) != 0)) @@ -9439,6 +10563,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } + + tempBits &= ~4294967296L; + if(tempBits == 0) + { + return; + } } if (((_bits & 8589934592L) != 0)) @@ -9451,6 +10581,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } + + tempBits &= ~8589934592L; + if(tempBits == 0) + { + return; + } } if (((_bits & 17179869184L) != 0)) @@ -9463,6 +10599,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } + + tempBits &= ~17179869184L; + if(tempBits == 0) + { + return; + } } if (((_bits & 34359738368L) != 0)) @@ -9475,10 +10617,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); } } + + tempBits &= ~34359738368L; + if(tempBits == 0) + { + return; + } } } + + private struct HeaderReferences { public StringValues _CacheControl; diff --git a/tools/Microsoft.AspNetCore.Server.Kestrel.GeneratedCode/KnownHeaders.cs b/tools/Microsoft.AspNetCore.Server.Kestrel.GeneratedCode/KnownHeaders.cs index 8cb51355ac..a062349f74 100644 --- a/tools/Microsoft.AspNetCore.Server.Kestrel.GeneratedCode/KnownHeaders.cs +++ b/tools/Microsoft.AspNetCore.Server.Kestrel.GeneratedCode/KnownHeaders.cs @@ -19,6 +19,51 @@ namespace Microsoft.AspNetCore.Server.Kestrel.GeneratedCode return condition ? formatter() : ""; } + static string AppendSwitch(IEnumerable> values, string className, bool handleUnknown = false) => + $@"fixed (byte* ptr = &keyBytes[keyOffset]) + {{ + var pUB = ptr; + var pUL = (ulong*)pUB; + var pUI = (uint*)pUB; + var pUS = (ushort*)pUB; + switch (keyLength) + {{{Each(values, byLength => $@" + case {byLength.Key}: + {{{Each(byLength, header => $@" + if ({header.EqualIgnoreCaseBytes()}) + {{ + if ({header.TestBit()}) + {{ + _headers._{header.Identifier} = AppendValue(_headers._{header.Identifier}, value); + }} + else + {{{If(className == "FrameResponseHeaders" && header.Identifier == "ContentLength", () => @" + _contentLength = ParseContentLength(value);")} + {header.SetBit()}; + _headers._{header.Identifier} = new StringValues(value);{(header.EnhancedSetter == false ? "" : $@" + _headers._raw{header.Identifier} = null;")} + }} + return; + + }} + ")}}} + break; + + + ")}}} + + {(handleUnknown ? $@" + key = new string('\0', keyLength); + fixed(char *keyBuffer = key) + {{ + if (!AsciiUtilities.TryGetAsciiString(ptr, keyBuffer, keyLength)) + {{ + throw BadHttpRequestException.GetException(RequestRejectionReason.InvalidCharactersInHeaderName); + }} + }} + ": "")} + }}"; + class KnownHeader { public string Name { get; set; } @@ -29,9 +74,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.GeneratedCode public int BytesOffset { get; set; } public int BytesCount { get; set; } public bool EnhancedSetter { get; set; } + public bool PrimaryHeader { get; set; } public string TestBit() => $"((_bits & {1L << Index}L) != 0)"; public string SetBit() => $"_bits |= {1L << Index}L"; public string ClearBit() => $"_bits &= ~{1L << Index}L"; + public string EqualIgnoreCaseBytes() { var result = ""; @@ -80,6 +127,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.GeneratedCode public static string GeneratedFile() { + var requestPrimaryHeaders = new[] + { + "Accept", + "Host", + "User-Agent" + + }; + var responsePrimaryHeaders = new[] + { + "Connection", + "Date", + "Content-Length", + "Content-Type", + "Server", + }; var commonHeaders = new[] { "Cache-Control", @@ -136,7 +198,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.GeneratedCode }).Concat(corsRequestHeaders).Select((header, index) => new KnownHeader { Name = header, - Index = index + Index = index, + PrimaryHeader = requestPrimaryHeaders.Contains(header) }).ToArray(); var enhancedHeaders = new[] { @@ -172,7 +235,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.GeneratedCode { Name = header, Index = index, - EnhancedSetter = enhancedHeaders.Contains(header) + EnhancedSetter = enhancedHeaders.Contains(header), + PrimaryHeader = responsePrimaryHeaders.Contains(header) }).ToArray(); var loops = new[] { @@ -377,11 +441,27 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http return MaybeUnknown?.Remove(key) ?? false; }} protected override void ClearFast() - {{ - _bits = 0; - _headers = default(HeaderReferences); - {(loop.ClassName == "FrameResponseHeaders" ? "_contentLength = null;" : "")} + {{ MaybeUnknown?.Clear(); + {(loop.ClassName == "FrameResponseHeaders" ? "_contentLength = null;" : "")} + if(FrameHeaders.BitCount(_bits) > 12) + {{ + _headers = default(HeaderReferences); + _bits = 0; + return; + }} + + {Each(loop.Headers.OrderBy(h => !h.PrimaryHeader), header => $@" + if ({header.TestBit()}) + {{ + _headers._{header.Identifier} = default(StringValues); + {header.ClearBit()}; + if(_bits == 0) + {{ + return; + }} + }} + ")} }} protected override void CopyToFast(KeyValuePair[] array, int arrayIndex) @@ -407,7 +487,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http {(loop.ClassName == "FrameResponseHeaders" ? $@" protected void CopyToFast(ref MemoryPoolIterator output) {{ - {Each(loop.Headers, header => $@" + var tempBits = _bits; + {Each(loop.Headers.OrderBy(h => !h.PrimaryHeader), header => $@" if ({header.TestBit()}) {{ {(header.EnhancedSetter == false ? "" : $@" if (_headers._raw{header.Identifier} != null) @@ -423,51 +504,29 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http output.CopyFromAscii(value); }} }} + + tempBits &= ~{1L << header.Index}L; + if(tempBits == 0) + {{ + return; + }} }} ")} - }}" : "")} + }} + + " : "")} {(loop.ClassName == "FrameRequestHeaders" ? $@" public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string value) + {{ + {AppendSwitch(loop.Headers.Where(h => h.PrimaryHeader).GroupBy(x => x.Name.Length), loop.ClassName)} + + AppendNonPrimaryHeaders(keyBytes, keyOffset, keyLength, value); + }} + + private unsafe void AppendNonPrimaryHeaders(byte[] keyBytes, int keyOffset, int keyLength, string value) {{ string key; - fixed (byte* ptr = &keyBytes[keyOffset]) - {{ - var pUB = ptr; - var pUL = (ulong*)pUB; - var pUI = (uint*)pUB; - var pUS = (ushort*)pUB; - switch (keyLength) - {{{Each(loop.HeadersByLength, byLength => $@" - case {byLength.Key}: - {{{Each(byLength, header => $@" - if ({header.EqualIgnoreCaseBytes()}) - {{ - if ({header.TestBit()}) - {{ - _headers._{header.Identifier} = AppendValue(_headers._{header.Identifier}, value); - }} - else - {{{If(loop.ClassName == "FrameResponseHeaders" && header.Identifier == "ContentLength", () => @" - _contentLength = ParseContentLength(value);")} - {header.SetBit()}; - _headers._{header.Identifier} = new StringValues(value);{(header.EnhancedSetter == false ? "" : $@" - _headers._raw{header.Identifier} = null;")} - }} - return; - }} - ")}}} - break; - ")}}} - - key = new string('\0', keyLength); - fixed(char *keyBuffer = key) - {{ - if (!AsciiUtilities.TryGetAsciiString(ptr, keyBuffer, keyLength)) - {{ - throw BadHttpRequestException.GetException(RequestRejectionReason.InvalidCharactersInHeaderName); - }} - }} - }} + {AppendSwitch(loop.Headers.Where(h => !h.PrimaryHeader).GroupBy(x => x.Name.Length), loop.ClassName, true)} StringValues existing; Unknown.TryGetValue(key, out existing);