예제 #1
0
        /// <summary>
        /// Forwards all bytes coming from a <see cref="PipeReader"/> to the specified <see cref="PipeWriter"/>.
        /// </summary>
        /// <param name="reader">The reader to get bytes from.</param>
        /// <param name="writer">The writer to copy bytes to.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        /// <returns>
        /// A <see cref="Task"/> that completes when the <paramref name="reader"/> has finished producing bytes, or an error occurs.
        /// This <see cref="Task"/> never faults, since any exceptions are used to complete the <paramref name="writer"/>.
        /// </returns>
        /// <remarks>
        /// If an error occurs during reading or writing, the <paramref name="writer"/> is completed with the exception.
        /// </remarks>
        internal static Task LinkToAsync(this PipeReader reader, PipeWriter writer, CancellationToken cancellationToken = default)
        {
            Requires.NotNull(reader, nameof(reader));
            Requires.NotNull(writer, nameof(writer));

            return(Task.Run(async delegate
            {
                try
                {
                    while (true)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        var result = await reader.ReadAsync(cancellationToken).ConfigureAwait(false);
                        writer.Write(result.Buffer);
                        reader.AdvanceTo(result.Buffer.End);
                        result.ScrubAfterAdvanceTo();
                        await writer.FlushAsync(cancellationToken).ConfigureAwait(false);
                        if (result.IsCompleted)
                        {
                            await writer.CompleteAsync().ConfigureAwait(false);
                            break;
                        }
                    }

                    await reader.CompleteAsync().ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    await writer.CompleteAsync(ex).ConfigureAwait(false);
                    await reader.CompleteAsync(ex).ConfigureAwait(false);
                }
            }));
        }
예제 #2
0
        private async Task ReceiveDataAsync(PipeReader reader, Memory <byte> destinationMemory, CancellationToken cancellationToken)
        {
            var position = 0;

            while (true)
            {
                var result = await reader.ReadAsync(cancellationToken);

                var buffer = result.Buffer;

                foreach (var memory in buffer)
                {
                    memory.CopyTo(destinationMemory.Slice(position, memory.Length));
                    position += memory.Length;
                }

                reader.AdvanceTo(buffer.End, buffer.End);

                if (result.IsCompleted)
                {
                    break;
                }
            }
            await reader.CompleteAsync();
        }
예제 #3
0
        static async Task ReadPipeAsync(PipeReader reader, CsvWriter csvWriter, Mapper mapper)
        {
            while (true)
            {
                var result = await reader.ReadAsync();

                ReadOnlySequence <byte> buffer = result.Buffer;

                while (TryReadCarUpdateDatagram(ref buffer, out var completeDatagram))
                {
                    var carData = StructSerializer
                                  .Deserialize <CarUpdateDatagram>(completeDatagram.ToArray(), 0);

                    var carModel = mapper.Map <CarStateModel>(carData);
                    csvWriter.NextRecord();
                    csvWriter.WriteRecord(carModel);
                }

                reader.AdvanceTo(buffer.Start, buffer.End);

                if (result.IsCompleted)
                {
                    break;
                }
            }

            await reader.CompleteAsync();
        }
        /// <summary>
        /// Liest die Pipe aus, parsed die Daten und gibt diese weiter an die API. (Wird erst beenden, wenn cancellationToken abgebrochen wird)
        /// </summary>
        /// <param name="reader">Der Reader von der Pipe, welche ausgelesen werden soll</param>
        /// <param name="cancellationToken"></param>
        /// <returns>Wird erst beenden, wenn cancellationToken abgebrochen wird</returns>
        private async Task ReadPipeAsync(PipeReader reader, CancellationToken cancellationToken)
        {
            var keepRunning = true;

            cancellationToken.Register(() => keepRunning = false);

            while (keepRunning)
            {
                ReadResult result = await reader.ReadAsync();

                ReadOnlySequence <byte> buffer = result.Buffer;

                while (this.TryReadMessage(ref buffer, out ReadOnlySequence <byte> line, "\n"))
                {
                    // Process the line.
                    //this.ProcessLine(line);
                }

                // Tell the PipeReader how much of the buffer has been consumed.
                reader.AdvanceTo(buffer.Start, buffer.End);

                // Stop reading if there's no more data coming.
                if (result.IsCompleted)
                {
                    break;
                }
            }

            // Mark the PipeReader as complete.
            await reader.CompleteAsync();
        }
        private async Task RunProcessAsync(PipeReader reader,
                                           CancellationToken cancellationToken = default)
        {
            ReadResult  readResult  = default;
            FlushResult flushResult = default;

            try
            {
                while (!readResult.IsCompleted && !flushResult.IsCompleted)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    readResult = await reader
                                 .ReadAsync(cancellationToken);

                    var buffer   = readResult.Buffer;
                    var consumed = buffer.Start;
                    var examined = buffer.End;

                    if (await TryProcessPacketAsync(ref buffer,
                                                    cancellationToken))
                    {
                        consumed = buffer.Start;
                        examined = consumed;
                    }

                    reader.AdvanceTo(consumed, examined);
                }
            }
            finally
            {
                await reader.CompleteAsync();
            }
        }
