Example #1
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);
                }
            }
        }
Example #2
0
        public async Task SyncReadAsyncWithCancellationToken()
        {
            PipeWriter writer = _pipe.Writer;
            PipeReader reader = _pipe.Reader;

            for (int i = 0; i < InnerIterationCount; i++)
            {
                ReadResult result = await reader.ReadAsync(_cts.Token);

                reader.AdvanceTo(result.Buffer.Start);
            }
        }
Example #3
0
        private static async ValueTask <TResult> ReadAsync <TResult, TParser>(this PipeReader reader, TParser parser, CancellationToken token)
            where TParser : struct, IBufferReader <TResult>
        {
            for (SequencePosition consumed; parser.RemainingBytes > 0; reader.AdvanceTo(consumed))
            {
                var readResult = await reader.ReadAsync(token).ConfigureAwait(false);

                readResult.ThrowIfCancellationRequested(token);
                parser.Append <TResult, TParser>(readResult.Buffer, out consumed);
            }
            return(parser.Complete());
        }
Example #4
0
    public static async Task <byte[]> ReadAsync(this PipeReader pipeReader, int numBytes)
    {
        while (true)
        {
            var result = await pipeReader.ReadAsync();

            if (result.Buffer.Length < numBytes)
            {
                pipeReader.AdvanceTo(result.Buffer.Start, result.Buffer.End);
                continue;
            }

            var buffer = result.Buffer.Slice(0, numBytes);

            var bytes = buffer.ToArray();

            pipeReader.AdvanceTo(buffer.End);

            return(bytes);
        }
    }
        protected async ValueTask <JsonTokenType> ReadNextTokenAsync(PipeReader pipe, JsonReaderState state, CancellationToken cancellationToken)
        {
            bool ForwardException(PipeReader pipe, Exception e)
            {
                pipe.Complete(e);
                return(false);
            }

            if (pipe == null)
            {
                throw new ArgumentNullException(nameof(pipe));
            }

            try
            {
                while (true)
                {
                    if (!pipe.TryRead(out ReadResult readResult))
                    {
                        readResult = await pipe.ReadAsync(cancellationToken);
                    }
                    if (readResult.IsCanceled)
                    {
                        throw new OperationCanceledException();
                    }

                    JsonTokenType IsReaderReady(ReadResult readResult, JsonReaderState state)
                    {
                        var reader      = new Utf8JsonReader(readResult.Buffer, readResult.IsCompleted, state);
                        var readerReady = reader.Read();

                        return(readerReady ? reader.TokenType : JsonTokenType.None);
                    }

                    var token = IsReaderReady(readResult, state);
                    if (token == JsonTokenType.None && readResult.IsCompleted)
                    {
                        pipe.Complete();
                        return(EndOfDocument);
                    }

                    pipe.AdvanceTo(readResult.Buffer.Start, readResult.Buffer.End);
                    if (token != JsonTokenType.None)
                    {
                        return(token);
                    }
                }
            }
            catch (Exception e) when(ForwardException(pipe, e))
            {
                throw;
            }
        }
Example #6
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();
            }
Example #7
0
        private async Task <bool> ReceiveHandshakeResponseAsync(PipeReader input, CancellationToken token)
        {
            while (true)
            {
                var result = await input.ReadAsync(token);

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

                try
                {
                    if (result.IsCanceled)
                    {
                        throw new InvalidOperationException("Connection cancelled before handshake complete.");
                    }

                    if (!buffer.IsEmpty)
                    {
                        if (ServiceProtocol.TryParseMessage(ref buffer, out var message))
                        {
                            consumed = buffer.Start;
                            examined = consumed;

                            if (!(message is HandshakeResponseMessage handshakeResponse))
                            {
                                throw new InvalidDataException(
                                          $"{message.GetType().Name} received when waiting for handshake response.");
                            }

                            if (string.IsNullOrEmpty(handshakeResponse.ErrorMessage))
                            {
                                return(true);
                            }

                            // Handshake error. Will stop reconnect.
                            Log.HandshakeError(_logger, handshakeResponse.ErrorMessage);
                            return(false);
                        }
                    }

                    if (result.IsCompleted)
                    {
                        // Not enough data, and we won't be getting any more data.
                        throw new InvalidOperationException("Service disconnected before sending a handshake response.");
                    }
                }
                finally
                {
                    input.AdvanceTo(consumed, examined);
                }
            }
        }
