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