/// <summary> /// Parses <see cref="TableMapEvent"/> from the buffer. /// </summary> public IBinlogEvent ParseEvent(EventHeader header, ref PacketReader reader) { var tableId = reader.ReadLongLittleEndian(6); // Reserved bytes and database name length reader.Advance(3); var databaseName = reader.ReadNullTerminatedString(); // Table name length reader.Advance(1); var tableName = reader.ReadNullTerminatedString(); var columnsNumber = (int)reader.ReadLengthEncodedNumber(); var columnTypes = reader.ReadByteArraySlow(columnsNumber); var metadataLength = (int)reader.ReadLengthEncodedNumber(); var metadata = ParseMetadata(ref reader, columnTypes); var nullBitmap = reader.ReadBitmapLittleEndian(columnsNumber); TableMetadata tableMetadata = null; if (!reader.IsEmpty()) { // Table metadata is supported in MySQL 5.6+ and MariaDB 10.5+. tableMetadata = new TableMetadata(ref reader, columnTypes); } return(new TableMapEvent(header, tableId, databaseName, tableName, columnTypes, metadata, nullBitmap, tableMetadata)); }
public void Test_Advance_ReturnsIsEmpty() { var payload = new byte[] { 76, 111, 114, 101, 109, 32, 105, 112, 115, 117, 109 }; var reader = new PacketReader(payload); reader.Advance(5); Assert.False(reader.IsEmpty()); Assert.Equal(5, reader.Consumed); reader.Advance(6); Assert.True(reader.IsEmpty()); Assert.Equal(11, reader.Consumed); }
/// <summary> /// Parses <see cref="RowsQueryEvent"/> from the buffer. /// </summary> public IBinlogEvent ParseEvent(EventHeader header, ref PacketReader reader) { reader.Advance(1); var query = reader.ReadStringToEndOfFile(); return(new RowsQueryEvent(header, query)); }
/// <summary> /// Skips empty holes made by partial updates (MySQL 8.0.16+) /// </summary> private void Advance(ref PacketReader reader, int startIndex, int offset) { int holeSize = offset - (reader.Consumed - startIndex); if (holeSize > 0) { reader.Advance(holeSize); } }
/// <summary> /// Parses <see cref="FormatDescriptionEvent"/> from the buffer. /// </summary> public IBinlogEvent ParseEvent(EventHeader header, ref PacketReader reader) { var binlogVersion = reader.ReadInt16LittleEndian(); var serverVersion = reader.ReadString(50).Trim((char)0); // Redundant timestamp & header length which is always 19 reader.Advance(5); // Get size of the event payload to determine beginning of the checksum part reader.Advance((int)EventType.FORMAT_DESCRIPTION_EVENT - 1); var eventPayloadLength = reader.ReadByte(); var checksumType = ChecksumType.NONE; if (eventPayloadLength != header.EventLength - EventConstants.HeaderSize) { reader.Advance(eventPayloadLength - (EventTypesOffset + (int)EventType.FORMAT_DESCRIPTION_EVENT)); checksumType = (ChecksumType)reader.ReadByte(); } return(new FormatDescriptionEvent(header, binlogVersion, serverVersion, checksumType)); }
/// <summary> /// Parses the header in a rows event. /// </summary> protected (long tableId, int flags, int columnsNumber) ParseHeader(ref PacketReader reader) { long tableId = reader.ReadLongLittleEndian(6); int flags = reader.ReadUInt16LittleEndian(); // Ignore extra data from newer versions of events if (RowsEventVersion == 2) { int extraDataLength = reader.ReadUInt16LittleEndian(); reader.Advance(extraDataLength - 2); } var columnsNumber = (int)reader.ReadLengthEncodedNumber(); return(tableId, flags, columnsNumber); }
/// <summary> /// Parses <see cref="QueryEvent"/> from the buffer. /// </summary> public IBinlogEvent ParseEvent(EventHeader header, ref PacketReader reader) { long threadId = (uint)reader.ReadInt32LittleEndian(); long duration = (uint)reader.ReadInt32LittleEndian(); // DatabaseName length is null terminated reader.Advance(1); var errorCode = reader.ReadInt16LittleEndian(); var statusVariableLength = reader.ReadInt16LittleEndian(); var statusVariables = reader.ReadByteArraySlow(statusVariableLength); var databaseName = reader.ReadNullTerminatedString(); var sqlStatement = reader.ReadStringToEndOfFile(); return(new QueryEvent(header, threadId, duration, errorCode, statusVariables, databaseName, sqlStatement)); }
private void ParseArrayOrObject(ref PacketReader reader, ValueType valueType, bool small, bool isObject) { int startIndex = reader.Consumed; int valueSize = small ? 2 : 4; int elementsNumber = ReadJsonSize(ref reader, small); int bytesNumber = ReadJsonSize(ref reader, small); // Key entries int[] keyOffset = isObject ? new int[elementsNumber] : null; int[] keyLength = isObject ? new int[elementsNumber] : null; if (isObject) { for (int i = 0; i < elementsNumber; i++) { keyOffset[i] = ReadJsonSize(ref reader, small); keyLength[i] = reader.ReadUInt16LittleEndian(); } } // Value entries var entries = new ValueEntry[elementsNumber]; for (int i = 0; i < elementsNumber; i++) { ValueType type = ReadValueType(ref reader); if (type == ValueType.LITERAL) { entries[i] = ValueEntry.FromInlined(type, ReadLiteral(ref reader)); reader.Advance(valueSize - 1); } else if (type == ValueType.INT16) { entries[i] = ValueEntry.FromInlined(type, (Int16)reader.ReadUInt16LittleEndian()); reader.Advance(valueSize - 2); } else if (type == ValueType.UINT16) { entries[i] = ValueEntry.FromInlined(type, (UInt16)reader.ReadUInt16LittleEndian()); reader.Advance(valueSize - 2); } else if (type == ValueType.INT32 && !small) { entries[i] = ValueEntry.FromInlined(type, (Int32)reader.ReadUInt32LittleEndian()); } else if (type == ValueType.UINT32 && !small) { entries[i] = ValueEntry.FromInlined(type, (UInt32)reader.ReadUInt32LittleEndian()); } else { int offset = ReadJsonSize(ref reader, small); if (offset >= bytesNumber) { throw new FormatException("The offset in JSON value was too long"); } entries[i] = ValueEntry.FromOffset(type, offset); } } // Key rows string[] keys = null; if (isObject) { keys = new string[elementsNumber]; for (int i = 0; i < elementsNumber; i++) { // 1 - Remove a hole between keys Advance(ref reader, startIndex, keyOffset[i]); keys[i] = reader.ReadString(keyLength[i]) ?? string.Empty /* JSON can have empty keys */; } } // Value rows if (isObject) { _writer.WriteStartObject(); } else { _writer.WriteStartArray(); } for (int i = 0; i < elementsNumber; i++) { if (isObject) { _writer.WriteKey(keys[i]); } ValueEntry entry = entries[i]; if (!entry.Inlined) { // 2 - Remove a hole between values Advance(ref reader, startIndex, entry.Offset); ParseNode(ref reader, entry.Type); } else if (entry.Value == null) { _writer.WriteNull(); } else if (entry.Type == ValueType.LITERAL) { _writer.WriteValue((bool)entry.Value); } else if (entry.Type == ValueType.INT16) { _writer.WriteValue((Int16)entry.Value); } else if (entry.Type == ValueType.UINT16) { _writer.WriteValue((UInt16)entry.Value); } else if (entry.Type == ValueType.INT32) { _writer.WriteValue((Int32)entry.Value); } else if (entry.Type == ValueType.UINT32) { _writer.WriteValue((UInt32)entry.Value); } } if (isObject) { _writer.WriteEndObject(); } else { _writer.WriteEndArray(); } // 3 - Remove a hole from the end Advance(ref reader, startIndex, bytesNumber); }
public static RSAParameters DecodePublicKey(byte[] x509Key) { using var memoryOwner = new MemoryOwner(new ReadOnlySequence <byte>(x509Key)); var reader = new PacketReader(memoryOwner.Memory.Span); var twobytes = reader.ReadInt16LittleEndian(); var skipBytes = twobytes switch { 0x8130 => 1, 0x8230 => 2, _ => throw new FormatException() }; reader.Advance(skipBytes); var sequence = reader.ReadByteArraySlow(15); if (!sequence.SequenceEqual(OidSequence)) { throw new FormatException("Sequence is not OID"); } twobytes = reader.ReadInt16LittleEndian(); skipBytes = twobytes switch { 0x8103 => 1, 0x8203 => 2, _ => throw new FormatException() }; reader.Advance(skipBytes); if (reader.ReadByte() != 0x00) { throw new FormatException(); // Null byte } twobytes = reader.ReadInt16LittleEndian(); skipBytes = twobytes switch { 0x8130 => 1, 0x8230 => 2, _ => throw new FormatException() }; reader.Advance(skipBytes); // Read modulus size twobytes = reader.ReadInt16LittleEndian(); int modulusSize = twobytes switch { 0x8102 => reader.ReadByte(), 0x8202 => reader.ReadInt16BigEndian(), _ => throw new FormatException() }; byte[] modulus = reader.ReadByteArraySlow(modulusSize); if (modulus[0] == 0x00) { modulus = modulus.Skip(1).ToArray(); } if (reader.ReadByte() != 0x02) { throw new FormatException(); } var exponentSize = reader.ReadByte(); byte[] exponent = reader.ReadByteArraySlow(exponentSize); return(new RSAParameters { Modulus = modulus, Exponent = exponent }); } } }