Example #8
0
        private async Task ReceiveLoop()
        {
            try
            {
                while (!_cancelTokenSource.IsCancellationRequested)
                {
                    var result = await _pipeReader.ReadAsync(_cancelTokenSource.Token);

                    var buffer = result.Buffer;

                    var readLength = 0L;

                    try
                    {
                        if (0 < buffer.Length)
                        {
                            readLength = onReceived?.Invoke(ref buffer) ?? buffer.Length;
                        }

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

                        if (result.IsCompleted)
                        {
                            readLength = buffer.Length;
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        readLength = buffer.Length;
                        onError?.Invoke(ex);

                        break;
                    }
                    finally
                    {
                        _pipeReader.AdvanceTo(buffer.GetPosition(readLength));
                    }
                }
            }
            catch (OperationCanceledException)
            {
                // cancel~
            }
            finally
            {
                await _pipeReader.CompleteAsync();
            }
        }
Example #9
0
        public async Task <Handshake> GetHandshakeMessage(PipeReader input)
        {
            ReadResult readAsync = await input.ReadAsync().ConfigureAwait(false);

            if (readAsync.Buffer.Length >= FrameHeaderSize)
            {
                ReadOnlySequence <byte> handshakeBytes =
                    readAsync.Buffer.Slice(0, FrameHeaderSize);

                ArraySegment <byte> arraySegment = handshakeBytes.ToArraySegment();

                if (Handshake.TryParse(arraySegment, out Handshake result))
                {
                    input.AdvanceTo(readAsync.Buffer.GetPosition(FrameHeaderSize));
                    return(result);
                }
            }

            input.AdvanceTo(readAsync.Buffer.GetPosition(0));
            return(null);
        }
        public async ValueTask <byte[]> ReadAsync(CancellationToken cancellationToken = default)
        {
            var result = await _reader.ReadAsync(cancellationToken).ConfigureAwait(false);

            var buffer = result.Buffer;

            try {
                return(buffer.ToArray());
            } finally {
                _reader.AdvanceTo(buffer.End);
            }
        }
Example #11
0
            // fast path - attempt to consume metadata synchronously
            private bool TryConsume()
            {
                if (!reader.TryReadBlock(LogEntryMetadata.Size, out var result) || result.IsCanceled)
                {
                    return(false);
                }

                metadata = new(result.Buffer, out var metadataEnd);
                reader.AdvanceTo(metadataEnd);
                consumed = false;
                return(true);
            }
Example #12
0
        protected async Task ReadPipeAsync(PipeReader reader)
        {
            var cts = _cts;

            while (!cts.IsCancellationRequested)
            {
                var result = await reader.ReadAsync(cts.Token);

                var buffer = result.Buffer;

                SequencePosition consumed = buffer.Start;
                SequencePosition examined = buffer.End;

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

                    var completed = result.IsCompleted;

                    if (buffer.Length > 0)
                    {
                        if (!ReaderBuffer(ref buffer, out consumed, out examined))
                        {
                            completed = true;
                            break;
                        }
                    }

                    if (completed)
                    {
                        break;
                    }
                }
                catch (Exception e)
                {
                    OnError("Protocol error", e);
                    // close the connection if get a protocol error
                    Close();
                    break;
                }
                finally
                {
                    reader.AdvanceTo(consumed, examined);
                }
            }

            reader.Complete();
            WriteEOFPackage();
        }
