public static byte[] Hash256(byte[] message) { var hashBuffer = new byte[HashHelpers.Hash256Size]; if (HashHelpers.TryHash256(message, hashBuffer)) { return(hashBuffer); } throw new ArgumentException(nameof(message)); }
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"); } } }