예제 #6
0
        private async Task ReadPipeAsync(PipeReader reader)
        {
            try
            {
                int?length = null;

                while (true)
                {
                    // Read data written to the pipe that has been made available.
                    var result = await reader.ReadAsync()
                                 .ConfigureAwait(false);

                    var buffer = result.Buffer;

                    while (true)
                    {
                        if (!length.HasValue)
                        {
                            if (buffer.Length < sizeof(int))
                            {
                                // The length prefix has not been received yet.
                                break;
                            }

                            // Enough data is available to read the length prefix.
                            length = ReadLengthPrefix(buffer);
                            // Slice away the part that contains the length prefix.
                            buffer = buffer.Slice(sizeof(int));
                        }

                        if (buffer.Length < length.Value)
                        {
                            // The remaining data has not been received yet.
                            break;
                        }

                        // Restart the disconnection timer, because a message has just been received.
                        _disconnectTimer.Change(DisconnectTimeout, Timeout.Infinite);
                        DataReceived?.Invoke(this, buffer.Slice(0, length.Value));

                        // Slice away the bytes that have been processed.
                        buffer = buffer.Slice(length.Value);
                        length = null;
                    }

                    // Mark the processed data as consumed and indicate that the rest has been examined.
                    reader.AdvanceTo(buffer.Start, buffer.End);

                    if (result.IsCompleted)
                    {
                        break;
                    }
                }
            }
            finally
            {
                await reader.CompleteAsync()
                .ConfigureAwait(false);
            }
        }
예제 #7
0
        private async ValueTask StartReadPipe(PipeReader pipeReader, CancellationToken cancellationToken)
        {
            var processor = new PacketsProcessor(_channelWriter);

            try
            {
                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var result = await pipeReader.ReadAsync(cancellationToken);

                    var length = await processor.ProcessBytesAsync(result.Buffer, cancellationToken);

                    pipeReader.AdvanceTo(result.Buffer.GetPosition(length));
                    if (result.IsCompleted)
                    {
                        break;
                    }
                }
            }
            catch (SocketException e)
            {
                await pipeReader.CompleteAsync(e);

                _channelWriter.Complete(e);
            }
        }
예제 #8
0
        /// <summary>
        /// Deserializes the header part of the fits document
        /// </summary>
        /// <param name="dataStream">the stream from which to read the data from (should be at position 0)</param>
        /// <exception cref="InvalidDataException"></exception>
        public async Task <Header> DeserializeAsync(PipeReader dataStream)
        {
            PreValidateStream(dataStream);

            var endOfHeaderReached = false;
            var headerEntries      = new List <HeaderEntry>();

            while (!endOfHeaderReached)
            {
                var result = await dataStream.ReadAsync().ConfigureAwait(false);

                var headerBlock = result.Buffer;

                if (result.IsCompleted || result.Buffer.Length < HeaderBlockSize)
                {
                    await dataStream.CompleteAsync().ConfigureAwait(false);

                    throw new InvalidDataException("No END marker found for the fits header, fits file might be corrupted");
                }

                headerEntries.AddRange(ParseHeaderBlock(headerBlock, out endOfHeaderReached));
                dataStream.AdvanceTo(result.Buffer.GetPosition(HeaderBlockSize), result.Buffer.End);
            }

            return(new Header(headerEntries));
        }