Example #13
0
        /// <summary>
        /// Read a single message from the pipe reader. Ensure the reader completes without additional data.
        /// </summary>
        /// <param name="input">The request pipe reader.</param>
        /// <returns>Complete message data.</returns>
        public static async ValueTask <byte[]> ReadSingleMessageAsync(this PipeReader input)
        {
            byte[] completeMessageData = null;

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

                var buffer = result.Buffer;

                try
                {
                    if (result.IsCanceled)
                    {
                        throw new InvalidDataException("Incoming message cancelled.");
                    }

                    if (!buffer.IsEmpty)
                    {
                        if (completeMessageData != null)
                        {
                            throw new InvalidDataException("Additional data after the message received.");
                        }

                        if (TryReadMessage(ref buffer, out var data))
                        {
                            // Store the message data
                            // Need to verify the request completes with no additional data
                            completeMessageData = data;
                        }
                    }

                    if (result.IsCompleted)
                    {
                        if (completeMessageData != null)
                        {
                            // Finished and the complete message has arrived
                            return(completeMessageData);
                        }

                        throw new InvalidDataException("Incomplete message.");
                    }
                }
                finally
                {
                    // The buffer was sliced up to where it was consumed, so we can just advance to the start.
                    // We mark examined as buffer.End so that if we didn't receive a full frame, we'll wait for more data
                    // before yielding the read again.
                    input.AdvanceTo(buffer.Start, buffer.End);
                }
            }
        }
