Пример #1
0
        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();
            }
        }
Пример #2
0
    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.");
    }
Пример #3
0
        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);
                }
            }
        }
Пример #5
0
        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();
        }
Пример #6
0
        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();
            }
        }
Пример #7
0
        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();
        }
Пример #8
0
        protected override void Dispose(bool disposing)
        {
            if (!disposing)
            {
                return;
            }

            _reader.CancelPendingRead();
            _reader.Complete();
            _networkStream.Dispose();
        }
Пример #9
0
        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();
        }
Пример #10
0
        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);
                }
            }
        }
Пример #11
0
 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
     {
     }
 }
Пример #12
0
        public void Abort(Exception ex)
        {
            lock (_writeLock)
            {
                if (_completed)
                {
                    return;
                }

                _completed = true;
                _outputReader.CancelPendingRead();
                _outputWriter.Complete(ex);
            }
        }
Пример #13
0
        public void Abort(Exception error)
        {
            lock (_contextLock)
            {
                if (_completed)
                {
                    return;
                }

                _log.ConnectionDisconnect(_connectionId);
                _completed = true;

                _outputPipeReader.CancelPendingRead();
                _pipeWriter.Complete(error);
            }
        }
Пример #14
0
        public void Stop()
        {
            lock (_dataWriterLock)
            {
                if (_streamCompleted)
                {
                    return;
                }

                _streamCompleted = true;

                _pipeReader.CancelPendingRead();

                _frameWriter.AbortPendingStreamDataWrites(_flowControl);
            }
        }
Пример #15
0
        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();
        }
Пример #16
0
        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();
        }
Пример #17
0
        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();
        }
Пример #18
0
        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();
        }
Пример #19
0
        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));
 }
Пример #21
0
        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();
Пример #23
0
 public override void CancelPendingRead()
 => _underlyingPipeReader.CancelPendingRead();
Пример #24
0
 public override void CancelPendingRead()
 {
     _reader.CancelPendingRead();
 }
Пример #25
0
 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();
 }
Пример #29
0
 public void Abort()
 {
     // Cancel the pending read so the process loop ends without an exception.
     reader.CancelPendingRead();
 }