From: js6pak Date: Mon, 5 Jul 2021 00:19:28 +0000 (+0200) Subject: Merge remote-tracking branch 'upstream/master' X-Git-Tag: 1.0.0~2 X-Git-Url: https://git.deb.at/?a=commitdiff_plain;h=6bc1d7374e04a9c1efb5b898239dcd486962eac2;p=rhonda%2Fimpostor.hazel.git Merge remote-tracking branch 'upstream/master' --- 6bc1d7374e04a9c1efb5b898239dcd486962eac2 diff --cc Hazel/Crypto/Sha256Stream.cs index 0000000,0c23f89..df05ca1 mode 000000,100644..100644 --- a/Hazel/Crypto/Sha256Stream.cs +++ b/Hazel/Crypto/Sha256Stream.cs @@@ -1,0 -1,79 +1,79 @@@ + using System; + using System.Security.Cryptography; + -namespace Hazel.Crypto ++namespace Impostor.Hazel.Crypto + { + /// + /// Streams data into a SHA256 digest + /// + public class Sha256Stream : IDisposable + { + /// + /// Size of the SHA256 digest in bytes + /// + public const int DigestSize = 32; + + private SHA256 hash = SHA256.Create(); + + struct EmptyArray + { + public static readonly byte[] Value = new byte[0]; + } + + /// + /// Create a new instance of a SHA256 stream + /// + public Sha256Stream() + { + } + + /// + /// Release resources associated with the stream + /// + public void Dispose() + { + this.hash?.Dispose(); + this.hash = null; + + GC.SuppressFinalize(this); + } + + /// + /// Reset the stream to its initial state + /// + public void Reset() + { + this.hash?.Dispose(); + this.hash = SHA256.Create(); + } + + /// + /// Add data to the stream + /// + public void AddData(ByteSpan data) + { + while (data.Length > 0) + { + int offset = this.hash.TransformBlock(data.GetUnderlyingArray(), data.Offset, data.Length, null, 0); + data = data.Slice(offset); + } + } + + /// + /// Calculate the final hash of the stream data + /// + /// + /// Target span to which the hash will be written + /// + public void CalculateHash(ByteSpan output) + { + if (output.Length != DigestSize) + { + throw new ArgumentException($"Expected a span of {DigestSize} bytes. Got a span of {output.Length} bytes", nameof(output)); + } + + this.hash.TransformFinalBlock(EmptyArray.Value, 0, 0); + new ByteSpan(this.hash.Hash).CopyTo(output); + } + } + } diff --cc Hazel/Dtls/DtlsConnectionListener.cs index c3b6cce,c6bf31d..5242758 --- a/Hazel/Dtls/DtlsConnectionListener.cs +++ b/Hazel/Dtls/DtlsConnectionListener.cs @@@ -2,9 -2,7 +2,8 @@@ using System using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; - using System.IO; using System.Net; +using System.Net.Sockets; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Threading; diff --cc Hazel/MessageReader.cs index 6e2a555,4e0cd2a..03b0a99 --- a/Hazel/MessageReader.cs +++ b/Hazel/MessageReader.cs @@@ -1,105 -1,235 +1,110 @@@ using System; -using System.IO; -using System.Linq; +using System.Buffers.Binary; +using System.Numerics; using System.Runtime.CompilerServices; using System.Text; - -namespace Hazel +using Impostor.Api; +using Impostor.Api.Games; +using Impostor.Api.Net.Inner; +using Impostor.Api.Net.Messages; +using Impostor.Api.Unity; +using Microsoft.Extensions.ObjectPool; + +namespace Impostor.Hazel { - public class MessageReader : IRecyclable + public class MessageReader : IMessageReader { - public static readonly ObjectPool ReaderPool = new ObjectPool(() => new MessageReader()); - - public byte[] Buffer; - public byte Tag; + private readonly ObjectPool _pool; + private bool _inUse; - public int Length; - public int Offset; - - public int BytesRemaining => this.Length - this.Position; - - private MessageReader Parent; - - public int Position + internal MessageReader(ObjectPool pool) { - get { return this._position; } - set - { - this._position = value; - this.readHead = value + Offset; - } + _pool = pool; } - private int _position; - private int readHead; + public byte[] Buffer { get; private set; } - public static MessageReader GetSized(int minSize) - { - var output = ReaderPool.GetObject(); + public int Offset { get; internal set; } - if (output.Buffer == null || output.Buffer.Length < minSize) - { - output.Buffer = new byte[minSize]; - } - else - { - Array.Clear(output.Buffer, 0, output.Buffer.Length); - } + public int Position { get; internal set; } - output.Offset = 0; - output.Position = 0; - output.Tag = byte.MaxValue; - return output; - } - - public static MessageReader Get(byte[] buffer) - { - var output = ReaderPool.GetObject(); - - output.Buffer = buffer; - output.Offset = 0; - output.Position = 0; - output.Length = buffer.Length; - output.Tag = byte.MaxValue; - - return output; - } - - public static MessageReader CopyMessageIntoParent(MessageReader source) - { - var output = MessageReader.GetSized(source.Length + 3); - System.Buffer.BlockCopy(source.Buffer, source.Offset - 3, output.Buffer, 0, source.Length + 3); + public int Length { get; internal set; } + + public int BytesRemaining => this.Length - this.Position; - output.Offset = 0; - output.Position = 0; - output.Length = source.Length + 3; + public byte Tag { get; private set; } - return output; - } + public MessageReader Parent { get; private set; } - public static MessageReader Get(MessageReader source) + private int ReadPosition => Offset + Position; + public void Update(byte[] buffer, int offset = 0, int position = 0, int? length = null, byte tag = byte.MaxValue, MessageReader parent = null) { - var output = MessageReader.GetSized(source.Buffer.Length); - System.Buffer.BlockCopy(source.Buffer, 0, output.Buffer, 0, source.Buffer.Length); - - output.Offset = source.Offset; - - output._position = source._position; - output.readHead = source.readHead; - - output.Length = source.Length; - output.Tag = source.Tag; - - return output; + _inUse = true; + + Buffer = buffer; + Offset = offset; + Position = position; + Length = length ?? buffer.Length; + Tag = tag; + Parent = parent; } - public static MessageReader Get(byte[] buffer, int offset) + internal void Reset() { - // Ensure there is at least a header - if (offset + 3 > buffer.Length) return null; - - var output = ReaderPool.GetObject(); - - output.Buffer = buffer; - output.Offset = offset; - output.Position = 0; - - output.Length = output.ReadUInt16(); - output.Tag = output.ReadByte(); - - output.Offset += 3; - output.Position = 0; - - return output; + _inUse = false; + + Tag = byte.MaxValue; + Buffer = null; + Offset = 0; + Position = 0; + Length = 0; + Parent = null; } - /// - /// Produces a MessageReader using the parent's buffer. This MessageReader should **NOT** be recycled. - /// - public MessageReader ReadMessage() + public IMessageReader ReadMessage() { - // Ensure there is at least a header - if (this.BytesRemaining < 3) throw new InvalidDataException($"ReadMessage header is longer than message length: 3 of {this.BytesRemaining}"); - - var output = new MessageReader(); - - output.Parent = this; - output.Buffer = this.Buffer; - output.Offset = this.readHead; - output.Position = 0; - - output.Length = output.ReadUInt16(); - output.Tag = output.ReadByte(); - - output.Offset += 3; - output.Position = 0; + var length = ReadUInt16(); + var tag = FastByte(); + var pos = ReadPosition; - if (this.BytesRemaining < output.Length + 3) throw new InvalidDataException($"Message Length at Position {this.readHead} is longer than message length: {output.Length + 3} of {this.BytesRemaining}"); + Position += length; - this.Position += output.Length + 3; - return output; + var reader = _pool.Get(); + reader.Update(Buffer, pos, 0, length, tag, this); + return reader; } - /// - /// Produces a MessageReader with a new buffer. This MessageReader should be recycled. - /// - public MessageReader ReadMessageAsNewBuffer() + public void RemoveMessage(IMessageReader message) { - if (this.BytesRemaining < 3) throw new InvalidDataException($"ReadMessage header is longer than message length: 3 of {this.BytesRemaining}"); - - var len = this.ReadUInt16(); - var tag = this.ReadByte(); + if (message.Buffer != Buffer) + { + throw new ImpostorProtocolException("Tried to remove message from a message that does not have the same buffer."); + } - if (this.BytesRemaining < len) throw new InvalidDataException($"Message Length at Position {this.readHead} is longer than message length: {len} of {this.BytesRemaining}"); + // Offset of where to start removing. + var offsetStart = message.Offset - 3; - var output = MessageReader.GetSized(len); + // Offset of where to end removing. + var offsetEnd = message.Offset + message.Length; - output.Parent = this; - Array.Copy(this.Buffer, this.readHead, output.Buffer, 0, len); + // The amount of bytes to copy over ourselves. + var lengthToCopy = message.Buffer.Length - offsetEnd; - output.Length = len; - output.Tag = tag; + System.Buffer.BlockCopy(Buffer, offsetEnd, Buffer, offsetStart, lengthToCopy); - this.Position += output.Length; - return output; + ((MessageReader) message).Parent.AdjustLength(message.Offset, message.Length + 3); } - public MessageWriter StartWriter() ++ public void InsertMessage(IMessageReader reader, IMessageWriter writer) + { - var output = new MessageWriter(this.Buffer); - output.Position = this.readHead; - return output; - } - - public void RemoveMessage(MessageReader reader) - { - var temp = MessageReader.GetSized(reader.Buffer.Length); - try - { - var headerOffset = reader.Offset - 3; - var endOfMessage = reader.Offset + reader.Length; - var len = reader.Buffer.Length - endOfMessage; - - Array.Copy(reader.Buffer, endOfMessage, temp.Buffer, 0, len); - Array.Copy(temp.Buffer, 0, this.Buffer, headerOffset, len); - - this.AdjustLength(reader.Offset, reader.Length + 3); - } - finally - { - temp.Recycle(); - } - } - - public void InsertMessage(MessageReader reader, MessageWriter writer) - { - var temp = MessageReader.GetSized(reader.Buffer.Length); - try - { - var headerOffset = reader.Offset - 3; - var startOfMessage = reader.Offset; - var len = reader.Buffer.Length - startOfMessage; - int writerOffset = 3; - switch (writer.SendOption) - { - case SendOption.Reliable: - writerOffset = 3; - break; - case SendOption.None: - writerOffset = 1; - break; - } - - //store the original buffer in temp - Array.Copy(reader.Buffer, headerOffset, temp.Buffer, 0, len); - - //put the contents of writer in at headerOffset - Array.Copy(writer.Buffer, writerOffset, this.Buffer, headerOffset, writer.Length-writerOffset); - - //put the original buffer in after that - Array.Copy(temp.Buffer, 0, this.Buffer, headerOffset + (writer.Length-writerOffset), len - writer.Length); - - this.AdjustLength(-1 * reader.Offset , -1 * (writer.Length - writerOffset)); - } - finally - { - temp.Recycle(); - } ++ throw new NotImplementedException(); + } + private void AdjustLength(int offset, int amount) { - if (this.readHead > offset) + this.Length -= amount; + + if (this.ReadPosition > offset) { this.Position -= amount; } @@@ -172,10 -309,48 +177,24 @@@ return output; } + public ulong ReadUInt64() + { - ulong output = (ulong)this.FastByte() - | (ulong)this.FastByte() << 8 - | (ulong)this.FastByte() << 16 - | (ulong)this.FastByte() << 24 - | (ulong)this.FastByte() << 32 - | (ulong)this.FastByte() << 40 - | (ulong)this.FastByte() << 48 - | (ulong)this.FastByte() << 56; - ++ var output = BinaryPrimitives.ReadUInt64LittleEndian(Buffer.AsSpan(ReadPosition)); ++ Position += sizeof(ulong); + return output; + } + + public long ReadInt64() + { - long output = (long)this.FastByte() - | (long)this.FastByte() << 8 - | (long)this.FastByte() << 16 - | (long)this.FastByte() << 24 - | (long)this.FastByte() << 32 - | (long)this.FastByte() << 40 - | (long)this.FastByte() << 48 - | (long)this.FastByte() << 56; - ++ var output = BinaryPrimitives.ReadInt64LittleEndian(Buffer.AsSpan(ReadPosition)); ++ Position += sizeof(long); + return output; + } + public unsafe float ReadSingle() { - float output = 0; - fixed (byte* bufPtr = &this.Buffer[this.readHead]) - { - byte* outPtr = (byte*)&output; - - *outPtr = *bufPtr; - *(outPtr + 1) = *(bufPtr + 1); - *(outPtr + 2) = *(bufPtr + 2); - *(outPtr + 3) = *(bufPtr + 3); - } - - this.Position += 4; + var output = BinaryPrimitives.ReadSingleLittleEndian(Buffer.AsSpan(ReadPosition)); + Position += sizeof(float); return output; }