Example #14
0
        public static async Task WriteFromBase64Urlsafe(
            this Stream stream, PipeReader base64Pipe,
            CancellationToken cancelToken = default)
        {
            if (stream is null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            if (base64Pipe is null)
            {
                throw new ArgumentNullException(nameof(base64Pipe));
            }

            try
            {
                using (var base64Buffer = bytesPool.Rent())
                {
                    Memory <byte> base64Memory    = base64Buffer.Memory;
                    int           base64Remaining = 0;
                    while (true)
                    {
                        ReadResult readResult = await base64Pipe
                                                .ReadAsync(cancelToken)
                                                .ConfigureAwait(false);

                        (base64Remaining, _) = await stream
                                               .WritePartialFromBase64Urlsafe(readResult.Buffer, base64Memory, base64Remaining, cancelToken)
                                               .ConfigureAwait(false);

                        base64Pipe.AdvanceTo(readResult.Buffer.End);

                        if (readResult.IsCompleted)
                        {
                            break;
                        }
                    }

                    base64Memory = base64Memory.Slice(0, base64Remaining);
                    await stream.WriteFinalFromBase64Urlsafe(base64Memory, cancelToken)
                    .ConfigureAwait(false);
                }

                await stream.FlushAsync(cancelToken).ConfigureAwait(false);

                base64Pipe.Complete();
            }
            catch (Exception e)
            {
                base64Pipe.Complete(e);
                throw;
            }
        }
Example #15
0
        private async Task ConsumeLoop(PipeReader audioData)
        {
            Debug.Assert(_cts is not null);
            SpinWait spinner = new();

            while (!_cts.IsCancellationRequested)
            {
                spinner.SpinOnce();
                ReadResult readResult = await audioData.ReadAsync();

                audioData.AdvanceTo(readResult.Buffer.End);
            }
        }
Example #16
0
        private async Task ProcessLogs(PipeReader reader, CancellationToken cancellationToken, bool stdOut = true)
        {
            while (true)
            {
                var result = await reader.ReadAsync(cancellationToken);

                try
                {
                    var position = result.Buffer.PositionOf((byte)'\r');
                    if (position != null)
                    {
                        var line = GetString(result.Buffer.Slice(0, position.Value));
                        if (stdOut)
                        {
                            _logger.LogDebug("Ffmpeg out: {0}", line);
                        }
                        else
                        {
                            _logger.LogError("Ffmpeg err: {0}", line);
                        }
                        reader.AdvanceTo(position.Value);
                    }
                    else
                    {
                        reader.AdvanceTo(result.Buffer.GetPosition(0));
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Failed to read from pipe");
                    break;
                }

                if (result.IsCompleted)
                {
                    break;
                }
            }
        }
Example #17
0
    public async Task DrainReaderTillCompletedAsync(PipeReader reader)
    {
        while (true)
        {
            var readResult = await reader.ReadAsync(this.TimeoutToken);

            reader.AdvanceTo(readResult.Buffer.End);
            if (readResult.IsCompleted)
            {
                break;
            }
        }
    }
Example #18
0
        /// <summary>
        /// Parses an HTTP form body.
        /// </summary>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
        /// <returns>The collection containing the parsed HTTP form body.</returns>
        public async Task <Dictionary <string, StringValues> > ReadFormAsync(CancellationToken cancellationToken = default)
        {
            KeyValueAccumulator accumulator = default;

            while (true)
            {
                var readResult = await _pipeReader.ReadAsync(cancellationToken);

                var buffer = readResult.Buffer;

                if (!buffer.IsEmpty)
                {
                    try
                    {
                        ParseFormValues(ref buffer, ref accumulator, readResult.IsCompleted);
                    }
                    catch
                    {
                        _pipeReader.AdvanceTo(buffer.Start);
                        throw;
                    }
                }

                if (readResult.IsCompleted)
                {
                    _pipeReader.AdvanceTo(buffer.End);

                    if (!buffer.IsEmpty)
                    {
                        throw new InvalidOperationException("End of body before form was fully parsed.");
                    }
                    break;
                }

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

            return(accumulator.GetResults());
        }
Example #19
0
        /// <summary>
        /// Asynchronously reads to the end of the current System.IO.Pipelines.PipeReader.
        /// Requires a call to BodyReader.Advance after use ReadResult.Buffer
        /// </summary>
        /// <param name="pipeReader"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async ValueTask <Memory <byte> > ReadToEndAsync(this PipeReader pipeReader, CancellationToken cancellationToken = default)
        {
            while (true)
            {
                // Calling PipeReader.ReadAsync() Does not mean it reads the entire stream:
                //// 1、It Start reading the stream from PipeReader.InnerStream.Position
                //// 2. Length of First buffer to read = PipeReader._readHead'length = PipeReader.InnerStream.Length - PipeReader.InnerStream.Position.
                //////  If PipeReader._readHead'length is zero, it will read the stream until it ends
                var readResult = await pipeReader.ReadAsync(cancellationToken);

                var buffer = readResult.Buffer;

                if (readResult.IsCompleted)
                {
                    var newbuffer = new byte[buffer.Length];
                    buffer.CopyTo(newbuffer);
                    pipeReader.AdvanceTo(buffer.Start);
                    return(newbuffer.AsMemory());
                }
                pipeReader.AdvanceTo(buffer.Start, buffer.End);
            }
        }
Example #20
0
    // Reverted.  Recommend formatting for table   --------------------------------------
    #region snippet
    async ValueTask <Message?> ReadSingleMessageAsync(PipeReader reader,
                                                      CancellationToken cancellationToken = default)
    {
        while (true)
        {
            ReadResult result = await reader.ReadAsync(cancellationToken);

            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 (TryParseLines(ref buffer, out Message message))
                {
                    // A single message was successfully parsed so mark the start of the
                    // parsed buffer as consumed. TryParseLines trims the buffer to
                    // point to the data after the message was parsed.
                    consumed = buffer.Start;

                    // 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;

                    return(message);
                }

                // There's no more data to be processed.
                if (result.IsCompleted)
                {
                    if (buffer.Length > 0)
                    {
                        // The message is incomplete and there's no more data to process.
                        throw new InvalidDataException("Incomplete message.");
                    }

                    break;
                }
            }
            finally
            {
                reader.AdvanceTo(consumed, examined);
            }
        }

        return(null);
    }
Example #21
0
        /// <inheritdoc />
        protected override async Task ExecuteAsync(CancellationToken cancellationToken)
        {
            while (true)
            {
                Logger?.LogTrace("Start reading from pipe");
                var readResult = await _reader.ReadAsync(cancellationToken)
                                 .ConfigureAwait(false);

                var buffer   = readResult.Buffer;
                var position = buffer.Start;

                while (buffer.TryGet(ref position, out var memory))
                {
                    Logger?.LogTrace("Pass through of {numBytes} bytes", memory.Length);

                    // Don't use the cancellation token source from above. Otherwise
                    // data might be lost.
                    await _writer.WriteAsync(memory, CancellationToken.None)
                    .ConfigureAwait(false);

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

                _reader.AdvanceTo(buffer.End);

                await _writer.FlushAsync(CancellationToken.None)
                .ConfigureAwait(false);

                if (readResult.IsCanceled || readResult.IsCompleted)
                {
                    Logger?.LogTrace("Cancelled={cancelled} or completed={completed}", readResult.IsCanceled, readResult.IsCompleted);
                    break;
                }
            }
        }
        internal static async ValueTask <(bool isCancelled, bool isCompleted)> ParseLineAsync(PipeReader reader, Memory <string?> lineBuffer, bool isHeader = false, byte fieldDelimiter = 44)
        {
            int index      = 0;
            var readResult = await reader.ReadAsync();

            while (true)
            {
                if (readResult.IsCanceled)
                {
                    break;
                }

                var buffer = readResult.Buffer;
                var(isEol, eolPosition) = CsvParser.FindEol(buffer);

                if (readResult.IsCompleted && !isEol)
                {
                    isEol = true;
                }

                var recordBuffer = buffer.Slice(buffer.Start, eolPosition ?? buffer.End);

                ParseLine(ref recordBuffer, lineBuffer.Span, ref index, isEol, isHeader, fieldDelimiter);

                if (isEol && recordBuffer.IsEmpty)
                {
                    var advance = eolPosition is null ? buffer.End : buffer.GetPosition(1, eolPosition.Value);

                    reader.AdvanceTo(advance);
                    break;
                }

                reader.AdvanceTo(recordBuffer.Start, recordBuffer.End);
                readResult = await reader.ReadAsync();
            }

            return(readResult.IsCanceled, readResult.IsCompleted);
        }
        private async Task SendingPipeSendAsync(PipeReader reader)
        {
            var senderSocketLock = new AsyncLock();

            while (_active)
            {
                try {
                    var result = await reader.ReadAsync(_linkedToken);

                    if (result.IsCanceled)
                    {
                        break;
                    }
                    var sequence = result.Buffer;
                    if (!sequence.IsEmpty)
                    {
                        using (await senderSocketLock.LockAsync()) {
                            var bytesCount = await _socket.SendBuffersAsync(sequence, _linkedToken);

                            reader.AdvanceTo(sequence.End);
                            if (bytesCount < 0)
                            {
                                _localSource.Cancel(false);
                            }
                        }
                    }
                    if (_stopping)
                    {
                        _localSource.Cancel(false);
                    }
                    if (result.IsCompleted)
                    {
                        break;
                    }
                } catch (OperationCanceledException oce) {
                    reader.Complete(oce);
                    return;
                } catch (SocketException se) when(se.ErrorCode.In(10054, 104))
                {
                    _localSource.Cancel(false);
                    reader.Complete(se);
                    return;
                } catch (Exception e) {
                    _logger.LogError(e, "While sending bytes in the socket");
                    reader.Complete(e);
                    return;
                }
            }
            reader.Complete();
        }
Example #24
0
        bool TryReadLine(ref ReadOnlySequence <byte> buffer, out ReadOnlySequence <byte> line)
        {
            SequencePosition?position = buffer.PositionOf((byte)'\n');

            if (position == null)
            {
                line = default;
                return(false);
            }
            line = buffer.Slice(0, position.Value);
            _reader.AdvanceTo(position.Value);
            buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
            return(true);
        }
Example #25
0
        async Task SendAsync()
        {
            PipeReader reader = _requestPipe.Reader;

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

                    ReadOnlySequence <byte> buffer = result.Buffer;

                    try
                    {
                        if (!buffer.IsEmpty)
                        {
                            for (SequencePosition position = buffer.Start; buffer.TryGet(ref position, out ReadOnlyMemory <byte> segment);)
                            {
                                if (Log != null && Log.Switch.ShouldTrace(TraceEventType.Verbose))
                                {
                                    string data = Encodings.Utf8.ToString(segment.Span);
                                    if (!string.IsNullOrWhiteSpace(data))
                                    {
                                        Log.TraceInformation(data);
                                    }
                                }

                                await WriteToSocketAsync(segment).ConfigureAwait(false);
                            }
                        }
                        else if (result.IsCompleted)
                        {
                            break;
                        }
                    }
                    finally
                    {
                        reader.AdvanceTo(buffer.End);
                    }
                }
            }
            catch (Exception e)
            {
                Log.TraceEvent(TraceEventType.Error, 0, e.ToString());
            }
            finally
            {
                reader.Complete();
            }
        }
Example #26
0
        protected async Task ReadPipeAsync(PipeReader reader)
        {
            while (true)
            {
                var result = await reader.ReadAsync();

                var buffer = result.Buffer;

                SequencePosition consumed = buffer.Start;
                SequencePosition examined = buffer.End;

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

                    var completed = result.IsCompleted;

                    while (true)
                    {
                        var package = ReaderBuffer(buffer, out consumed, out examined);

                        if (package != null)
                        {
                            await OnPackageReceived(package);
                        }

                        if (examined.Equals(buffer.End))
                        {
                            break;
                        }

                        buffer = buffer.Slice(examined);
                    }

                    if (completed)
                    {
                        break;
                    }
                }
                finally
                {
                    reader.AdvanceTo(consumed, examined);
                }
            }

            reader.Complete();
        }