예제 #9
0
        protected virtual async Task Receive(PipeReader reader)
        {
            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    ReadResult result = await reader.ReadAsync(cancellationToken);

                    if (result.IsCompleted)
                    {
                        break;
                    }
                    ReadOnlySequence <byte> buffer = result.Buffer;

                    while (TryReadLine(ref buffer, out ReadOnlySequence <byte> line))
                    {
                        await ProcessLine(Id, line);
                    }

                    reader.AdvanceTo(buffer.Start, buffer.End);
                }
            }
            catch (Exception e)
            {
                await LogException(e.Message);
            }
            finally
            {
                await reader.CompleteAsync();

                Stop();
                Dispose();
            }
        }
예제 #10
0
        private async Task PipeProcessorAsync(PipeReader reader, CancellationToken cancelationToken = default)
        {
            while (!cancelationToken.IsCancellationRequested)
            {
                var result = await reader.ReadAsync(cancelationToken);

                var buffer = result.Buffer;
                SequencePosition?position;

                do
                {
                    position = buffer.PositionOf((byte)'\n');

                    if (position != null)
                    {
                        var notif = msgProc.PushMessage(buffer.Slice(0, position.Value).ToArray());
                        if (notif.HasValue)
                        {
                            dispatcher.Invoke(notif.Value);
                        }

                        // +2 = skipping \n\r
                        buffer = buffer.Slice(buffer.GetPosition(2, position.Value));
                    }
                } while (position != null);

                reader.AdvanceTo(buffer.Start, buffer.End);
                if (result.IsCompleted || result.IsCanceled)
                {
                    break;
                }
            }

            await reader.CompleteAsync();
        }
        private static async Task <List <byte[]> > ListenAsync(PipeReader input)
        {
            var       messages      = new List <byte[]>();
            const int messageLength = 3;

            while (true)
            {
                var result = await input.ReadAsync();

                var buffer = result.Buffer;

                while (!buffer.IsEmpty)
                {
                    var payload = buffer.Slice(0, messageLength);
                    messages.Add(payload.ToArray());
                    buffer = buffer.Slice(messageLength);
                }

                input.AdvanceTo(buffer.Start, buffer.End);

                if (result.IsCompleted)
                {
                    break;
                }
            }

            await input.CompleteAsync();

            return(messages);
        }
        private static async IAsyncEnumerable <ReadOnlySequence <byte> > GetReaderResult(
            PipeReader reader, [EnumeratorCancellation] CancellationToken token = default)
        {
            while (true && !token.IsCancellationRequested)
            {
                ReadResult result = await reader.ReadAsync();

                ReadOnlySequence <byte> buffer = result.Buffer;
                if (buffer.Length < 4)
                {
                    yield break;
                }
                var position = buffer.GetPosition(sizeof(int));
                Console.WriteLine("Reading...");
                yield return(buffer.Slice(0, position));

                buffer = buffer.Slice(position);
                reader.AdvanceTo(buffer.Start, position);
                // Tell the PipeReader how much of the buffer has been consumed.
                // Stop reading if there's no more data coming.
                if (result.IsCompleted)
                {
                    break;
                }
            }
            // Mark the PipeReader as complete.
            await reader.CompleteAsync();
        }
예제 #13
0
        protected override async Task ExecuteAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Worker started");
            _payloadReadyEvent.Wait(cancellationToken);
            _payloadReadyEvent.Reset();

            while (!cancellationToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.UtcNow);
                if (!File.Exists(Constants.EXPECTED_ZIP_FILE_NAME))
                {
                    // The package hasn't arrived yet
                    _logger.LogDebug("Compressed payload not found {filename}", Constants.EXPECTED_ZIP_FILE_NAME);
                    await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);

                    continue;
                }

                using ZipArchive zipArchive = ZipFile.OpenRead(Constants.EXPECTED_ZIP_FILE_NAME);
                ZipArchiveEntry dataEntry      = zipArchive.Entries.SingleOrDefault();
                Stream          zipEntryStream = dataEntry.Open();

                StreamPipeReaderOptions streamOptions =
                    new StreamPipeReaderOptions(bufferSize: MINIMUM_BUFFER_SIZE);
                PipeReader pipeReader = PipeReader.Create(zipEntryStream, streamOptions);

                while (true)
                {
                    _logger.LogDebug("Reading stream into pipe buffer");
                    ReadResult result = await pipeReader.ReadAsync(cancellationToken);

                    ReadOnlySequence <byte> buffer = result.Buffer;

                    // Notify the PipeReader how much buffer was used
                    pipeReader.AdvanceTo(buffer.Start, buffer.End);

                    if (!result.IsCompleted)
                    {
                        continue;
                    }

                    _logger.LogDebug("Payload read");
                    JsonDocument documentFromBuffer = InspectBuffer(buffer);
                    _ = await _payloadChannel.AddPayloadAsync(documentFromBuffer, cancellationToken);

                    break;
                }

                await pipeReader.CompleteAsync();

                await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);

                return;
            }

            if (cancellationToken.IsCancellationRequested)
            {
                _logger.LogWarning("Operation cancelled");
            }
        }
