private bool TryParseLine(int maxLength, out string?line) { maxLength += NewLine.Length; var data = _receiveBuffer.AsReadOnlySequence(); bool lineExpected = data.Length >= maxLength; if (lineExpected) { // Don't look at more than maxLength data. data = data.Slice(0, maxLength); } var reader = new SequenceReader <byte>(data); if (reader.TryReadTo(out ReadOnlySequence <byte> lineSequence, NewLine)) { try { line = s_utf8Encoding.GetString(lineSequence.ToArray()); } catch (DecoderFallbackException) { ThrowHelper.ThrowProtocolInvalidUtf8(); throw; } _receiveBuffer.Remove(reader.Consumed); return(true); } if (lineExpected) { throw new ProtocolException($"Line delimited by '\\r\\n' exceeds {maxLength}"); } line = null; return(false); }
public SequenceReader(ReadOnlySequence <byte> data) { _reader = new SequenceReader <byte>(data); }
public bool TryDecodePacket(Sequence receiveBuffer, int maxLength, out Packet packet) { // Binary Packet Protocol: https://tools.ietf.org/html/rfc4253#section-6. /* * uint32 packet_length * byte padding_length * byte[n1] payload; n1 = packet_length - padding_length - 1 * byte[n2] random padding; n2 = padding_length * byte[m] mac (Message Authentication Code - MAC); m = mac_length */ if (_decodedPacket == null) { _decodedPacket = _sequencePool.RentSequence(); } // We can't decode past the packet, because the mac is not encrypted. // We need to know the packet length to know how much we can decrypt. while (_decodedPacket.Length < 4 && receiveBuffer.Length >= _decode.BlockSize) { _decode.Transform(receiveBuffer.AsReadOnlySequence().Slice(0, _decode.BlockSize), _decodedPacket); receiveBuffer.Remove(_decode.BlockSize); } var decodedReader = new SequenceReader(_decodedPacket); if (decodedReader.Length >= 4) { // Read the packet length. uint packet_length = decodedReader.ReadUInt32(); if (packet_length > maxLength) { ThrowHelper.ThrowProtocolPacketTooLong(); } // Decode the entire packet. uint concatenated_length = 4 + packet_length; // TODO: verify contatenated_length is a multiple of the cipher block size or 8, whichever is larger. long remaining = concatenated_length - decodedReader.Length; if (remaining > 0 && receiveBuffer.Length >= remaining) { _decode.Transform(receiveBuffer.AsReadOnlySequence().Slice(0, remaining), _decodedPacket); receiveBuffer.Remove(remaining); remaining = 0; } if (remaining == 0) { if (_decodedPacket.Length != concatenated_length) { ThrowHelper.ThrowInvalidOperation("Complete packet expected."); } // TODO: verify mac receiveBuffer.Remove(_mac.HashSize); packet = new Packet(_decodedPacket); _decodedPacket = null; return(true); } } packet = new Packet(null); return(false); }