Example #27
0
        public static async Task ReceiveHandshakeRequestAsync(PipeReader input)
        {
            using (var cts = new CancellationTokenSource(DefaultHandshakeTimeout))
            {
                while (true)
                {
                    var result = await input.ReadAsync(cts.Token);

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

                    try
                    {
                        if (!buffer.IsEmpty)
                        {
                            if (ServiceProtocol.TryParseMessage(ref buffer, out var message))
                            {
                                consumed = buffer.Start;
                                examined = consumed;

                                if (!(message is HandshakeRequestMessage handshakeRequest))
                                {
                                    throw new InvalidDataException(
                                              $"{message.GetType().Name} received when waiting for handshake request.");
                                }

                                if (handshakeRequest.Version != ServiceProtocol.Version)
                                {
                                    throw new InvalidDataException("Protocol version not supported.");
                                }

                                break;
                            }
                        }

                        if (result.IsCompleted)
                        {
                            // Not enough data, and we won't be getting any more data.
                            throw new InvalidOperationException(
                                      "Service connectioned disconnected before sending a handshake request");
                        }
                    }
                    finally
                    {
                        input.AdvanceTo(consumed, examined);
                    }
                }
            }
        }
Example #28
0
File: Zmq.cs Project: kzbsv/KzjHack
        static async Task ReadBlockHashPipeAsync(PipeReader reader)
        {
            // Read Bitcoin block ids from a PipeReader
            while (_zmqRunning)
            {
                var rr = await reader.ReadAsync();

                var buf     = rr.Buffer;
                var blockId = new KzUInt256();
                buf.ToSpan().CopyTo(blockId.Span);
                reader.AdvanceTo(buf.GetPosition(32));
                KzH.WriteLine($"BlockId parsed id={blockId.ToHex()}");
            }
        }
