Use writable buffer writer (#1564)
This commit is contained in:
parent
239b691ff5
commit
53b0eea2ec
|
|
@ -41,19 +41,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
return;
|
||||
}
|
||||
|
||||
var writableBuffer = _pipe.Writer.Alloc();
|
||||
|
||||
var writableBuffer = _pipe.Writer.Alloc(1);
|
||||
var writer = new WritableBufferWriter(writableBuffer);
|
||||
if (buffer.Count > 0)
|
||||
{
|
||||
if (chunk)
|
||||
{
|
||||
ChunkWriter.WriteBeginChunkBytes(ref writableBuffer, buffer.Count);
|
||||
writableBuffer.WriteFast(buffer);
|
||||
ChunkWriter.WriteEndChunkBytes(ref writableBuffer);
|
||||
ChunkWriter.WriteBeginChunkBytes(ref writer, buffer.Count);
|
||||
writer.Write(buffer.Array, buffer.Offset, buffer.Count);
|
||||
ChunkWriter.WriteEndChunkBytes(ref writer);
|
||||
}
|
||||
else
|
||||
{
|
||||
writableBuffer.WriteFast(buffer);
|
||||
writer.Write(buffer.Array, buffer.Offset, buffer.Count);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
|
|||
return;
|
||||
}
|
||||
|
||||
var buffer = _pipe.Writer.Alloc();
|
||||
var buffer = _pipe.Writer.Alloc(1);
|
||||
callback(buffer, state);
|
||||
buffer.Commit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,16 +47,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return new ArraySegment<byte>(bytes, offset, 10 - offset);
|
||||
}
|
||||
|
||||
public static int WriteBeginChunkBytes(ref WritableBuffer start, int dataCount)
|
||||
public static int WriteBeginChunkBytes(ref WritableBufferWriter start, int dataCount)
|
||||
{
|
||||
var chunkSegment = BeginChunkBytes(dataCount);
|
||||
start.WriteFast(chunkSegment);
|
||||
start.Write(chunkSegment.Array, chunkSegment.Offset, chunkSegment.Count);
|
||||
return chunkSegment.Count;
|
||||
}
|
||||
|
||||
public static void WriteEndChunkBytes(ref WritableBuffer start)
|
||||
public static void WriteEndChunkBytes(ref WritableBufferWriter start)
|
||||
{
|
||||
start.WriteFast(_endChunkBytes);
|
||||
start.Write(_endChunkBytes.Array, _endChunkBytes.Offset, _endChunkBytes.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -993,12 +993,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
private static void WriteResponseHeaders(WritableBuffer writableBuffer, Frame frame)
|
||||
{
|
||||
var writer = new WritableBufferWriter(writableBuffer);
|
||||
|
||||
var responseHeaders = frame.FrameResponseHeaders;
|
||||
writableBuffer.WriteFast(_bytesHttpVersion11);
|
||||
writer.Write(_bytesHttpVersion11);
|
||||
var statusBytes = ReasonPhrases.ToStatusBytes(frame.StatusCode, frame.ReasonPhrase);
|
||||
writableBuffer.WriteFast(statusBytes);
|
||||
responseHeaders.CopyTo(ref writableBuffer);
|
||||
writableBuffer.WriteFast(_bytesEndHeaders);
|
||||
writer.Write(statusBytes);
|
||||
responseHeaders.CopyTo(ref writer);
|
||||
writer.Write(_bytesEndHeaders);
|
||||
}
|
||||
|
||||
public void ParseRequest(ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined)
|
||||
|
|
|
|||
|
|
@ -7753,7 +7753,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return true;
|
||||
}
|
||||
|
||||
protected void CopyToFast(ref WritableBuffer output)
|
||||
protected void CopyToFast(ref WritableBufferWriter output)
|
||||
{
|
||||
var tempBits = _bits | (_contentLength.HasValue ? -9223372036854775808L : 0);
|
||||
|
||||
|
|
@ -7761,7 +7761,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
if (_headers._rawConnection != null)
|
||||
{
|
||||
output.WriteFast(_headers._rawConnection);
|
||||
output.Write(_headers._rawConnection);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -7771,8 +7771,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Connection[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 17, 14);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 17, 14);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7787,7 +7787,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
if (_headers._rawDate != null)
|
||||
{
|
||||
output.WriteFast(_headers._rawDate);
|
||||
output.Write(_headers._rawDate);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -7797,8 +7797,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Date[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 31, 8);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 31, 8);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7818,8 +7818,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ContentType[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 133, 16);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 133, 16);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7834,7 +7834,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
if (_headers._rawServer != null)
|
||||
{
|
||||
output.WriteFast(_headers._rawServer);
|
||||
output.Write(_headers._rawServer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -7844,8 +7844,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Server[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 350, 10);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 350, 10);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7858,8 +7858,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
if ((tempBits & -9223372036854775808L) != 0)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 592, 18);
|
||||
output.WriteNumeric((ulong)ContentLength.Value);
|
||||
output.Write(_headerBytes, 592, 18);
|
||||
PipelineExtensions.WriteNumeric(ref output, (ulong)ContentLength.Value);
|
||||
|
||||
if((tempBits & ~-9223372036854775808L) == 0)
|
||||
{
|
||||
|
|
@ -7876,8 +7876,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._CacheControl[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 0, 17);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 0, 17);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7897,8 +7897,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._KeepAlive[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 39, 14);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 39, 14);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7918,8 +7918,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Pragma[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 53, 10);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 53, 10);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7939,8 +7939,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Trailer[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 63, 11);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 63, 11);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7955,7 +7955,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
if (_headers._rawTransferEncoding != null)
|
||||
{
|
||||
output.WriteFast(_headers._rawTransferEncoding);
|
||||
output.Write(_headers._rawTransferEncoding);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -7965,8 +7965,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._TransferEncoding[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 74, 21);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 74, 21);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7986,8 +7986,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Upgrade[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 95, 11);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 95, 11);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8007,8 +8007,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Via[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 106, 7);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 106, 7);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8028,8 +8028,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Warning[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 113, 11);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 113, 11);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8049,8 +8049,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Allow[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 124, 9);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 124, 9);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8070,8 +8070,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ContentEncoding[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 149, 20);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 149, 20);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8091,8 +8091,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ContentLanguage[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 169, 20);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 169, 20);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8112,8 +8112,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ContentLocation[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 189, 20);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 189, 20);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8133,8 +8133,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ContentMD5[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 209, 15);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 209, 15);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8154,8 +8154,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ContentRange[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 224, 17);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 224, 17);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8175,8 +8175,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Expires[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 241, 11);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 241, 11);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8196,8 +8196,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._LastModified[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 252, 17);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 252, 17);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8217,8 +8217,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AcceptRanges[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 269, 17);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 269, 17);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8238,8 +8238,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Age[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 286, 7);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 286, 7);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8259,8 +8259,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ETag[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 293, 8);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 293, 8);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8280,8 +8280,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Location[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 301, 12);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 301, 12);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8301,8 +8301,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._ProxyAuthenticate[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 313, 22);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 313, 22);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8322,8 +8322,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._RetryAfter[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 335, 15);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 335, 15);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8343,8 +8343,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._SetCookie[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 360, 14);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 360, 14);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8364,8 +8364,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._Vary[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 374, 8);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 374, 8);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8385,8 +8385,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._WWWAuthenticate[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 382, 20);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 382, 20);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8406,8 +8406,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AccessControlAllowCredentials[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 402, 36);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 402, 36);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8427,8 +8427,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AccessControlAllowHeaders[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 438, 32);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 438, 32);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8448,8 +8448,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AccessControlAllowMethods[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 470, 32);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 470, 32);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8469,8 +8469,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AccessControlAllowOrigin[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 502, 31);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 502, 31);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8490,8 +8490,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AccessControlExposeHeaders[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 533, 33);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 533, 33);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8511,8 +8511,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._AccessControlMaxAge[i];
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_headerBytes, 566, 26);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, 566, 26);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public void CopyTo(ref WritableBuffer output)
|
||||
public void CopyTo(ref WritableBufferWriter output)
|
||||
{
|
||||
CopyToFast(ref output);
|
||||
if (MaybeUnknown != null)
|
||||
|
|
@ -45,10 +45,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{
|
||||
if (value != null)
|
||||
{
|
||||
output.WriteFast(_CrLf);
|
||||
output.WriteAsciiNoValidation(kv.Key);
|
||||
output.WriteFast(_colonSpace);
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_CrLf);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, kv.Key);
|
||||
output.Write(_colonSpace);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
private readonly IPipeWriter _pipe;
|
||||
private readonly Frame _frame;
|
||||
|
||||
// https://github.com/dotnet/corefxlab/issues/1334
|
||||
// https://github.com/dotnet/corefxlab/issues/1334
|
||||
// Pipelines don't support multiple awaiters on flush
|
||||
// this is temporary until it does
|
||||
private TaskCompletionSource<object> _flushTcs;
|
||||
|
|
@ -59,20 +59,20 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return TaskCache.CompletedTask;
|
||||
}
|
||||
|
||||
writableBuffer = _pipe.Alloc();
|
||||
|
||||
writableBuffer = _pipe.Alloc(1);
|
||||
var writer = new WritableBufferWriter(writableBuffer);
|
||||
if (buffer.Count > 0)
|
||||
{
|
||||
if (chunk)
|
||||
{
|
||||
ChunkWriter.WriteBeginChunkBytes(ref writableBuffer, buffer.Count);
|
||||
ChunkWriter.WriteBeginChunkBytes(ref writer, buffer.Count);
|
||||
}
|
||||
|
||||
writableBuffer.WriteFast(buffer);
|
||||
writer.Write(buffer.Array, buffer.Offset, buffer.Count);
|
||||
|
||||
if (chunk)
|
||||
{
|
||||
ChunkWriter.WriteEndChunkBytes(ref writableBuffer);
|
||||
ChunkWriter.WriteEndChunkBytes(ref writer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
private Task FlushAsyncAwaited(WritableBufferAwaitable awaitable)
|
||||
{
|
||||
// https://github.com/dotnet/corefxlab/issues/1334
|
||||
// https://github.com/dotnet/corefxlab/issues/1334
|
||||
// Since the flush awaitable doesn't currently support multiple awaiters
|
||||
// we need to use a task to track the callbacks.
|
||||
// All awaiters get the same task
|
||||
|
|
@ -157,7 +157,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return;
|
||||
}
|
||||
|
||||
var buffer = _pipe.Alloc();
|
||||
var buffer = _pipe.Alloc(1);
|
||||
callback(buffer, state);
|
||||
buffer.Commit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,98 +95,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return result;
|
||||
}
|
||||
|
||||
// Temporary until the fast write implementation propagates from corefx
|
||||
public unsafe static void WriteFast(this WritableBuffer buffer, byte[] source)
|
||||
{
|
||||
buffer.WriteFast(source, 0, source.Length);
|
||||
}
|
||||
|
||||
public unsafe static void WriteFast(this WritableBuffer buffer, ArraySegment<byte> source)
|
||||
{
|
||||
buffer.WriteFast(source.Array, source.Offset, source.Count);
|
||||
}
|
||||
|
||||
public unsafe static void WriteFast(this WritableBuffer buffer, byte[] source, int offset, int length)
|
||||
{
|
||||
var dest = buffer.Buffer.Span;
|
||||
var destLength = dest.Length;
|
||||
|
||||
if (destLength == 0)
|
||||
{
|
||||
buffer.Ensure();
|
||||
|
||||
// Get the new span and length
|
||||
dest = buffer.Buffer.Span;
|
||||
destLength = dest.Length;
|
||||
}
|
||||
|
||||
var sourceLength = length;
|
||||
if (sourceLength <= destLength)
|
||||
{
|
||||
ref byte pSource = ref source[offset];
|
||||
ref byte pDest = ref dest.DangerousGetPinnableReference();
|
||||
Unsafe.CopyBlockUnaligned(ref pDest, ref pSource, (uint)sourceLength);
|
||||
buffer.Advance(sourceLength);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.WriteMultiBuffer(source, offset, length);
|
||||
}
|
||||
|
||||
private static unsafe void WriteMultiBuffer(this WritableBuffer buffer, byte[] source, int offset, int length)
|
||||
{
|
||||
var remaining = length;
|
||||
|
||||
while (remaining > 0)
|
||||
{
|
||||
var writable = Math.Min(remaining, buffer.Buffer.Length);
|
||||
|
||||
buffer.Ensure(writable);
|
||||
|
||||
if (writable == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ref byte pSource = ref source[offset];
|
||||
ref byte pDest = ref buffer.Buffer.Span.DangerousGetPinnableReference();
|
||||
|
||||
Unsafe.CopyBlockUnaligned(ref pDest, ref pSource, (uint)writable);
|
||||
|
||||
remaining -= writable;
|
||||
offset += writable;
|
||||
|
||||
buffer.Advance(writable);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write string characters as ASCII without validating that characters fall in the ASCII range
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// ASCII character validation is done by <see cref="FrameHeaders.ValidateHeaderCharacters(string)"/>
|
||||
/// </remarks>
|
||||
/// <param name="buffer">the buffer</param>
|
||||
/// <param name="data">The string to write</param>
|
||||
public unsafe static void WriteAsciiNoValidation(this WritableBuffer buffer, string data)
|
||||
public unsafe static void WriteAsciiNoValidation(ref WritableBufferWriter buffer, string data)
|
||||
{
|
||||
if (string.IsNullOrEmpty(data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var dest = buffer.Buffer.Span;
|
||||
var dest = buffer.Span;
|
||||
var destLength = dest.Length;
|
||||
var sourceLength = data.Length;
|
||||
|
||||
if (destLength == 0)
|
||||
{
|
||||
buffer.Ensure();
|
||||
|
||||
dest = buffer.Buffer.Span;
|
||||
destLength = dest.Length;
|
||||
}
|
||||
|
||||
// Fast path, try copying to the available memory directly
|
||||
if (sourceLength <= destLength)
|
||||
{
|
||||
|
|
@ -200,26 +119,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}
|
||||
else
|
||||
{
|
||||
buffer.WriteAsciiMultiWrite(data);
|
||||
WriteAsciiMultiWrite(ref buffer, data);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe static void WriteNumeric(this WritableBuffer buffer, ulong number)
|
||||
public unsafe static void WriteNumeric(ref WritableBufferWriter buffer, ulong number)
|
||||
{
|
||||
const byte AsciiDigitStart = (byte)'0';
|
||||
|
||||
var span = buffer.Buffer.Span;
|
||||
var span = buffer.Span;
|
||||
var bytesLeftInBlock = span.Length;
|
||||
|
||||
if (bytesLeftInBlock == 0)
|
||||
{
|
||||
buffer.Ensure();
|
||||
|
||||
span = buffer.Buffer.Span;
|
||||
bytesLeftInBlock = span.Length;
|
||||
}
|
||||
|
||||
// Fast path, try copying to the available memory directly
|
||||
var simpleWrite = true;
|
||||
fixed (byte* output = &span.DangerousGetPinnableReference())
|
||||
|
|
@ -258,12 +169,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
if (!simpleWrite)
|
||||
{
|
||||
buffer.WriteNumericMultiWrite(number);
|
||||
WriteNumericMultiWrite(ref buffer, number);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static unsafe void WriteNumericMultiWrite(this WritableBuffer buffer, ulong number)
|
||||
private static void WriteNumericMultiWrite(ref WritableBufferWriter buffer, ulong number)
|
||||
{
|
||||
const byte AsciiDigitStart = (byte)'0';
|
||||
|
||||
|
|
@ -280,11 +191,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
while (value != 0);
|
||||
|
||||
var length = _maxULongByteLength - position;
|
||||
buffer.WriteFast(new ArraySegment<byte>(byteBuffer, position, length));
|
||||
buffer.Write(byteBuffer, position, length);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private unsafe static void WriteAsciiMultiWrite(this WritableBuffer buffer, string data)
|
||||
private unsafe static void WriteAsciiMultiWrite(ref WritableBufferWriter buffer, string data)
|
||||
{
|
||||
var remaining = data.Length;
|
||||
|
||||
|
|
@ -294,16 +205,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
|
||||
while (remaining > 0)
|
||||
{
|
||||
var writable = Math.Min(remaining, buffer.Buffer.Length);
|
||||
|
||||
buffer.Ensure(writable);
|
||||
var writable = Math.Min(remaining, buffer.Span.Length);
|
||||
|
||||
if (writable == 0)
|
||||
{
|
||||
buffer.Ensure();
|
||||
continue;
|
||||
}
|
||||
|
||||
fixed (byte* output = &buffer.Buffer.Span.DangerousGetPinnableReference())
|
||||
fixed (byte* output = &buffer.Span.DangerousGetPinnableReference())
|
||||
{
|
||||
EncodeAsciiCharsToBytes(inputSlice, output, writable);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,13 +33,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[InlineData(ulong.MinValue)]
|
||||
[InlineData(ulong.MaxValue)]
|
||||
[InlineData(4_8_15_16_23_42)]
|
||||
public async Task WritesNumericToAscii(ulong number)
|
||||
public void WritesNumericToAscii(ulong number)
|
||||
{
|
||||
var writer = _pipe.Writer.Alloc();
|
||||
writer.WriteNumeric(number);
|
||||
await writer.FlushAsync();
|
||||
var writerBuffer = _pipe.Writer.Alloc();
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
PipelineExtensions.WriteNumeric(ref writer, number);
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
||||
var reader = await _pipe.Reader.ReadAsync();
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
var numAsStr = number.ToString();
|
||||
var expected = Encoding.ASCII.GetBytes(numAsStr);
|
||||
AssertExtensions.Equal(expected, reader.Buffer.Slice(0, numAsStr.Length).ToArray());
|
||||
|
|
@ -51,16 +52,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[InlineData(_ulongMaxValueLength - 1)]
|
||||
public void WritesNumericAcrossSpanBoundaries(int gapSize)
|
||||
{
|
||||
var writer = _pipe.Writer.Alloc(100);
|
||||
var writerBuffer = _pipe.Writer.Alloc(100);
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
// almost fill up the first block
|
||||
var spacer = new Span<byte>(new byte[writer.Buffer.Length - gapSize]);
|
||||
var spacer = new byte[writer.Span.Length - gapSize];
|
||||
writer.Write(spacer);
|
||||
|
||||
var bufferLength = writer.Buffer.Length;
|
||||
writer.WriteNumeric(ulong.MaxValue);
|
||||
Assert.NotEqual(bufferLength, writer.Buffer.Length);
|
||||
var bufferLength = writer.Span.Length;
|
||||
PipelineExtensions.WriteNumeric(ref writer, ulong.MaxValue);
|
||||
Assert.NotEqual(bufferLength, writer.Span.Length);
|
||||
|
||||
writer.FlushAsync().GetAwaiter().GetResult();
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
var numAsString = ulong.MaxValue.ToString();
|
||||
|
|
@ -79,12 +81,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
// null or empty
|
||||
[InlineData("", new byte[0])]
|
||||
[InlineData(null, new byte[0])]
|
||||
public async Task EncodesAsAscii(string input, byte[] expected)
|
||||
public void EncodesAsAscii(string input, byte[] expected)
|
||||
{
|
||||
var writer = _pipe.Writer.Alloc();
|
||||
writer.WriteAsciiNoValidation(input);
|
||||
await writer.FlushAsync();
|
||||
var reader = await _pipe.Reader.ReadAsync();
|
||||
var writerBuffer = _pipe.Writer.Alloc();
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref writer, input);
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
||||
if (expected.Length > 0)
|
||||
{
|
||||
|
|
@ -103,30 +106,32 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
[InlineData("𤭢𐐝")]
|
||||
// non-ascii characters stored in 16 bits
|
||||
[InlineData("ñ٢⛄⛵")]
|
||||
public async Task WriteAsciiNoValidationWritesOnlyOneBytePerChar(string input)
|
||||
public void WriteAsciiNoValidationWritesOnlyOneBytePerChar(string input)
|
||||
{
|
||||
// WriteAscii doesn't validate if characters are in the ASCII range
|
||||
// but it shouldn't produce more than one byte per character
|
||||
var writer = _pipe.Writer.Alloc();
|
||||
writer.WriteAsciiNoValidation(input);
|
||||
await writer.FlushAsync();
|
||||
var reader = await _pipe.Reader.ReadAsync();
|
||||
var writerBuffer = _pipe.Writer.Alloc();
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref writer, input);
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
|
||||
Assert.Equal(input.Length, reader.Buffer.Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WriteAsciiNoValidation()
|
||||
public void WriteAsciiNoValidation()
|
||||
{
|
||||
const byte maxAscii = 0x7f;
|
||||
var writer = _pipe.Writer.Alloc();
|
||||
var writerBuffer = _pipe.Writer.Alloc();
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
for (var i = 0; i < maxAscii; i++)
|
||||
{
|
||||
writer.WriteAsciiNoValidation(new string((char)i, 1));
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref writer, new string((char)i, 1));
|
||||
}
|
||||
await writer.FlushAsync();
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
||||
var reader = await _pipe.Reader.ReadAsync();
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
var data = reader.Buffer.Slice(0, maxAscii).ToArray();
|
||||
for (var i = 0; i < maxAscii; i++)
|
||||
{
|
||||
|
|
@ -147,17 +152,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
|
|||
public void WritesAsciiAcrossBlockBoundaries(int stringLength, int gapSize)
|
||||
{
|
||||
var testString = new string(' ', stringLength);
|
||||
var writer = _pipe.Writer.Alloc(100);
|
||||
var writerBuffer = _pipe.Writer.Alloc(100);
|
||||
var writer = new WritableBufferWriter(writerBuffer);
|
||||
// almost fill up the first block
|
||||
var spacer = new Span<byte>(new byte[writer.Buffer.Length - gapSize]);
|
||||
var spacer = new byte[writer.Span.Length - gapSize];
|
||||
writer.Write(spacer);
|
||||
Assert.Equal(gapSize, writer.Buffer.Span.Length);
|
||||
Assert.Equal(gapSize, writer.Span.Length);
|
||||
|
||||
var bufferLength = writer.Buffer.Length;
|
||||
writer.WriteAsciiNoValidation(testString);
|
||||
Assert.NotEqual(bufferLength, writer.Buffer.Length);
|
||||
var bufferLength = writer.Span.Length;
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref writer, testString);
|
||||
Assert.NotEqual(bufferLength, writer.Span.Length);
|
||||
|
||||
writer.FlushAsync().GetAwaiter().GetResult();
|
||||
writerBuffer.FlushAsync().GetAwaiter().GetResult();
|
||||
|
||||
var reader = _pipe.Reader.ReadAsync().GetAwaiter().GetResult();
|
||||
var written = reader.Buffer.Slice(spacer.Length, stringLength);
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
private void InsertData(byte[] bytes)
|
||||
{
|
||||
var buffer = Pipe.Writer.Alloc(2048);
|
||||
buffer.WriteFast(bytes);
|
||||
buffer.Write(bytes);
|
||||
// There should not be any backpressure and task completes immediately
|
||||
buffer.FlushAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -522,7 +522,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
return true;
|
||||
}}
|
||||
{(loop.ClassName == "FrameResponseHeaders" ? $@"
|
||||
protected void CopyToFast(ref WritableBuffer output)
|
||||
protected void CopyToFast(ref WritableBufferWriter output)
|
||||
{{
|
||||
var tempBits = _bits | (_contentLength.HasValue ? {1L << 63}L : 0);
|
||||
{Each(loop.Headers.Where(header => header.Identifier != "ContentLength").OrderBy(h => !h.PrimaryHeader), header => $@"
|
||||
|
|
@ -530,7 +530,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
{{ {(header.EnhancedSetter == false ? "" : $@"
|
||||
if (_headers._raw{header.Identifier} != null)
|
||||
{{
|
||||
output.WriteFast(_headers._raw{header.Identifier});
|
||||
output.Write(_headers._raw{header.Identifier});
|
||||
}}
|
||||
else ")}
|
||||
{{
|
||||
|
|
@ -540,8 +540,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
var value = _headers._{header.Identifier}[i];
|
||||
if (value != null)
|
||||
{{
|
||||
output.WriteFast(_headerBytes, {header.BytesOffset}, {header.BytesCount});
|
||||
output.WriteAsciiNoValidation(value);
|
||||
output.Write(_headerBytes, {header.BytesOffset}, {header.BytesCount});
|
||||
PipelineExtensions.WriteAsciiNoValidation(ref output, value);
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
|
|
@ -554,8 +554,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
|
|||
}}{(header.Identifier == "Server" ? $@"
|
||||
if ((tempBits & {1L << 63}L) != 0)
|
||||
{{
|
||||
output.WriteFast(_headerBytes, {loop.Headers.First(x => x.Identifier == "ContentLength").BytesOffset}, {loop.Headers.First(x => x.Identifier == "ContentLength").BytesCount});
|
||||
output.WriteNumeric((ulong)ContentLength.Value);
|
||||
output.Write(_headerBytes, {loop.Headers.First(x => x.Identifier == "ContentLength").BytesOffset}, {loop.Headers.First(x => x.Identifier == "ContentLength").BytesCount});
|
||||
PipelineExtensions.WriteNumeric(ref output, (ulong)ContentLength.Value);
|
||||
|
||||
if((tempBits & ~{1L << 63}L) == 0)
|
||||
{{
|
||||
|
|
|
|||
Loading…
Reference in New Issue