예제 #14
0
        private async Task ReadPipeAsync(PipeReader reader, CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                var result = await reader.ReadAsync(cancellationToken);

                var buffer = new ByteReader(result.Buffer);
                while (!buffer.IsEnd)
                {
                    try
                    {
                        if (!await ProcessAsync(buffer))
                        {
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        LogError(ex);
                        break;
                    }
                }

                // 告诉PipeReader我们已经处理多少缓冲
                reader.AdvanceTo(buffer.Start, buffer.End);
                // 如果没有更多的数据,停止都去
                if (result.IsCompleted)
                {
                    break;
                }
            }

            // 将PipeReader标记为完成
            await reader.CompleteAsync();
        }
        private static async Task ProcessLinesAsync(Socket socket)
        {
            Console.WriteLine($"[{socket.RemoteEndPoint}]: connected");

            NetworkStream stream = new NetworkStream(socket);
            PipeReader    reader = PipeReader.Create(stream);

            while (true)
            {
                ReadResult result = await reader.ReadAsync();

                ReadOnlySequence <byte> buffer = result.Buffer;

                while (TryReadLine(ref buffer, out ReadOnlySequence <byte> line))
                {
                    ProcessLine(line);
                }

                reader.AdvanceTo(buffer.Start, buffer.End);

                if (result.IsCompleted)
                {
                    break;
                }
            }

            await reader.CompleteAsync();

            Console.WriteLine($"[{socket.RemoteEndPoint}]: disconnected");
        }
예제 #16
0
        public static async IAsyncEnumerable <ResultRow> Reader(PipeReader reader)
        {
            var keys = new FastSerializableKeys <string>();

            while (true)
            {
                var result = await reader.ReadAsync().ConfigureAwait(false);

                var buffer = result.Buffer;
                SequencePosition?position;

                do
                {
                    position = buffer.PositionOf((byte)'\n');
                    if (position == null)
                    {
                        continue;
                    }

                    var row = DeserializeRow(keys, buffer.Slice(0, position.Value));
                    yield return(row);

                    buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
                } while (position != null);

                reader.AdvanceTo(buffer.Start, buffer.End);

                if (result.IsCompleted)
                {
                    break;
                }
            }

            await reader.CompleteAsync().ConfigureAwait(false);
        }
예제 #17
0
파일: Pipe.cs 프로젝트: wzchua/docs
        async Task ReadPipeAsync(PipeReader reader)
        {
            while (true)
            {
                ReadResult result = await reader.ReadAsync();

                ReadOnlySequence <byte> buffer = result.Buffer;

                while (TryReadLine(ref buffer, out ReadOnlySequence <byte> line))
                {
                    // Process the line.
                    ProcessLine(line);
                }

                // Tell the PipeReader how much of the buffer has been consumed.
                reader.AdvanceTo(buffer.Start, buffer.End);

                // Stop reading if there's no more data coming.
                if (result.IsCompleted)
                {
                    break;
                }
            }

            // Mark the PipeReader as complete.
            await reader.CompleteAsync();
        }
예제 #18
0
        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);
                }
            }
        }
예제 #19
0
        public async Task RunAsync(
            CancellationToken cancellationToken = default)
        {
            mp3dec_t decoder;

            unsafe
            {
                mp3dec_init(&decoder);
            }

            try
            {
                FlushResult flushResult = default;
                ReadResult  readResult  = default;
                while (!flushResult.IsCompleted)
                {
                    readResult = await _input.ReadAsync();

                    var buffer = readResult.Buffer;

                    if (buffer.IsEmpty && readResult.IsCompleted)
                    {
                        return;
                    }

                    while (TryReadFrame(ref buffer, out var frame))
                    {
                        var block = _outputPipe.Writer.GetMemory(
                            (MINIMP3_MAX_SAMPLES_PER_FRAME * sizeof(short))
                            + sizeof(short));

                        var success = TryProcessFrame(frame, ref decoder,
                                                      block.Span, out var bytesWritten);

                        _outputPipe.Writer.Advance(bytesWritten);

                        // invalid data was passed, so bail out
                        if (!success)
                        {
                            return;
                        }
                    }

                    flushResult = await _outputPipe.Writer.FlushAsync(
                        cancellationToken);

                    _input.AdvanceTo(buffer.Start, buffer.End);
                }
            }
            finally
            {
                _ = await _outputPipe.Writer.FlushAsync(cancellationToken);

                await _input.CompleteAsync();

                await _outputPipe.Writer.CompleteAsync();
            }
예제 #20
0
        private async Task ReadAsync()
        {
            try
            {
                while (!_cancellation.IsCancellationRequested)
                {
                    var result = await _pipeReader.ReadAsync(_cancellation.Token);

                    var buffer = result.Buffer;

                    var readLength = 0L;

                    try
                    {
                        if (0 < buffer.Length)
                        {
                            readLength = OnRead(ref buffer);
                        }

                        if (result.IsCanceled)
                        {
                            readLength = buffer.Length;
                            break;
                        }

                        if (result.IsCompleted)
                        {
                            readLength = buffer.Length;
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        readLength = buffer.Length;
                        OnError(ex);
                        break;
                    }
                    finally
                    {
                        _pipeReader.AdvanceTo(buffer.GetPosition(readLength));
                    }
                }
            }
            catch (OperationCanceledException)
            {
                // cancel~
            }
            catch (Exception ex)
            {
                OnError(ex);
            }
            finally
            {
                await _pipeReader.CompleteAsync();
            }
        }
예제 #21
0
파일: Program.cs 프로젝트: dutts/docs-1
    static async Task ProcessMessagesAsync(
        PipeReader reader,
        PipeWriter writer)
    {
        try
        {
            while (true)
            {
                ReadResult readResult = await reader.ReadAsync();

                ReadOnlySequence <byte> buffer = readResult.Buffer;

                try
                {
                    if (readResult.IsCanceled)
                    {
                        break;
                    }

                    if (TryParseLines(ref buffer, out string message))
                    {
                        FlushResult flushResult =
                            await WriteMessagesAsync(writer, message);

                        if (flushResult.IsCanceled || flushResult.IsCompleted)
                        {
                            break;
                        }
                    }

                    if (readResult.IsCompleted)
                    {
                        if (!buffer.IsEmpty)
                        {
                            throw new InvalidDataException("Incomplete message.");
                        }
                        break;
                    }
                }
                finally
                {
                    reader.AdvanceTo(buffer.Start, buffer.End);
                }
            }
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex);
        }
        finally
        {
            await reader.CompleteAsync();

            await writer.CompleteAsync();
        }
    }
예제 #22
0
        private async Task ReadPipeAsync(PipeReader reader)
        {
            try
            {
                while (State == EstablishedConnectionState.Opened)
                {
                    ReadResult result = await reader.ReadAsync(cts.Token).ConfigureAwait(false);

                    ReadOnlySequence <byte> buffer = result.Buffer;
                    if (buffer.Length == 0)
                    {
                        continue;
                    }

                    SequencePosition consumed;
                    SequencePosition examined;
                    try
                    {
                        (consumed, examined) = ReadFrames(ref buffer);
                        Debug.WriteLine($"ADVANCE_TO consumed: {consumed.GetInteger()}, examined: {examined.GetInteger()}");
                    }
                    catch (Exception ex)
                    {
                        OnError(ErrorCode.FailedToReadFrames, ex);
                        consumed = buffer.End;
                        examined = buffer.End;
                    }

                    reader.AdvanceTo(consumed, examined);
                    if (result.IsCompleted)
                    {
                        break;
                    }
                }

                await reader.CompleteAsync().ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                OnError(ErrorCode.ReadPipe, ex);
                await reader.CompleteAsync(ex).ConfigureAwait(false);
            }
        }
예제 #23
0
        /// <inheritdoc/>
        public async Task RunAsync(
            CancellationToken cancellationToken = default)
        {
            bool identified = false;

            _codec = new TaskCompletionSource <MpegAudioCodec>();

            try
            {
                FlushResult flushResult = default;
                ReadResult  readResult  = default;
                while (!flushResult.IsCompleted)
                {
                    readResult = await _input.ReadAsync(cancellationToken);

                    var buffer = readResult.Buffer;

                    if (buffer.IsEmpty && readResult.IsCompleted)
                    {
                        return;
                    }

                    while (TryReadMpegFrame(ref buffer, out var frame,
                                            out var version, out var layer, out var bitrate,
                                            out var samplingRate, out var channelCount))
                    {
                        if (!identified)
                        {
                            identified = true;
                            _          = _codec.TrySetResult(
                                new MpegAudioCodec(version, layer,
                                                   samplingRate, channelCount, bitrate));
                        }

                        if (!TryWriteFrame(frame, _outputPipe.Writer))
                        {
                            return;
                        }
                    }

                    flushResult = await _outputPipe.Writer.FlushAsync(
                        cancellationToken);

                    _input.AdvanceTo(buffer.Start, buffer.End);
                }
            }
            finally
            {
                _ = await _outputPipe.Writer.FlushAsync(cancellationToken);

                await _input.CompleteAsync();

                await _outputPipe.Writer.CompleteAsync();
            }
예제 #24
0
        /// <inheritdoc/>
        public async Task RunAsync(
            CancellationToken cancellationToken = default)
        {
            try
            {
                FlushResult flushResult = default;
                ReadResult  readResult  = default;
                while (!flushResult.IsCompleted)
                {
                    readResult = await _input.ReadAsync(cancellationToken);

                    var buffer = readResult.Buffer;

                    if (buffer.IsEmpty && readResult.IsCompleted)
                    {
                        return;
                    }

                    while (TryHandleElement(ref buffer, out var status))
                    {
                        if (status == EbmlHandleStatus.NewBlock &&
                            !TryWriteBlock(_bestAudioTrack, _outputPipe.Writer,
                                           _state.BlockData))
                        {
                            return;
                        }

                        if (status == EbmlHandleStatus.UnsupportedFile ||
                            status == EbmlHandleStatus.NoMoreData)
                        {
                            return;
                        }

                        if (status == EbmlHandleStatus.MissingData)
                        {
                            break;
                        }
                    }

                    flushResult = await _outputPipe.Writer.FlushAsync(
                        cancellationToken);

                    _input.AdvanceTo(buffer.Start, buffer.End);
                }
            }
            finally
            {
                _ = await _outputPipe.Writer.FlushAsync(cancellationToken);

                await _input.CompleteAsync();

                await _outputPipe.Writer.CompleteAsync();
            }
예제 #25
0
        /// <summary>
        /// Receive multiple messages from a pipe
        /// </summary>
        public static async IAsyncEnumerable <T> ReceiveAsync <T>(PipeReader source, MessagePipeOptions options = default)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            options = options.Normalize();

            while (true)
            {
                // obtain the next buffer
                options.OnLog("ReceiveAsync obtaining buffer...");
                if (!source.TryRead(out var result))
                {
                    result = await source.ReadAsync(options.CancellationToken).ConfigureAwait(false);
                }
                if (result.IsCanceled)
                {
                    ThrowCancelled();
                }

                // consume the buffer
                var buffer = result.Buffer;
                options.OnLog($"ReceiveAsync got {buffer.Length} bytes");
                int processed = 0;
                while (options.TryRead <T>(ref buffer, out var item))
                {
                    processed++;
                    yield return(item);
                }

                if (processed == 0 && result.IsCompleted) // check for termination
                {
                    // we have everything, and there will never be any more; was it clean?
                    if (!buffer.IsEmpty)
                    {
                        ThrowInputCompletedWithPartialPayload();
                    }
                    break;
                }

                // mark what we consumed (the "ref buffer" means we've sliced it already)
                source.AdvanceTo(buffer.Start, buffer.End);
            }
            if (options.MarkComplete)
            {
                await source.CompleteAsync().ConfigureAwait(false);
            }
            options.OnLog("ReceiveAsync completed successfully");
        }
예제 #26
0
    private async Task ProcessMessagesAsync(CancellationToken cancellationToken)
    {
        try
        {
            while (true)
            {
                SequencePosition?position;
                ReadResult       result = await _reader.ReadAsync(cancellationToken);

                ReadOnlySequence <byte> buffer = result.Buffer;

                do
                {
                    position = buffer.PositionOf(SubscriptionSession.Delimiter);

                    if (position is not null)
                    {
                        await _pipeline.ProcessAsync(
                            _connection,
                            buffer.Slice(0, position.Value),
                            cancellationToken);

                        // Skip the message which was read.
                        buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
                    }
                }while (position != null);

                _reader.AdvanceTo(buffer.Start, buffer.End);

                if (result.IsCompleted)
                {
                    break;
                }
            }
        }
        catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested)
        {
        }
        catch (WebSocketException)
        {
            // we will just stop receiving
        }
        finally
        {
            // reader should be completed always, so that related pipe writer can
            // stop write new messages
            await _reader.CompleteAsync();
        }
    }
예제 #27
0
        public async IAsyncEnumerable <IPacket> ReadPacketAsync(TimeSpan timeout, [EnumeratorCancellation] CancellationToken cancellationToken = default)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                ReadResult result = await _pipeReader.ReadAsync(cancellationToken)
                                    .AsTask()
                                    .WithTimeout(timeout, TimeoutConstants.Message);

                ReadOnlySequence <byte> buffer = result.Buffer;

                while (!cancellationToken.IsCancellationRequested)
                {
                    // We can't calculate packet size without the packet header
                    if (buffer.Length < PacketConstants.HeaderSize)
                    {
                        break;
                    }

                    // Make sure the packet fits in the buffer
                    // See: https://mariadb.com/kb/en/library/0-packet/
                    var bodySize   = GetBodySize(buffer);
                    var packetSize = PacketConstants.HeaderSize + bodySize;

                    if (buffer.Length < packetSize)
                    {
                        break;
                    }

                    // Process packet and repeat in case there are more packets in the buffer
                    var packet = TryReadPacket(buffer.Slice(PacketConstants.HeaderSize, bodySize));

                    if (packet != null)
                    {
                        yield return(packet);
                    }

                    buffer = buffer.Slice(buffer.GetPosition(packetSize));
                }

                _pipeReader.AdvanceTo(buffer.Start, buffer.End);

                if (result.IsCompleted)
                {
                    break;
                }
            }

            await _pipeReader.CompleteAsync();
        }
