using System; using System.Buffers; using System.Security.Cryptography; namespace ScreenConnect; public class BlockBufferWriteStream : BlockBufferStream { private CursorBuffer danglingUntransformedBuffer; private Proc bufferCycler; protected override ICryptoTransform CreateTransform(byte[] key, byte[] iv) { return Singleton.Instance.CreateEncryptor(key, iv); } protected override void OnBlockSizeChanged() { danglingUntransformedBuffer.CompletedCount.AssertEquals(0); danglingUntransformedBuffer = CursorBuffer.From(new byte[base.BlockSize]); } public int GetUnflushedByteCount() { return base.BufferCompletedCount + danglingUntransformedBuffer.CompletedCount; } public BlockBufferWriteStream(Proc bufferCycler) { this.bufferCycler = bufferCycler; } protected override void OnNeedsBufferCycled() { bufferCycler(this); } public override void Write(byte[] buffer, int offset, int count) { CursorBuffer sourceToAdvance = CursorBuffer.From(buffer, offset, count); if (danglingUntransformedBuffer.CompletedCount != 0) { CursorBuffer.Copy(ref sourceToAdvance, ref danglingUntransformedBuffer); if (danglingUntransformedBuffer.RemainingCount == 0) { DemandBufferCount(base.BlockSize); CursorBuffer.ResetToBeginning(ref danglingUntransformedBuffer); WriteAndTransform(ref danglingUntransformedBuffer, base.Transform); CursorBuffer.ResetToBeginning(ref danglingUntransformedBuffer); } } if (sourceToAdvance.RemainingCount != 0) { while (sourceToAdvance.RemainingCount >= base.BlockSize) { DemandBufferCount(base.BlockSize); WriteAndTransform(ref sourceToAdvance, base.Transform); } } if (sourceToAdvance.RemainingCount != 0) { CursorBuffer.Copy(ref sourceToAdvance, ref danglingUntransformedBuffer); } } public override void Flush() { danglingUntransformedBuffer.CompletedCount.AssertEquals(0); base.Flush(); } public void WriteZerosForFlush() { if (danglingUntransformedBuffer.CompletedCount > 0) { int remainingCount = danglingUntransformedBuffer.RemainingCount; using Extensions.ArrayPoolRental arrayPoolRental = ArrayPool.Shared.RentEx(remainingCount); Array.Clear(arrayPoolRental.RentedArray, 0, remainingCount); Write(arrayPoolRental.RentedArray, 0, remainingCount); } } public override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } }