// For use with System.IO.Pipelines // Decrypt packets directly from underlying data stream without needing to buffer public int TryDecrypt(ReadOnlySequence <byte> buffer, out PoolPacketReader packet) { if (buffer.Length < HEADER_SIZE) { packet = null; return(0); } SequenceReader <byte> reader = new(buffer); reader.TryReadLittleEndian(out short encSeq); reader.TryReadLittleEndian(out int packetSize); int rawPacketSize = HEADER_SIZE + packetSize; if (buffer.Length < rawPacketSize) { packet = null; return(0); } // Only decode sequence once we know there is sufficient data because it mutates IV short decSeq = DecodeSeqBase(encSeq); if (decSeq != Cipher.Version) { throw new ArgumentException($"Packet has invalid sequence header: {decSeq}"); } byte[] data = ArrayProvider.Rent(packetSize); buffer.Slice(HEADER_SIZE, packetSize).CopyTo(data); foreach (ICrypter crypter in DecryptSeq) { crypter.Decrypt(data, 0, packetSize); } packet = new(ArrayProvider, data, packetSize); return(rawPacketSize); }