예제 #28
0
        public async IAsyncEnumerable <ReadOnlySequence <byte> > Frames([EnumeratorCancellation] CancellationToken cancellationToken)
        {
            ThrowIfDisposed();

            _ = FillPipe(cancellationToken);

            try
            {
                while (true)
                {
                    var result = await _reader.ReadAsync(cancellationToken).ConfigureAwait(false);

                    var buffer = result.Buffer;

                    while (true)
                    {
                        if (buffer.Length < 4)
                        {
                            break;
                        }

                        var frameSize = buffer.ReadUInt32(0, true);
                        var totalSize = frameSize + 4;

                        if (buffer.Length < totalSize)
                        {
                            break;
                        }

                        yield return(buffer.Slice(4, frameSize));

                        buffer = buffer.Slice(totalSize);
                    }

                    if (result.IsCompleted)
                    {
                        break;
                    }

                    _reader.AdvanceTo(buffer.Start);
                }
            }
            finally
            {
                await _reader.CompleteAsync().ConfigureAwait(false);
            }
        }
예제 #29
0
        private static async Task ProcessMessagesAsync(
            PipeReader reader,
            ProcessAsync processAsync,
            CancellationToken cancellationToken)
        {
            try
            {
                while (true)
                {
                    ReadResult result = await reader
                                        .ReadAsync(cancellationToken)
                                        .ConfigureAwait(false);

                    ReadOnlySequence <byte> buffer   = result.Buffer;
                    SequencePosition?       position = null;

                    do
                    {
                        position = buffer.PositionOf(Delimiter);

                        if (position != null)
                        {
                            await processAsync(
                                buffer.Slice(0, position.Value),
                                cancellationToken)
                            .ConfigureAwait(false);

                            // Skip the message which was read.
                            buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
                        }
                    } while (position != null);

                    reader.AdvanceTo(buffer.Start, buffer.End);

                    if (result.IsCompleted)
                    {
                        break;
                    }
                }
            }
            catch (TaskCanceledException) { }
            finally
            {
                await reader.CompleteAsync().ConfigureAwait(false);
            }
        }
예제 #30
0
    private async ValueTask ConsumeAsync(PipeReader reader, CancellationToken cancellationToken)
    {
        while (true)
        {
            var result = await reader.ReadAsync(cancellationToken);

            var buffer = result.Buffer;

            reader.AdvanceTo(buffer.End, buffer.End);

            if (result.IsCompleted)
            {
                break;
            }
        }

        await reader.CompleteAsync();
    }