public void Abort(Exception error) { // Abort can be called after Dispose if there's a flush timeout. // It's important to still call _lifetimeFeature.Abort() in this case. lock (_contextLock) { if (_aborted) { return; } if (!_completed) { _log.ConnectionDisconnect(_connectionId); _completed = true; _outputPipeReader.CancelPendingRead(); _pipeWriter.Complete(error); } _aborted = true; _lifetimeFeature.Abort(); } }
private static async ValueTask <string> ReadHttpHeadersAsync(PipeReader reader, CancellationToken cancellationToken = default) { while (true) { ReadResult result = await reader.ReadAsync(cancellationToken); ReadOnlySequence <byte> buffer = result.Buffer; try { if (TryReadHeaders(ref buffer, out string?headers)) { if (!buffer.IsEmpty) { reader.CancelPendingRead(); } return(headers); } if (result.IsCompleted) { break; } } finally { reader.AdvanceTo(buffer.Start, buffer.End); } } throw new InvalidDataException(@"Cannot read HTTP headers."); }
public void StartUnwrapRead() { // Upon sending the session end byte, the client can start another session immediately. // We need to stop those bytes from being consumed by the upgrade stream (e.g. NegotiateStream), // but we can't return a zero byte response to the pending read until after we've sent the session // end byte otherwise it will close the upgrade stream and prevent the session end byte from being // sent. Calling StartUnwrapRead prevents any reads from completing until FinisheUnwrapRead has // been called. This ensures any client bytes from the next session are not consumed and still // allows a write to be sent through the wrapping stream. bool acquired = _readSemaphore.Wait(0); try { lock (_thisLock) { _unwrapTcs = new TaskCompletionSource <object>(); _canRead = false; } _input.CancelPendingRead(); } finally { if (acquired) { _readSemaphore.Release(); } } }
private async Task ReadPipeAsync(PipeReader reader, CancellationToken cancellationToken = default) { while (true) { if (cancellationToken.IsCancellationRequested) { reader.CancelPendingRead(); await reader.CompleteAsync(); break; } bool isAny = reader.TryRead(out ReadResult result); if (!isAny) { continue; } ReadOnlySequence <byte> buffer = result.Buffer; // In the event that no message is parsed successfully, mark consumed // as nothing and examined as the entire buffer. SequencePosition consumed = buffer.Start; SequencePosition examined = buffer.End; try { if (parser.TryParse(ref buffer, out Message message, out int bConsumed, GetName())) { // A single message was successfully parsed so mark the start as the // parsed buffer as consumed. TryParseMessage trims the buffer to // point to the data after the message was parsed. consumed = buffer.GetPosition(bConsumed); // Examined is marked the same as consumed here, so the next call // to ReadSingleMessageAsync will process the next message if there's // one. examined = consumed; Console.WriteLine(); if (!(message is null)) { foreach (var observer in observers) { observer.OnNext(message); } } } } catch (Exception e) { Console.WriteLine(e); foreach (var observer in observers) { observer.OnError(e); } } finally { reader.AdvanceTo(consumed, examined); } } }
private async Task SendResponse(PipeReader reader, CancellationToken cancellation) { while (true) { if (cancellation.IsCancellationRequested) { reader.CancelPendingRead(); break; } var result = await reader.ReadAsync(cancellation); if (result.IsCanceled) { break; } var buffer = result.Buffer; if (buffer.Length <= 0) { break; } byte[] fillBufferBytes = null; try { if (!MemoryMarshal.TryGetArray(buffer.First, out ArraySegment <byte> fillBuffer)) { fillBufferBytes = ArrayPool <byte> .Shared.Rent((int)buffer.Length); fillBuffer = new ArraySegment <byte>(fillBufferBytes); } await socket.SendAsync(fillBuffer, SocketFlags.None); if (result.IsCompleted) { break; } } finally { if (fillBufferBytes != null) { ArrayPool <byte> .Shared.Return(fillBufferBytes); } } reader.AdvanceTo(buffer.Start, buffer.End); } reader.Complete(); }
public async Task <byte[]> ResolveAsync(byte[] Request) { if (!TcpClient.Connected || !SslStream.CanWrite) { await InitializeAsync(); } var Length = BitConverter.GetBytes((ushort)Request.Length); Array.Reverse(Length); await PipeWriter.WriteAsync(Length); await PipeWriter.WriteAsync(Request); PipeWriter.Complete(); var Task = PipeReader.ReadAsync().AsTask(); Task.Wait(Options.CurrentValue.Timeout); if (Task.IsCompleted) { var Result = Task.Result; PipeReader.Complete(); var Buffer = Result.Buffer.Length > 14 ? Result.Buffer.Slice(2) : throw new OperationCanceledException(); return(Buffer.ToArray()); } else { PipeReader.CancelPendingRead(); PipeReader.Complete(); throw new TimeoutException(); } }
public void TryReadAfterCancelPendingReadReturnsTrue() { PipeReader reader = PipeReader.Create(Stream.Null); reader.CancelPendingRead(); Assert.True(reader.TryRead(out ReadResult result)); Assert.True(result.IsCanceled); reader.AdvanceTo(result.Buffer.End); reader.Complete(); }
protected override void Dispose(bool disposing) { if (!disposing) { return; } _reader.CancelPendingRead(); _reader.Complete(); _networkStream.Dispose(); }
public void TryReadAfterCancelPendingReadReturnsTrue() { PipeReader reader = PipeReader.Create(ReadOnlySequence <byte> .Empty); reader.CancelPendingRead(); Assert.True(reader.TryRead(out ReadResult result)); Assert.True(result.IsCanceled); reader.AdvanceTo(result.Buffer.End); reader.Complete(); }
public static async Task CopyToUntilCanceledOrCompletedAsync(this PipeReader reader, PipeWriter writer, CancellationToken cancel) { using var cancelRegistration = cancel.Register(delegate { // If we get canceled, indicate operation cancellation on both pipes to break out of the loop. // The purpose of this here is to avoid throwing exceptions for cancellation, instead using the graceful signal. // Just because exceptions cost extra CPU time that we want to avoid when handling load spikes (such as mass disconnects). reader.CancelPendingRead(); writer.CancelPendingFlush(); }); // We copy until we encounter either a read cancellation (upstream reached end of stream) or a write // completion (downstream reached end of stream) or a write cancellation (downstream requested graceful stop). while (true) { var readResult = await reader.ReadAsync(CancellationToken.None); if (readResult.IsCanceled) { break; } try { if (!readResult.Buffer.IsEmpty) { foreach (var segment in readResult.Buffer) { var memory = writer.GetMemory(segment.Length); segment.CopyTo(memory); writer.Advance(segment.Length); } var flushResult = await writer.FlushAsync(CancellationToken.None); if (flushResult.IsCanceled || flushResult.IsCompleted) { break; } } if (readResult.IsCompleted) { break; } } finally { reader.AdvanceTo(readResult.Buffer.End); } } }
public static void CancelPendingReadEvenIfClosed(this PipeReader reader) { // CancelPendingRead() will throw if the pipe is already closed. // This behavior is not useful to us, so eat the exception. try { reader.CancelPendingRead(); } catch { } }
public void Abort(Exception ex) { lock (_writeLock) { if (_completed) { return; } _completed = true; _outputReader.CancelPendingRead(); _outputWriter.Complete(ex); } }
public void Abort(Exception error) { lock (_contextLock) { if (_completed) { return; } _log.ConnectionDisconnect(_connectionId); _completed = true; _outputPipeReader.CancelPendingRead(); _pipeWriter.Complete(error); } }
public void Stop() { lock (_dataWriterLock) { if (_streamCompleted) { return; } _streamCompleted = true; _pipeReader.CancelPendingRead(); _frameWriter.AbortPendingStreamDataWrites(_flowControl); } }
public async Task ReadCanBeCanceledViaCancelPendingReadWhenReadAtLeastAsync(bool useZeroByteReads) { var stream = new CancelledReadsStream(); PipeReader reader = PipeReader.Create(stream, new StreamPipeReaderOptions(useZeroByteReads: useZeroByteReads)); ValueTask <ReadResult> task = reader.ReadAtLeastAsync(1); reader.CancelPendingRead(); stream.WaitForReadTask.TrySetResult(null); ReadResult readResult = await task; Assert.True(readResult.IsCanceled); reader.Complete(); }
public async Task ReadCanBeCanceledViaCancelPendingReadWhenReadIsAsync() { var stream = new CancelledReadsStream(); PipeReader reader = PipeReader.Create(stream); ValueTask <ReadResult> task = reader.ReadAsync(); reader.CancelPendingRead(); stream.WaitForReadTask.TrySetResult(null); ReadResult readResult = await task; Assert.True(readResult.IsCanceled); reader.Complete(); }
public async Task ReadAsyncReturnsCanceledIfCanceledBeforeRead() { var stream = new MemoryStream(new byte[10000]); PipeReader reader = PipeReader.Create(stream); // Make sure state isn't used from before for (var i = 0; i < 3; i++) { reader.CancelPendingRead(); ValueTask <ReadResult> readResultTask = reader.ReadAsync(); Assert.True(readResultTask.IsCompleted); ReadResult readResult = readResultTask.GetAwaiter().GetResult(); Assert.True(readResult.IsCanceled); readResult = await reader.ReadAsync(); reader.AdvanceTo(readResult.Buffer.End); } reader.Complete(); }
public async Task ReadAsyncReturnsCanceledInterleaved() { var stream = new MemoryStream(new byte[10000]); PipeReader reader = PipeReader.Create(stream); // Cancel and Read interleaved to confirm cancellations are independent for (var i = 0; i < 3; i++) { reader.CancelPendingRead(); ValueTask <ReadResult> readResultTask = reader.ReadAsync(); Assert.True(readResultTask.IsCompleted); ReadResult readResult = readResultTask.GetAwaiter().GetResult(); Assert.True(readResult.IsCanceled); readResult = await reader.ReadAsync(); Assert.False(readResult.IsCanceled); } reader.Complete(); }
public override async ValueTask <byte[]> ResolveAsync(byte[] Query) { if (!TcpClient.Connected || !NetworkStream.CanWrite) { await InitializeAsync(); } var QueryLength = BitConverter.GetBytes((ushort)Query.Length); var PrefixedQuery = Concat(QueryLength, Query); await PipeWriter.WriteAsync(PrefixedQuery); PipeWriter.Complete(); var Task = PipeReader.ReadAsync().AsTask(); Task.Wait(Options.CurrentValue.Timeout); if (Task.IsCompleted) { var Result = Task.Result; PipeReader.Complete(); var Buffer = Result.Buffer.Length > 14 ? Result.Buffer.Slice(2) : throw new OperationCanceledException(); return(Buffer.ToArray()); } PipeReader.CancelPendingRead(); PipeReader.Complete(); throw new TimeoutException(); }
/// <inheritdoc /> protected override Task OnPauseRequestedAsync(CancellationToken cancellationToken) { _socketPipeReader.CancelPendingRead(); return(base.OnPauseRequestedAsync(cancellationToken)); }
async Task ReadLoop() { using (_config.InputLogger?.InputLoopStarting()) { try { while (!StopToken.IsCancellationRequested) { ReadResult read = await _pipeReader.ReadAsync(StopToken); IInputLogger?m = _config.InputLogger; if (StopToken.IsCancellationRequested || read.IsCanceled) { m?.ReadLoopTokenCancelled(); break;//The client called the cancel, no need to notify it. } //The packet header require 2-5 bytes OperationStatus res = TryParsePacketHeader(read.Buffer, out byte header, out int length, out SequencePosition position); if (res == OperationStatus.InvalidData) { m?.InvalidIncomingData(); await DisconnectAsync(DisconnectedReason.ProtocolError); break; } if (res == OperationStatus.Done) { _pipeReader.AdvanceTo(position); using (m?.IncomingPacket(header, length)) { // TODO: Can concurrently changing the ref to CurrentReflex could cause an issue here ? Lets hope not for now. await CurrentReflex(m, this, header, length, _pipeReader, StopToken); } continue; } Debug.Assert(res == OperationStatus.NeedMoreData); if (read.IsCompleted) { if (read.Buffer.Length == 0) { m?.EndOfStream(); } else { m?.UnexpectedEndOfStream(); } await DisconnectAsync(DisconnectedReason.RemoteDisconnected); break; } _pipeReader.AdvanceTo(read.Buffer.Start, read.Buffer.End); //Mark data observed, so we will wait new data. } _pipeReader.Complete(); _pipeReader.CancelPendingRead(); } catch (OperationCanceledException e) { _config.InputLogger?.LoopCanceledException(e); } catch (Exception e) { _config.InputLogger?.ExceptionOnParsingIncomingData(e); await DisconnectAsync(DisconnectedReason.UnspecifiedError); } } }
public override void CancelPendingRead() => _input.CancelPendingRead();
public override void CancelPendingRead() => _underlyingPipeReader.CancelPendingRead();
public override void CancelPendingRead() { _reader.CancelPendingRead(); }
public override void CancelPendingRead() { _delegate.CancelPendingRead(); }
public void Abort(ConnectionAbortedException ex) { // TODO: Really abort the connection using the ConnectionContex like Http1OutputProducer. _outputReader.CancelPendingRead(); Complete(); }
// on user thread private async ValueTask <NetSendResult> SendFragmentedMessageAsync( PipeReader reader, NetConnection recipient, int sequenceChannel, CancellationToken cancellationToken) { int group = GetNextFragmentGroup(); (NetSendResult Result, NetSenderChannel?) SendChunk(NetOutgoingMessage chunk) { return(recipient.EnqueueMessage(chunk, NetDeliveryMethod.ReliableOrdered, sequenceChannel)); } NetSendResult finalResult; Exception? exception = null; try { ReadResult readResult; do { readResult = await reader.ReadAsync(cancellationToken).ConfigureAwait(false); if (readResult.IsCanceled) { NetOutgoingMessage cancelChunk = CreateStreamChunk(0, group, NetStreamFragmentType.Cancelled); finalResult = SendChunk(cancelChunk).Result; break; } ReadOnlySequence <byte> buffer = readResult.Buffer; int mtu = recipient.CurrentMTU; int bytesPerChunk = NetFragmentationHelper.GetBestChunkSize(group, (int)buffer.Length, mtu); while (buffer.Length > 0) { long chunkLength = Math.Min(buffer.Length, bytesPerChunk); NetOutgoingMessage chunk = CreateStreamChunk((int)chunkLength, group, NetStreamFragmentType.Data); foreach (ReadOnlyMemory <byte> memory in buffer.Slice(0, chunkLength)) { chunk.Write(memory.Span); } buffer = buffer.Slice(chunkLength); LidgrenException.Assert(chunk.GetEncodedSize() <= mtu); Interlocked.Add(ref chunk._recyclingCount, 1); var(result, channel) = SendChunk(chunk); if (result == NetSendResult.Queued) { await channel !.WaitForIdleAsync(millisecondsTimeout: 10000, cancellationToken); } else if (result != NetSendResult.Sent) { NetOutgoingMessage cancelChunk = CreateStreamChunk(0, group, NetStreamFragmentType.Cancelled); finalResult = SendChunk(cancelChunk).Result; reader.CancelPendingRead(); break; } } reader.AdvanceTo(readResult.Buffer.End); }while (!readResult.IsCompleted); NetOutgoingMessage endChunk = CreateStreamChunk(0, group, NetStreamFragmentType.EndOfStream); finalResult = SendChunk(endChunk).Result; } catch (Exception ex) { exception = ex; NetOutgoingMessage errorChunk = CreateStreamChunk(0, group, NetStreamFragmentType.ServerError); finalResult = SendChunk(errorChunk).Result; } await reader.CompleteAsync(exception).ConfigureAwait(false); return(finalResult); }
public void CancelPendingRead() { _cancelCalled = true; _input.CancelPendingRead(); }
public void Abort() { // Cancel the pending read so the process loop ends without an exception. reader.CancelPendingRead(); }