// Must be called with _writeLock private void Append(ArraySegment <byte> data) { if (_completed) { return; } var writeableBuffer = _outputWriter.Alloc(1); writeableBuffer.Write(data); writeableBuffer.Commit(); }
public void Write <T>(Action <WritableBuffer, T> callback, T state) { lock (_contextLock) { if (_completed) { return; } var buffer = _pipeWriter.Alloc(1); callback(buffer, state); buffer.Commit(); } }
public static Task WriteAsync(this IPipeWriter output, ArraySegment <byte> source) { var writeBuffer = output.Alloc(); writeBuffer.Write(source); return(FlushAsync(writeBuffer)); }
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { var output = _writer.Alloc(); output.Write(new Span <byte>(buffer, offset, count)); await output.FlushAsync(); }
public static async void Echo(IPipeReader input, IPipeWriter output) { try { while (true) { var result = await input.ReadAsync(); var request = result.Buffer; if (request.IsEmpty && result.IsCompleted) { input.Advance(request.End); break; } int len = request.Length; var response = output.Alloc(); response.Append(request); await response.FlushAsync(); input.Advance(request.End); } } catch { input.Complete(); output.Complete(); } }
public static async Task CopyToAsync(this IPipeReader input, IPipeWriter output) { while (true) { var result = await input.ReadAsync(); var inputBuffer = result.Buffer; var fin = result.IsCompleted; try { if (inputBuffer.IsEmpty && fin) { return; } var buffer = output.Alloc(); buffer.Append(inputBuffer); await buffer.FlushAsync(); } finally { input.Advance(inputBuffer.End); } } }
public static Task WriteAsync(this IPipeWriter output, Span <byte> source) { var writeBuffer = output.Alloc(); writeBuffer.Write(source); return(AwaitFlushAsync(writeBuffer)); }
public static async Task WriteAsync(this IPipeWriter output, Span <byte> source) { var writeBuffer = output.Alloc(); writeBuffer.Write(source); await writeBuffer.FlushAsync(); }
private async Task EndResponse() { var buffer = _output.Alloc(); if (!HasStarted) { WriteBeginResponseHeaders(buffer); } if (_autoChunk) { WriteEndResponse(buffer); } await buffer.FlushAsync(); }
public static async Task CopyToAsync(this IPipeReader input, IPipeWriter output) { while (true) { var result = await input.ReadAsync(); var inputBuffer = result.Buffer; try { if (inputBuffer.IsEmpty && result.IsCompleted) { return; } var buffer = output.Alloc(); foreach (var memory in inputBuffer) { buffer.Write(memory.Span); } await buffer.FlushAsync(); } finally { input.Advance(inputBuffer.End); } } }
public async Task Execute(IPipeReader reader, IPipeWriter writer) { List <MemoryHandle> handles = new List <MemoryHandle>(); while (true) { var result = await reader.ReadAsync(); var inputBuffer = result.Buffer; if (inputBuffer.IsEmpty) { if (result.IsCompleted) { break; } reader.Advance(inputBuffer.End); continue; } var writerBuffer = writer.Alloc(); var buffer = inputBuffer.First; if (buffer.Length > 0) { unsafe { var handle = buffer.Retain(pin: true); handles.Add(handle); _inflater.SetInput((IntPtr)handle.PinnedPointer, buffer.Length); writerBuffer.Ensure(); handle = writerBuffer.Buffer.Retain(pin: true); handles.Add(handle); int written = _inflater.Inflate((IntPtr)handle.PinnedPointer, writerBuffer.Buffer.Length); writerBuffer.Advance(written); var consumed = buffer.Length - _inflater.AvailableInput; inputBuffer = inputBuffer.Slice(0, consumed); } } reader.Advance(inputBuffer.End); await writerBuffer.FlushAsync(); } reader.Complete(); writer.Complete(); _inflater.Dispose(); foreach (var handle in handles) { handle.Dispose(); } }
private void EnsureBuffer() { if (_needAlloc) { _writableBuffer = _writer.Alloc(); _needAlloc = false; } }
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken token) { var output = _output.Alloc(); if (buffer != null) { output.Write(new ArraySegment <byte>(buffer, offset, count)); } await output.FlushAsync(token); }
public void WriteRecords(IPipeReader pipeReader, RecordType recordType) { lock (_connectionOutputLock) { if (!pipeReader.TryRead(out var reader)) { return; } var buffer = reader.Buffer; var output = _output.Alloc(); try { WriteRecords(ref buffer, ref output, recordType); } finally { pipeReader.Advance(buffer.End); } output.Commit(); } }
private static async Task WriteSimpleMessage(IPipeWriter output, string command) { // keep things simple: using the text protocol guarantees a text-protocol response // (in real code we'd use the RESP format, but ... meh) await Console.Out.WriteLineAsync($">> sending '{command}'..."); var buffer = output.Alloc(); var arr = Encoding.ASCII.GetBytes($"{command}\r\n"); // there's a nice way to do this; I've forgotten buffer.Write(arr); await buffer.FlushAsync(); }
private static async Task WriteSimpleMessage(IPipeWriter output, string command) { // keep things simple: using the text protocol guarantees a text-protocol response // (in real code we'd use the RESP format, but ... meh) var msg = (!ShowDetails && command.StartsWith("AUTH", StringComparison.OrdinalIgnoreCase)) ? "AUTH ****" : command; await Console.Out.WriteLineAsync($">> sending '{msg}'..."); var buffer = output.Alloc(); buffer.WriteUtf8(command.AsReadOnlySpan()); buffer.Ensure(CRLF.Length); buffer.Write(CRLF); buffer.Commit(); await buffer.FlushAsync(); }
public static Task WriteAsync(this IPipeWriter output, ReadOnlyMemory <byte> source) { var writeBuffer = output.Alloc(); writeBuffer.Write(source.Span); var awaitable = writeBuffer.FlushAsync(); if (awaitable.IsCompleted) { awaitable.GetResult(); return(_completedTask); } return(FlushAsyncAwaited(awaitable)); }
internal WritableBufferAwaitable WriteAsync(IPipeWriter output) { var write = output.Alloc(); if (_buffers != null) { foreach (var buffer in _buffers) { write.Append(buffer.Buffer); } } else { ApplyMask(); write.Append(_buffer); } return(write.FlushAsync()); }
private async Task CopyCompletedAsync(IPipeReader input, IPipeWriter output) { var result = await input.ReadAsync(); var inputBuffer = result.Buffer; while (true) { try { if (inputBuffer.IsEmpty && result.IsCompleted) { return; } var buffer = output.Alloc(); foreach (var memory in inputBuffer) { buffer.Write(memory.Span); } await buffer.FlushAsync(); } finally { input.Advance(inputBuffer.End); } var awaiter = input.ReadAsync(); if (!awaiter.IsCompleted) { // No more data break; } result = await input.ReadAsync(); inputBuffer = result.Buffer; } }
private static async Task CopyCompletedAsync(IPipeReader input, IPipeWriter output) { var result = await input.ReadAsync(); var inputBuffer = result.Buffer; while (true) { try { if (inputBuffer.IsEmpty && result.IsCompleted) { return; } var buffer = output.Alloc(); buffer.Append(inputBuffer); await buffer.FlushAsync(); } finally { input.Advance(inputBuffer.End); } var awaiter = input.ReadAsync(); if (!awaiter.IsCompleted) { // No more data break; } result = await input.ReadAsync(); inputBuffer = result.Buffer; } }
public async Task Execute(IPipeReader reader, IPipeWriter writer) { while (true) { var result = await reader.ReadAsync(); var inputBuffer = result.Buffer; if (inputBuffer.IsEmpty) { if (result.IsCompleted) { break; } reader.Advance(inputBuffer.End); continue; } var writerBuffer = writer.Alloc(); var memory = inputBuffer.First; if (memory.Length > 0) { unsafe { void *pointer; if (memory.TryGetPointer(out pointer)) { _inflater.SetInput((IntPtr)pointer, memory.Length); void *writePointer; writerBuffer.Ensure(); if (writerBuffer.Memory.TryGetPointer(out writePointer)) { int written = _inflater.Inflate((IntPtr)writePointer, writerBuffer.Memory.Length); writerBuffer.Advance(written); } else { throw new InvalidOperationException("Pointer needs to be pinned"); } } else { throw new InvalidOperationException("Pointer needs to be pinned"); } var consumed = memory.Length - _inflater.AvailableInput; inputBuffer = inputBuffer.Slice(0, consumed); } } reader.Advance(inputBuffer.End); await writerBuffer.FlushAsync(); } reader.Complete(); writer.Complete(); _inflater.Dispose(); }
public async Task Execute(IPipeReader reader, IPipeWriter writer) { while (true) { var result = await reader.ReadAsync(); var inputBuffer = result.Buffer; if (inputBuffer.IsEmpty) { if (result.IsCompleted) { break; } reader.Advance(inputBuffer.End); continue; } var writerBuffer = writer.Alloc(); var memory = inputBuffer.First; unsafe { // TODO: Pin pointer if not pinned void *inPointer; if (memory.TryGetPointer(out inPointer)) { _deflater.SetInput((IntPtr)inPointer, memory.Length); } else { throw new InvalidOperationException("Pointer needs to be pinned"); } } while (!_deflater.NeedsInput()) { unsafe { void *outPointer; writerBuffer.Ensure(); if (writerBuffer.Memory.TryGetPointer(out outPointer)) { int written = _deflater.ReadDeflateOutput((IntPtr)outPointer, writerBuffer.Memory.Length); writerBuffer.Advance(written); } else { throw new InvalidOperationException("Pointer needs to be pinned"); } } } var consumed = memory.Length - _deflater.AvailableInput; inputBuffer = inputBuffer.Slice(0, consumed); reader.Advance(inputBuffer.End); await writerBuffer.FlushAsync(); } bool flushed = false; do { // Need to do more stuff here var writerBuffer = writer.Alloc(); unsafe { void *pointer; writerBuffer.Ensure(); var memory = writerBuffer.Memory; if (memory.TryGetPointer(out pointer)) { int compressedBytes; flushed = _deflater.Flush((IntPtr)pointer, memory.Length, out compressedBytes); writerBuffer.Advance(compressedBytes); } else { throw new InvalidOperationException("Pointer needs to be pinned"); } } await writerBuffer.FlushAsync(); }while (flushed); bool finished = false; do { // Need to do more stuff here var writerBuffer = writer.Alloc(); unsafe { void *pointer; writerBuffer.Ensure(); var memory = writerBuffer.Memory; if (memory.TryGetPointer(out pointer)) { int compressedBytes; finished = _deflater.Finish((IntPtr)pointer, memory.Length, out compressedBytes); writerBuffer.Advance(compressedBytes); } } await writerBuffer.FlushAsync(); }while (!finished); reader.Complete(); writer.Complete(); _deflater.Dispose(); }
private async Task DoReceive() { Exception error = null; try { while (true) { // Ensure we have some reasonable amount of buffer space var buffer = _input.Alloc(MinAllocBufferSize); try { var bytesReceived = await _socket.ReceiveAsync(GetArraySegment(buffer.Buffer), SocketFlags.None); if (bytesReceived == 0) { // FIN break; } buffer.Advance(bytesReceived); } finally { buffer.Commit(); } var result = await buffer.FlushAsync(); if (result.IsCompleted) { // Pipe consumer is shut down, do we stop writing break; } } } catch (SocketException ex) when(ex.SocketErrorCode == SocketError.ConnectionReset) { error = new ConnectionResetException(ex.Message, ex); } catch (SocketException ex) when(ex.SocketErrorCode == SocketError.OperationAborted) { error = new ConnectionAbortedException(); } catch (ObjectDisposedException) { error = new ConnectionAbortedException(); } catch (IOException ex) { error = ex; } catch (Exception ex) { error = new IOException(ex.Message, ex); } finally { _connectionContext.Abort(error); _input.Complete(error); } }
private static async void ReadFromSocket(TSocket tsocket, IPipeWriter writer, bool dataMayBeAvailable) { Exception error = null; try { var availableBytes = dataMayBeAvailable ? tsocket.Socket.GetAvailableBytes() : 0; bool readable0 = true; if (availableBytes == 0 && (readable0 = await Readable(tsocket))) // Readable { availableBytes = tsocket.Socket.GetAvailableBytes(); } else if (!readable0) { error = new ConnectionAbortedException(); } while (availableBytes != 0) { var buffer = writer.Alloc(2048); try { error = Receive(tsocket.Fd, availableBytes, ref buffer); if (error != null) { break; } availableBytes = 0; var flushResult = await buffer.FlushAsync(); bool readable = true; if (!flushResult.IsCompleted && // Reader hasn't stopped !flushResult.IsCancelled && // TransportThread hasn't stopped (readable = await Readable(tsocket))) // Readable { availableBytes = tsocket.Socket.GetAvailableBytes(); } else if (flushResult.IsCancelled || !readable) { error = new ConnectionAbortedException(); } } catch (Exception e) { availableBytes = 0; buffer.Commit(); error = e; } } } catch (Exception ex) { error = ex; } finally { // even when error == null, we call Abort // this mean receiving FIN causes Abort // rationale: https://github.com/aspnet/KestrelHttpServer/issues/1139#issuecomment-251748845 tsocket.ConnectionContext.Abort(error); writer.Complete(error); CleanupSocketEnd(tsocket); } }
public async Task Execute(IPipeReader reader, IPipeWriter writer) { List <MemoryHandle> handles = new List <MemoryHandle>(); while (true) { var result = await reader.ReadAsync(); var inputBuffer = result.Buffer; if (inputBuffer.IsEmpty) { if (result.IsCompleted) { break; } reader.Advance(inputBuffer.End); continue; } var writerBuffer = writer.Alloc(); var buffer = inputBuffer.First; unsafe { var handle = buffer.Retain(pin: true); handles.Add(handle); _deflater.SetInput((IntPtr)handle.PinnedPointer, buffer.Length); } while (!_deflater.NeedsInput()) { unsafe { writerBuffer.Ensure(); var handle = writerBuffer.Buffer.Retain(pin: true); handles.Add(handle); int written = _deflater.ReadDeflateOutput((IntPtr)handle.PinnedPointer, writerBuffer.Buffer.Length); writerBuffer.Advance(written); } } var consumed = buffer.Length - _deflater.AvailableInput; inputBuffer = inputBuffer.Slice(0, consumed); reader.Advance(inputBuffer.End); await writerBuffer.FlushAsync(); } bool flushed = false; do { // Need to do more stuff here var writerBuffer = writer.Alloc(); unsafe { writerBuffer.Ensure(); var memory = writerBuffer.Buffer; var handle = memory.Retain(pin: true); handles.Add(handle); int compressedBytes; flushed = _deflater.Flush((IntPtr)handle.PinnedPointer, memory.Length, out compressedBytes); writerBuffer.Advance(compressedBytes); } await writerBuffer.FlushAsync(); }while (flushed); bool finished = false; do { // Need to do more stuff here var writerBuffer = writer.Alloc(); unsafe { writerBuffer.Ensure(); var memory = writerBuffer.Buffer; var handle = memory.Retain(pin: true); handles.Add(handle); int compressedBytes; finished = _deflater.Finish((IntPtr)handle.PinnedPointer, memory.Length, out compressedBytes); writerBuffer.Advance(compressedBytes); } await writerBuffer.FlushAsync(); }while (!finished); reader.Complete(); writer.Complete(); _deflater.Dispose(); foreach (var handle in handles) { handle.Dispose(); } }