Example #29
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");
        }
        internal override async ValueTask <RawResult> Process()
        {
            var firstChar = await ReadByte();

            PipeReader.AdvanceTo(ReadResult.Buffer.Start, ReadResult.Buffer.Slice(1).Start);

            if (firstChar == ByteConstants.Dash)
            {
                var line = await ReadLine();

                var redisResponse = line.AsString();
                PipeReader.AdvanceTo(line.End);
                throw new RedisFailedCommandException(redisResponse, RedisClient.LastCommand);
            }

            object result;

            if (firstChar == ByteConstants.Asterix)
            {
                var processor = RedisClient.ArrayResultProcessor;
                processor.SetMembers(RedisClient, PipeReader, ReadResult, CancellationToken);
                result = await processor.Process();
            }
            else if (firstChar == ByteConstants.Plus)
            {
                var processor = RedisClient.WordResultProcessor;
                processor.SetMembers(RedisClient, PipeReader, ReadResult, CancellationToken);
                result = await processor.Process();
            }
            else if (firstChar == ByteConstants.Colon)
            {
                var processor = RedisClient.IntegerResultProcessor;
                processor.SetMembers(RedisClient, PipeReader, ReadResult, CancellationToken);
                result = await processor.Process();
            }
            else if (firstChar == ByteConstants.Dollar)
            {
                var processor = RedisClient.DataResultProcessor;
                processor.SetMembers(RedisClient, PipeReader, ReadResult, CancellationToken);
                result = await processor.Process();
            }
            else
            {
                var processor = RedisClient.EmptyResultProcessor;
                processor.SetMembers(RedisClient, PipeReader, ReadResult, CancellationToken);
                result = await processor.Process();
            }

            return(new RawResult(result));
        }