Пример #1
0
        public static byte[] Hash256(byte[] message)
        {
            var hashBuffer = new byte[HashHelpers.Hash256Size];

            if (HashHelpers.TryHash256(message, hashBuffer))
            {
                return(hashBuffer);
            }

            throw new ArgumentException(nameof(message));
        }
Пример #2
0
        public static async ValueTask <Message?> ReceiveMessage(PipeReader reader, EndPoint address, uint magic, ILogger log, CancellationToken token = default)
        {
            while (true)
            {
                var readResult = await reader.ReadAsync(token).ConfigureAwait(false);

                var buffer = readResult.Buffer;
                log.LogDebug("read {length} bytes from pipe {address} {IsCompleted} {IsCanceled} ",
                             readResult.Buffer.Length, address, readResult.IsCompleted, readResult.IsCanceled);
                SequencePosition consumed = buffer.Start;
                SequencePosition examined = buffer.End;

                try
                {
                    if (readResult.IsCanceled)
                    {
                        throw new OperationCanceledException();
                    }

                    var messageRead = TryReadMessage(ref buffer, out var message, out var advance);

                    if (advance)
                    {
                        consumed = buffer.End;
                        examined = consumed;
                    }

                    if (messageRead)
                    {
                        Debug.Assert(message != null);
                        return(message);
                    }

                    if (readResult.IsCompleted)
                    {
                        if (buffer.Length > 0)
                        {
                            throw new InvalidDataException("Incomplete message.");
                        }

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

            bool TryReadMessage(ref ReadOnlySequence <byte> _buffer, out Message?_message, out bool _advance)
            {
                _message = null;
                _advance = false;

                if (_buffer.Length < MessageHeader.Size)
                {
                    log.LogDebug("Haven't received enough data to read the message header {bufferLength} {address}", _buffer.Length, address);
                    return(false);
                }

                if (!MessageHeader.TryRead(_buffer, out var header))
                {
                    throw new InvalidDataException("MessageHeader could not be parsed");
                }
                log.LogDebug("Received {command} message header {magic} {length} {checksum} {address}",
                             header.Command, header.Magic, header.Length, header.Checksum, address);

                var messageLength = MessageHeader.Size + header.Length;

                if (_buffer.Length < messageLength)
                {
                    log.LogDebug("Haven't received enough data to read the message payload {bufferNeeded} {bufferLength} {address}",
                                 messageLength, _buffer.Length, address);
                    return(false);
                }

                _buffer  = _buffer.Slice(0, messageLength);
                _advance = true;
                if (header.Magic != magic)
                {
                    // ignore messages sent with the wrong magic value
                    log.LogWarning("Ignoring message with incorrect magic {expected} {actual} {address}", magic, header.Magic, address);
                    return(false);
                }

                Span <byte> hashBuffer = stackalloc byte[UInt256.Size];

                HashHelpers.TryHash256(_buffer.Slice(MessageHeader.Size), hashBuffer);
                var checksum = BinaryPrimitives.ReadUInt32LittleEndian(hashBuffer.Slice(0, sizeof(uint)));

                if (header.Checksum != checksum)
                {
                    // ignore messages sent with invalid checksum
                    log.LogWarning("Ignoring message with incorrect checksum {expected} {actual} {address}", checksum, header.Checksum, address);
                    return(false);
                }

                if (Message.TryRead(_buffer, header, out _message))
                {
                    log.LogDebug("Receive {message} {address}", _message.GetType().Name, address);
                    return(true);
                }
                else
                {
                    throw new InvalidDataException($"'{header.Command}' Message could not be parsed");
                }
            }
        }