| File: System\Net\Http\SocketsHttpHandler\ChunkedEncodingWriteStream.cs | Web Access |
| Project: src\runtime\src\libraries\System.Net.Http\src\System.Net.Http.csproj (System.Net.Http) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namespace System.Net.Http { internal sealed partial class HttpConnection : IDisposable { private sealed class ChunkedEncodingWriteStream : HttpContentWriteStream { private static readonly byte[] s_crlfBytes = "\r\n"u8.ToArray(); private static readonly byte[] s_finalChunkBytes = "0\r\n\r\n"u8.ToArray(); public ChunkedEncodingWriteStream(HttpConnection connection) : base(connection) { } public override void Write(ReadOnlySpan<byte> buffer) { BytesWritten += buffer.Length; HttpConnection connection = GetConnectionOrThrow(); Debug.Assert(connection._currentRequest != null); if (buffer.Length == 0) { connection.Flush(); return; } // Write chunk length in hex followed by \r\n ValueTask writeTask = connection.WriteHexInt32Async(buffer.Length, async: false); Debug.Assert(writeTask.IsCompleted); writeTask.GetAwaiter().GetResult(); connection.Write(s_crlfBytes); // Write chunk contents followed by \r\n connection.Write(buffer); connection.Write(s_crlfBytes); } public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken ignored) { BytesWritten += buffer.Length; HttpConnection connection = GetConnectionOrThrow(); Debug.Assert(connection._currentRequest != null); // The token is ignored because it's coming from SendAsync and the only operations // here are those that are already covered by the token having been registered with // to close the connection. ValueTask task = buffer.Length == 0 ? // Don't write if nothing was given, especially since we don't want to accidentally send a 0 chunk, // which would indicate end of body. Instead, just ensure no content is stuck in the buffer. connection.FlushAsync(async: true) : WriteChunkAsync(connection, buffer); return task; static async ValueTask WriteChunkAsync(HttpConnection connection, ReadOnlyMemory<byte> buffer) { // Write chunk length in hex followed by \r\n await connection.WriteHexInt32Async(buffer.Length, async: true).ConfigureAwait(false); await connection.WriteAsync(s_crlfBytes).ConfigureAwait(false); // Write chunk contents followed by \r\n await connection.WriteAsync(buffer).ConfigureAwait(false); await connection.WriteAsync(s_crlfBytes).ConfigureAwait(false); } } public override Task FinishAsync(bool async) { // Send 0 byte chunk to indicate end, then final CrLf HttpConnection connection = GetConnectionOrThrow(); _connection = null; if (async) { return connection.WriteAsync(s_finalChunkBytes).AsTask(); } else { connection.Write(s_finalChunkBytes); return Task.CompletedTask; } } } } }