diff --git a/src/Microsoft.AspNet.Server.Kestrel/Filter/StreamSocketOutput.cs b/src/Microsoft.AspNet.Server.Kestrel/Filter/StreamSocketOutput.cs index d2c1deae3b..cbcb99f3a9 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Filter/StreamSocketOutput.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Filter/StreamSocketOutput.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Filter return new MemoryPoolIterator2(_producingBlock); } - public void ProducingComplete(MemoryPoolIterator2 end, int count) + public void ProducingComplete(MemoryPoolIterator2 end) { var block = _producingBlock; while (block != end.Block) diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs index 008e1a905e..9870a5ab46 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs @@ -674,12 +674,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http _responseHeaders.SetRawConnection("keep-alive", _bytesConnectionKeepAlive); } - count += end.CopyFrom(_httpVersion == HttpVersionType.Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0); - count += end.CopyFrom(statusBytes); - count += _responseHeaders.CopyTo(ref end); - count += end.CopyFrom(_bytesEndHeaders, 0, _bytesEndHeaders.Length); + end.CopyFrom(_httpVersion == HttpVersionType.Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0); + end.CopyFrom(statusBytes); + _responseHeaders.CopyTo(ref end); + end.CopyFrom(_bytesEndHeaders, 0, _bytesEndHeaders.Length); - SocketOutput.ProducingComplete(end, count); + SocketOutput.ProducingComplete(end); if (immediate) { diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/FrameHeaders.Generated.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/FrameHeaders.Generated.cs index bc7f4d0caa..5571e9c56b 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/FrameHeaders.Generated.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/FrameHeaders.Generated.cs @@ -7821,16 +7821,15 @@ namespace Microsoft.AspNet.Server.Kestrel.Http ((ICollection>)MaybeUnknown)?.CopyTo(array, arrayIndex); } - protected int CopyToFast(ref MemoryPoolIterator2 output) + protected void CopyToFast(ref MemoryPoolIterator2 output) { - var count = 0; if (((_bits & 1L) != 0)) { foreach(var value in _CacheControl) { - count += output.CopyFrom(_headerBytes, 0, 17); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 0, 17); + output.CopyFromAscii(value); } } @@ -7838,12 +7837,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { if (_rawConnection != null) { - count += output.CopyFrom(_rawConnection, 0, _rawConnection.Length); + output.CopyFrom(_rawConnection, 0, _rawConnection.Length); } else foreach(var value in _Connection) { - count += output.CopyFrom(_headerBytes, 17, 14); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 17, 14); + output.CopyFromAscii(value); } } @@ -7851,12 +7850,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { if (_rawDate != null) { - count += output.CopyFrom(_rawDate, 0, _rawDate.Length); + output.CopyFrom(_rawDate, 0, _rawDate.Length); } else foreach(var value in _Date) { - count += output.CopyFrom(_headerBytes, 31, 8); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 31, 8); + output.CopyFromAscii(value); } } @@ -7864,8 +7863,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _KeepAlive) { - count += output.CopyFrom(_headerBytes, 39, 14); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 39, 14); + output.CopyFromAscii(value); } } @@ -7873,8 +7872,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Pragma) { - count += output.CopyFrom(_headerBytes, 53, 10); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 53, 10); + output.CopyFromAscii(value); } } @@ -7882,8 +7881,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Trailer) { - count += output.CopyFrom(_headerBytes, 63, 11); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 63, 11); + output.CopyFromAscii(value); } } @@ -7891,12 +7890,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { if (_rawTransferEncoding != null) { - count += output.CopyFrom(_rawTransferEncoding, 0, _rawTransferEncoding.Length); + output.CopyFrom(_rawTransferEncoding, 0, _rawTransferEncoding.Length); } else foreach(var value in _TransferEncoding) { - count += output.CopyFrom(_headerBytes, 74, 21); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 74, 21); + output.CopyFromAscii(value); } } @@ -7904,8 +7903,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Upgrade) { - count += output.CopyFrom(_headerBytes, 95, 11); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 95, 11); + output.CopyFromAscii(value); } } @@ -7913,8 +7912,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Via) { - count += output.CopyFrom(_headerBytes, 106, 7); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 106, 7); + output.CopyFromAscii(value); } } @@ -7922,8 +7921,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Warning) { - count += output.CopyFrom(_headerBytes, 113, 11); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 113, 11); + output.CopyFromAscii(value); } } @@ -7931,8 +7930,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Allow) { - count += output.CopyFrom(_headerBytes, 124, 9); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 124, 9); + output.CopyFromAscii(value); } } @@ -7940,12 +7939,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { if (_rawContentLength != null) { - count += output.CopyFrom(_rawContentLength, 0, _rawContentLength.Length); + output.CopyFrom(_rawContentLength, 0, _rawContentLength.Length); } else foreach(var value in _ContentLength) { - count += output.CopyFrom(_headerBytes, 133, 18); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 133, 18); + output.CopyFromAscii(value); } } @@ -7953,8 +7952,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ContentType) { - count += output.CopyFrom(_headerBytes, 151, 16); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 151, 16); + output.CopyFromAscii(value); } } @@ -7962,8 +7961,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ContentEncoding) { - count += output.CopyFrom(_headerBytes, 167, 20); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 167, 20); + output.CopyFromAscii(value); } } @@ -7971,8 +7970,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ContentLanguage) { - count += output.CopyFrom(_headerBytes, 187, 20); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 187, 20); + output.CopyFromAscii(value); } } @@ -7980,8 +7979,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ContentLocation) { - count += output.CopyFrom(_headerBytes, 207, 20); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 207, 20); + output.CopyFromAscii(value); } } @@ -7989,8 +7988,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ContentMD5) { - count += output.CopyFrom(_headerBytes, 227, 15); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 227, 15); + output.CopyFromAscii(value); } } @@ -7998,8 +7997,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ContentRange) { - count += output.CopyFrom(_headerBytes, 242, 17); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 242, 17); + output.CopyFromAscii(value); } } @@ -8007,8 +8006,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Expires) { - count += output.CopyFrom(_headerBytes, 259, 11); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 259, 11); + output.CopyFromAscii(value); } } @@ -8016,8 +8015,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _LastModified) { - count += output.CopyFrom(_headerBytes, 270, 17); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 270, 17); + output.CopyFromAscii(value); } } @@ -8025,8 +8024,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _AcceptRanges) { - count += output.CopyFrom(_headerBytes, 287, 17); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 287, 17); + output.CopyFromAscii(value); } } @@ -8034,8 +8033,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Age) { - count += output.CopyFrom(_headerBytes, 304, 7); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 304, 7); + output.CopyFromAscii(value); } } @@ -8043,8 +8042,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ETag) { - count += output.CopyFrom(_headerBytes, 311, 8); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 311, 8); + output.CopyFromAscii(value); } } @@ -8052,8 +8051,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Location) { - count += output.CopyFrom(_headerBytes, 319, 12); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 319, 12); + output.CopyFromAscii(value); } } @@ -8061,8 +8060,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _ProxyAutheticate) { - count += output.CopyFrom(_headerBytes, 331, 21); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 331, 21); + output.CopyFromAscii(value); } } @@ -8070,8 +8069,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _RetryAfter) { - count += output.CopyFrom(_headerBytes, 352, 15); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 352, 15); + output.CopyFromAscii(value); } } @@ -8079,12 +8078,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { if (_rawServer != null) { - count += output.CopyFrom(_rawServer, 0, _rawServer.Length); + output.CopyFrom(_rawServer, 0, _rawServer.Length); } else foreach(var value in _Server) { - count += output.CopyFrom(_headerBytes, 367, 10); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 367, 10); + output.CopyFromAscii(value); } } @@ -8092,8 +8091,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _SetCookie) { - count += output.CopyFrom(_headerBytes, 377, 14); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 377, 14); + output.CopyFromAscii(value); } } @@ -8101,8 +8100,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _Vary) { - count += output.CopyFrom(_headerBytes, 391, 8); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 391, 8); + output.CopyFromAscii(value); } } @@ -8110,12 +8109,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { foreach(var value in _WWWAuthenticate) { - count += output.CopyFrom(_headerBytes, 399, 20); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, 399, 20); + output.CopyFromAscii(value); } } - return count; } public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string value) { diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/FrameResponseHeaders.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/FrameResponseHeaders.cs index 30c75fe4e2..693c58e912 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/FrameResponseHeaders.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/FrameResponseHeaders.cs @@ -30,23 +30,22 @@ namespace Microsoft.AspNet.Server.Kestrel.Http return GetEnumerator(); } - public int CopyTo(ref MemoryPoolIterator2 output) + public void CopyTo(ref MemoryPoolIterator2 output) { - var count = CopyToFast(ref output); + CopyToFast(ref output); if (MaybeUnknown != null) { foreach (var kv in MaybeUnknown) { foreach (var value in kv.Value) { - count += output.CopyFrom(_CrLf, 0, 2); - count += output.CopyFromAscii(kv.Key); - count += output.CopyFrom(_colonSpace, 0, 2); - count += output.CopyFromAscii(value); + output.CopyFrom(_CrLf, 0, 2); + output.CopyFromAscii(kv.Key); + output.CopyFrom(_colonSpace, 0, 2); + output.CopyFromAscii(value); } } } - return count; } public partial struct Enumerator : IEnumerator> diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/ISocketOutput.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/ISocketOutput.cs index 1ec17d269b..597326ca82 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/ISocketOutput.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/ISocketOutput.cs @@ -30,7 +30,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Http /// or is called afterwards. /// /// Points to the end of the committed data. - /// The number of bytes added to the response. - void ProducingComplete(MemoryPoolIterator2 end, int count); + void ProducingComplete(MemoryPoolIterator2 end); } } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs index 64c5808efb..82242f039a 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/SocketOutput.cs @@ -19,6 +19,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http private const int _initialTaskQueues = 64; private static WaitCallback _returnBlocks = (state) => ReturnBlocks((MemoryPoolBlock2)state); + private static MemoryPoolIterator2 _defaultIterator; private readonly KestrelThread _thread; private readonly UvStreamHandle _socket; @@ -34,8 +35,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http private MemoryPoolBlock2 _head; private MemoryPoolBlock2 _tail; - private bool _isProducing; - private MemoryPoolBlock2 _returnFromOnProducingComplete; + private MemoryPoolIterator2 _lastStart; // This locks access to to all of the below fields private readonly object _contextLock = new object(); @@ -83,7 +83,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http var tail = ProducingStart(); tail.CopyFrom(buffer); // We do our own accounting below - ProducingComplete(tail, count: 0); + ProducingCompleteNoPreComplete(tail); } TaskCompletionSource tcs = null; @@ -165,54 +165,57 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { lock (_returnLock) { - Debug.Assert(!_isProducing); - _isProducing = true; + Debug.Assert(_lastStart.IsDefault); if (_tail == null) { throw new IOException("The socket has been closed."); } - return new MemoryPoolIterator2(_tail, _tail.End); + _lastStart = new MemoryPoolIterator2(_tail, _tail.End); + + return _lastStart; } } - public void ProducingComplete(MemoryPoolIterator2 end, int count) + public void ProducingComplete(MemoryPoolIterator2 end) + { + Debug.Assert(!_lastStart.IsDefault); + + int bytesProduced, buffersIncluded; + BytesBetween(_lastStart, end, out bytesProduced, out buffersIncluded); + + lock (_contextLock) + { + _numBytesPreCompleted += bytesProduced; + } + + ProducingCompleteNoPreComplete(end); + } + + private void ProducingCompleteNoPreComplete(MemoryPoolIterator2 end) { - var decreasePreCompleted = false; MemoryPoolBlock2 blockToReturn = null; lock (_returnLock) { - Debug.Assert(_isProducing); - _isProducing = false; + Debug.Assert(!_lastStart.IsDefault); - if (_returnFromOnProducingComplete == null) + // If the socket has been closed, return the produced blocks + // instead of advancing the now non-existent tail. + if (_tail != null) { _tail = end.Block; _tail.End = end.Index; - - if (count != 0) - { - decreasePreCompleted = true; - } } else { - blockToReturn = _returnFromOnProducingComplete; - _returnFromOnProducingComplete = null; + blockToReturn = _lastStart.Block; } - } - if (decreasePreCompleted) - { - lock (_contextLock) - { - _numBytesPreCompleted += count; - } + _lastStart = _defaultIterator; } - if (blockToReturn != null) { ThreadPool.QueueUserWorkItem(_returnBlocks, blockToReturn); @@ -354,11 +357,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http returnBlock.Pool?.Return(returnBlock); } - if (_isProducing) - { - _returnFromOnProducingComplete = _tail; - } - else + // Only return the _tail if we aren't between ProducingStart/Complete calls + if (_lastStart.IsDefault) { _tail.Pool?.Return(_tail); } @@ -387,6 +387,28 @@ namespace Microsoft.AspNet.Server.Kestrel.Http return WriteAsync(buffer, immediate); } + private static void BytesBetween(MemoryPoolIterator2 start, MemoryPoolIterator2 end, out int bytes, out int buffers) + { + if (start.Block == end.Block) + { + bytes = end.Index - start.Index; + buffers = 1; + return; + } + + bytes = start.Block.Data.Offset + start.Block.Data.Count - start.Index; + buffers = 1; + + for (var block = start.Block.Next; block != end.Block; block = block.Next) + { + bytes += block.Data.Count; + buffers++; + } + + bytes += end.Index - end.Block.Data.Offset; + buffers++; + } + private class WriteContext { private static WaitCallback _returnWrittenBlocks = (state) => ReturnWrittenBlocks((MemoryPoolBlock2)state); @@ -535,24 +557,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http _lockedStart = new MemoryPoolIterator2(head, head.Start); _lockedEnd = new MemoryPoolIterator2(tail, tail.End); - if (_lockedStart.Block == _lockedEnd.Block) - { - _byteCount = _lockedEnd.Index - _lockedStart.Index; - _bufferCount = 1; - return; - } - - _byteCount = _lockedStart.Block.Data.Offset + _lockedStart.Block.Data.Count - _lockedStart.Index; - _bufferCount = 1; - - for (var block = _lockedStart.Block.Next; block != _lockedEnd.Block; block = block.Next) - { - _byteCount += block.Data.Count; - _bufferCount++; - } - - _byteCount += _lockedEnd.Index - _lockedEnd.Block.Data.Offset; - _bufferCount++; + BytesBetween(_lockedStart, _lockedEnd, out _byteCount, out _bufferCount); } } } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs index 9af9d4428e..41551d056c 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs @@ -532,17 +532,17 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure } } - public int CopyFrom(byte[] data) + public void CopyFrom(byte[] data) { - return CopyFrom(new ArraySegment(data)); + CopyFrom(new ArraySegment(data)); } - public int CopyFrom(byte[] data, int offset, int count) + public void CopyFrom(byte[] data, int offset, int count) { - return CopyFrom(new ArraySegment(data, offset, count)); + CopyFrom(new ArraySegment(data, offset, count)); } - public int CopyFrom(ArraySegment buffer) + public void CopyFrom(ArraySegment buffer) { Debug.Assert(_block != null); Debug.Assert(_block.Pool != null); @@ -582,11 +582,9 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure _block = block; _index = blockIndex; - - return buffer.Count; } - public unsafe int CopyFromAscii(string data) + public unsafe void CopyFromAscii(string data) { Debug.Assert(_block != null); Debug.Assert(_block.Pool != null); @@ -649,8 +647,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure _block = block; _index = blockIndex; - - return length; } } } diff --git a/test/Microsoft.AspNet.Server.KestrelTests/SocketOutputTests.cs b/test/Microsoft.AspNet.Server.KestrelTests/SocketOutputTests.cs index dca77cf881..d5f86b76aa 100644 --- a/test/Microsoft.AspNet.Server.KestrelTests/SocketOutputTests.cs +++ b/test/Microsoft.AspNet.Server.KestrelTests/SocketOutputTests.cs @@ -309,17 +309,15 @@ namespace Microsoft.AspNet.Server.KestrelTests // block 1 var start = socketOutput.ProducingStart(); start.Block.End = start.Block.Data.Offset + start.Block.Data.Count; - var totalBytes = start.Block.Data.Count; // block 2 var block2 = memory.Lease(); block2.End = block2.Data.Offset + block2.Data.Count; start.Block.Next = block2; - totalBytes += block2.Data.Count; var end = new MemoryPoolIterator2(block2, block2.End); - socketOutput.ProducingComplete(end, totalBytes); + socketOutput.ProducingComplete(end); // A call to Write is required to ensure a write is scheduled socketOutput.WriteAsync(default(ArraySegment)); diff --git a/tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode/KnownHeaders.cs b/tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode/KnownHeaders.cs index 214cf91f6b..aaf19e8300 100644 --- a/tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode/KnownHeaders.cs +++ b/tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode/KnownHeaders.cs @@ -380,24 +380,22 @@ namespace Microsoft.AspNet.Server.Kestrel.Http ((ICollection>)MaybeUnknown)?.CopyTo(array, arrayIndex); }} {(loop.ClassName == "FrameResponseHeaders" ? $@" - protected int CopyToFast(ref MemoryPoolIterator2 output) + protected void CopyToFast(ref MemoryPoolIterator2 output) {{ - var count = 0; {Each(loop.Headers, header => $@" if ({header.TestBit()}) {{ {(header.EnhancedSetter == false ? "" : $@" if (_raw{header.Identifier} != null) {{ - count += output.CopyFrom(_raw{header.Identifier}, 0, _raw{header.Identifier}.Length); + output.CopyFrom(_raw{header.Identifier}, 0, _raw{header.Identifier}.Length); }} else ")} foreach(var value in _{header.Identifier}) {{ - count += output.CopyFrom(_headerBytes, {header.BytesOffset}, {header.BytesCount}); - count += output.CopyFromAscii(value); + output.CopyFrom(_headerBytes, {header.BytesOffset}, {header.BytesCount}); + output.CopyFromAscii(value); }} }} ")} - return count; }}" : "")} public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string value) {{